Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / third_party / mbedtls / repo / library / chachapoly.c
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: 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
29 #if defined(MBEDTLS_CHACHAPOLY_C)
30
31 #include "mbedtls/chachapoly.h"
32 #include "mbedtls/platform_util.h"
33
34 #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
45 #if !defined(MBEDTLS_CHACHAPOLY_ALT)
46
47 /* 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
53 #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 )
57
58 /**
59  * \brief           Adds nul bytes to pad the AAD for Poly1305.
60  *
61  * \param ctx       The ChaCha20-Poly1305 context.
62  */
63 static int chachapoly_pad_aad( mbedtls_chachapoly_context *ctx )
64 {
65     uint32_t partial_block_len = (uint32_t) ( ctx->aad_len % 16U );
66     unsigned char zeroes[15];
67
68     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 ) );
76 }
77
78 /**
79  * \brief           Adds nul bytes to pad the ciphertext for Poly1305.
80  *
81  * \param ctx       The ChaCha20-Poly1305 context.
82  */
83 static int chachapoly_pad_ciphertext( mbedtls_chachapoly_context *ctx )
84 {
85     uint32_t partial_block_len = (uint32_t) ( ctx->ciphertext_len % 16U );
86     unsigned char zeroes[15];
87
88     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 ) );
95 }
96
97 void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx )
98 {
99     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;
107 }
108
109 void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx )
110 {
111     if( ctx == NULL )
112         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;
120 }
121
122 int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx,
123                                const unsigned char key[32] )
124 {
125     int ret;
126     CHACHAPOLY_VALIDATE_RET( ctx != NULL );
127     CHACHAPOLY_VALIDATE_RET( key != NULL );
128
129     ret = mbedtls_chacha20_setkey( &ctx->chacha20_ctx, key );
130
131     return( ret );
132 }
133
134 int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx,
135                                const unsigned char nonce[12],
136                                mbedtls_chachapoly_mode_t mode  )
137 {
138     int ret;
139     unsigned char poly1305_key[64];
140     CHACHAPOLY_VALIDATE_RET( ctx != NULL );
141     CHACHAPOLY_VALIDATE_RET( nonce != NULL );
142
143     /* Set counter = 0, will be update to 1 when generating Poly1305 key */
144     ret = mbedtls_chacha20_starts( &ctx->chacha20_ctx, nonce, 0U );
145     if( ret != 0 )
146         goto cleanup;
147
148     /* Generate the Poly1305 key by getting the ChaCha20 keystream output with
149      * counter = 0.  This is the same as encrypting a buffer of zeroes.
150      * Only the first 256-bits (32 bytes) of the key is used for Poly1305.
151      * The other 256 bits are discarded.
152      */
153     memset( poly1305_key, 0, sizeof( poly1305_key ) );
154     ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, sizeof( poly1305_key ),
155                                       poly1305_key, poly1305_key );
156     if( ret != 0 )
157         goto cleanup;
158
159     ret = mbedtls_poly1305_starts( &ctx->poly1305_ctx, poly1305_key );
160
161     if( ret == 0 )
162     {
163         ctx->aad_len        = 0U;
164         ctx->ciphertext_len = 0U;
165         ctx->state          = CHACHAPOLY_STATE_AAD;
166         ctx->mode           = mode;
167     }
168
169 cleanup:
170     mbedtls_platform_zeroize( poly1305_key, 64U );
171     return( ret );
172 }
173
174 int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx,
175                                    const unsigned char *aad,
176                                    size_t aad_len )
177 {
178     CHACHAPOLY_VALIDATE_RET( ctx != NULL );
179     CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL );
180
181     if( ctx->state != CHACHAPOLY_STATE_AAD )
182         return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
183
184     ctx->aad_len += aad_len;
185
186     return( mbedtls_poly1305_update( &ctx->poly1305_ctx, aad, aad_len ) );
187 }
188
189 int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx,
190                                size_t len,
191                                const unsigned char *input,
192                                unsigned char *output )
193 {
194     int ret;
195     CHACHAPOLY_VALIDATE_RET( ctx != NULL );
196     CHACHAPOLY_VALIDATE_RET( len == 0 || input != NULL );
197     CHACHAPOLY_VALIDATE_RET( len == 0 || output != NULL );
198
199     if( ( ctx->state != CHACHAPOLY_STATE_AAD ) &&
200         ( ctx->state != CHACHAPOLY_STATE_CIPHERTEXT ) )
201     {
202         return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
203     }
204
205     if( ctx->state == CHACHAPOLY_STATE_AAD )
206     {
207         ctx->state = CHACHAPOLY_STATE_CIPHERTEXT;
208
209         ret = chachapoly_pad_aad( ctx );
210         if( ret != 0 )
211             return( ret );
212     }
213
214     ctx->ciphertext_len += len;
215
216     if( ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT )
217     {
218         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 );
225     }
226     else /* DECRYPT */
227     {
228         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 );
235     }
236
237     return( 0 );
238 }
239
240 int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx,
241                                unsigned char mac[16] )
242 {
243     int ret;
244     unsigned char len_block[16];
245     CHACHAPOLY_VALIDATE_RET( ctx != NULL );
246     CHACHAPOLY_VALIDATE_RET( mac != NULL );
247
248     if( ctx->state == CHACHAPOLY_STATE_INIT )
249     {
250         return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE );
251     }
252
253     if( ctx->state == CHACHAPOLY_STATE_AAD )
254     {
255         ret = chachapoly_pad_aad( ctx );
256         if( ret != 0 )
257             return( ret );
258     }
259     else if( ctx->state == CHACHAPOLY_STATE_CIPHERTEXT )
260     {
261         ret = chachapoly_pad_ciphertext( ctx );
262         if( ret != 0 )
263             return( ret );
264     }
265
266     ctx->state = CHACHAPOLY_STATE_FINISHED;
267
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      */
271     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 );
287
288     ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, len_block, 16U );
289     if( ret != 0 )
290         return( ret );
291
292     ret = mbedtls_poly1305_finish( &ctx->poly1305_ctx, mac );
293
294     return( ret );
295 }
296
297 static 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] )
306 {
307     int ret;
308
309     ret = mbedtls_chachapoly_starts( ctx, nonce, mode );
310     if( ret != 0 )
311         goto cleanup;
312
313     ret = mbedtls_chachapoly_update_aad( ctx, aad, aad_len );
314     if( ret != 0 )
315         goto cleanup;
316
317     ret = mbedtls_chachapoly_update( ctx, length, input, output );
318     if( ret != 0 )
319         goto cleanup;
320
321     ret = mbedtls_chachapoly_finish( ctx, tag );
322
323 cleanup:
324     return( ret );
325 }
326
327 int 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 {
336     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
343     return( chachapoly_crypt_and_tag( ctx, MBEDTLS_CHACHAPOLY_ENCRYPT,
344                                       length, nonce, aad, aad_len,
345                                       input, output, tag ) );
346 }
347
348 int 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;
361     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 );
367
368     if( ( ret = chachapoly_crypt_and_tag( ctx,
369                         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     {
381         mbedtls_platform_zeroize( output, length );
382         return( MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED );
383     }
384
385     return( 0 );
386 }
387
388 #endif /* MBEDTLS_CHACHAPOLY_ALT */
389
390 #if defined(MBEDTLS_SELF_TEST)
391
392 static 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
402 static 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
410 static 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
418 static const size_t test_aad_len[1] =
419 {
420     12U
421 };
422
423 static 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
444 static 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
465 static const size_t test_input_len[1] =
466 {
467     114U
468 };
469
470 static 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
478 #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
491 int mbedtls_chachapoly_self_test( int verbose )
492 {
493     mbedtls_chachapoly_context ctx;
494     unsigned i;
495     int ret;
496     unsigned char output[200];
497     unsigned char mac[16];
498
499     for( i = 0U; i < 1U; i++ )
500     {
501         if( verbose != 0 )
502             mbedtls_printf( "  ChaCha20-Poly1305 test %u ", i );
503
504         mbedtls_chachapoly_init( &ctx );
505
506         ret = mbedtls_chachapoly_setkey( &ctx, test_key[i] );
507         ASSERT( 0 == ret, ( "setkey() error code: %i\n", ret ) );
508
509         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 );
517
518         ASSERT( 0 == ret, ( "crypt_and_tag() error code: %i\n", ret ) );
519
520         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" ) );
525
526         mbedtls_chachapoly_free( &ctx );
527
528         if( verbose != 0 )
529             mbedtls_printf( "passed\n" );
530     }
531
532     if( verbose != 0 )
533         mbedtls_printf( "\n" );
534
535     return( 0 );
536 }
537
538 #endif /* MBEDTLS_SELF_TEST */
539
540 #endif /* MBEDTLS_CHACHAPOLY_C */