Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: nRF51_Vdd TextLCD BME280
chachapoly.c
00001 /** 00002 * \file chachapoly.c 00003 * 00004 * \brief ChaCha20-Poly1305 AEAD construction based on RFC 7539. 00005 * 00006 * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved 00007 * SPDX-License-Identifier: Apache-2.0 00008 * 00009 * Licensed under the Apache License, Version 2.0 (the "License"); you may 00010 * not use this file except in compliance with the License. 00011 * You may obtain a copy of the License at 00012 * 00013 * http://www.apache.org/licenses/LICENSE-2.0 00014 * 00015 * Unless required by applicable law or agreed to in writing, software 00016 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00017 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00018 * See the License for the specific language governing permissions and 00019 * limitations under the License. 00020 * 00021 * This file is part of mbed TLS (https://tls.mbed.org) 00022 */ 00023 #if !defined(MBEDTLS_CONFIG_FILE) 00024 #include "mbedtls/config.h" 00025 #else 00026 #include MBEDTLS_CONFIG_FILE 00027 #endif 00028 00029 #if defined(MBEDTLS_CHACHAPOLY_C) 00030 00031 #include "mbedtls/chachapoly.h" 00032 #include "mbedtls/platform_util.h" 00033 00034 #include <string.h> 00035 00036 #if defined(MBEDTLS_SELF_TEST) 00037 #if defined(MBEDTLS_PLATFORM_C) 00038 #include "mbedtls/platform.h" 00039 #else 00040 #include <stdio.h> 00041 #define mbedtls_printf printf 00042 #endif /* MBEDTLS_PLATFORM_C */ 00043 #endif /* MBEDTLS_SELF_TEST */ 00044 00045 #if !defined(MBEDTLS_CHACHAPOLY_ALT) 00046 00047 #define CHACHAPOLY_STATE_INIT ( 0 ) 00048 #define CHACHAPOLY_STATE_AAD ( 1 ) 00049 #define CHACHAPOLY_STATE_CIPHERTEXT ( 2 ) /* Encrypting or decrypting */ 00050 #define CHACHAPOLY_STATE_FINISHED ( 3 ) 00051 00052 /** 00053 * \brief Adds nul bytes to pad the AAD for Poly1305. 00054 * 00055 * \param ctx The ChaCha20-Poly1305 context. 00056 */ 00057 static int chachapoly_pad_aad( mbedtls_chachapoly_context *ctx ) 00058 { 00059 uint32_t partial_block_len = (uint32_t) ( ctx->aad_len % 16U ); 00060 unsigned char zeroes[15]; 00061 00062 if( partial_block_len == 0U ) 00063 return( 0 ); 00064 00065 memset( zeroes, 0, sizeof( zeroes ) ); 00066 00067 return( mbedtls_poly1305_update( &ctx->poly1305_ctx, 00068 zeroes, 00069 16U - partial_block_len ) ); 00070 } 00071 00072 /** 00073 * \brief Adds nul bytes to pad the ciphertext for Poly1305. 00074 * 00075 * \param ctx The ChaCha20-Poly1305 context. 00076 */ 00077 static int chachapoly_pad_ciphertext( mbedtls_chachapoly_context *ctx ) 00078 { 00079 uint32_t partial_block_len = (uint32_t) ( ctx->ciphertext_len % 16U ); 00080 unsigned char zeroes[15]; 00081 00082 if( partial_block_len == 0U ) 00083 return( 0 ); 00084 00085 memset( zeroes, 0, sizeof( zeroes ) ); 00086 return( mbedtls_poly1305_update( &ctx->poly1305_ctx, 00087 zeroes, 00088 16U - partial_block_len ) ); 00089 } 00090 00091 void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx ) 00092 { 00093 if( ctx != NULL ) 00094 { 00095 mbedtls_chacha20_init( &ctx->chacha20_ctx ); 00096 mbedtls_poly1305_init( &ctx->poly1305_ctx ); 00097 ctx->aad_len = 0U; 00098 ctx->ciphertext_len = 0U; 00099 ctx->state = CHACHAPOLY_STATE_INIT; 00100 ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT; 00101 } 00102 } 00103 00104 void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx ) 00105 { 00106 if( ctx != NULL ) 00107 { 00108 mbedtls_chacha20_free( &ctx->chacha20_ctx ); 00109 mbedtls_poly1305_free( &ctx->poly1305_ctx ); 00110 ctx->aad_len = 0U; 00111 ctx->ciphertext_len = 0U; 00112 ctx->state = CHACHAPOLY_STATE_INIT; 00113 ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT; 00114 } 00115 } 00116 00117 int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx, 00118 const unsigned char key[32] ) 00119 { 00120 int ret; 00121 00122 if( ( ctx == NULL ) || ( key == NULL ) ) 00123 { 00124 return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); 00125 } 00126 00127 ret = mbedtls_chacha20_setkey( &ctx->chacha20_ctx, key ); 00128 00129 return( ret ); 00130 } 00131 00132 int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx, 00133 const unsigned char nonce[12], 00134 mbedtls_chachapoly_mode_t mode ) 00135 { 00136 int ret; 00137 unsigned char poly1305_key[64]; 00138 00139 if( ( ctx == NULL ) || ( nonce == NULL ) ) 00140 { 00141 return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); 00142 } 00143 00144 /* Set counter = 0, will be update to 1 when generating Poly1305 key */ 00145 ret = mbedtls_chacha20_starts( &ctx->chacha20_ctx, nonce, 0U ); 00146 if( ret != 0 ) 00147 goto cleanup; 00148 00149 /* Generate the Poly1305 key by getting the ChaCha20 keystream output with 00150 * counter = 0. This is the same as encrypting a buffer of zeroes. 00151 * Only the first 256-bits (32 bytes) of the key is used for Poly1305. 00152 * The other 256 bits are discarded. 00153 */ 00154 memset( poly1305_key, 0, sizeof( poly1305_key ) ); 00155 ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, sizeof( poly1305_key ), 00156 poly1305_key, poly1305_key ); 00157 if( ret != 0 ) 00158 goto cleanup; 00159 00160 ret = mbedtls_poly1305_starts( &ctx->poly1305_ctx, poly1305_key ); 00161 00162 if( ret == 0 ) 00163 { 00164 ctx->aad_len = 0U; 00165 ctx->ciphertext_len = 0U; 00166 ctx->state = CHACHAPOLY_STATE_AAD; 00167 ctx->mode = mode; 00168 } 00169 00170 cleanup: 00171 mbedtls_platform_zeroize( poly1305_key, 64U ); 00172 return( ret ); 00173 } 00174 00175 int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx, 00176 const unsigned char *aad, 00177 size_t aad_len ) 00178 { 00179 if( ctx == NULL ) 00180 { 00181 return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); 00182 } 00183 else if( ( aad_len > 0U ) && ( aad == NULL ) ) 00184 { 00185 /* aad pointer is allowed to be NULL if aad_len == 0 */ 00186 return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); 00187 } 00188 else if( ctx->state != CHACHAPOLY_STATE_AAD ) 00189 { 00190 return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE ); 00191 } 00192 00193 ctx->aad_len += aad_len; 00194 00195 return( mbedtls_poly1305_update( &ctx->poly1305_ctx, aad, aad_len ) ); 00196 } 00197 00198 int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx, 00199 size_t len, 00200 const unsigned char *input, 00201 unsigned char *output ) 00202 { 00203 int ret; 00204 00205 if( ctx == NULL ) 00206 { 00207 return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); 00208 } 00209 else if( ( len > 0U ) && ( ( input == NULL ) || ( output == NULL ) ) ) 00210 { 00211 /* input and output pointers are allowed to be NULL if len == 0 */ 00212 return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); 00213 } 00214 else if( ( ctx->state != CHACHAPOLY_STATE_AAD ) && 00215 ( ctx->state != CHACHAPOLY_STATE_CIPHERTEXT ) ) 00216 { 00217 return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE ); 00218 } 00219 00220 if( ctx->state == CHACHAPOLY_STATE_AAD ) 00221 { 00222 ctx->state = CHACHAPOLY_STATE_CIPHERTEXT; 00223 00224 ret = chachapoly_pad_aad( ctx ); 00225 if( ret != 0 ) 00226 return( ret ); 00227 } 00228 00229 ctx->ciphertext_len += len; 00230 00231 if( ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT ) 00232 { 00233 ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output ); 00234 if( ret != 0 ) 00235 return( ret ); 00236 00237 ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, output, len ); 00238 if( ret != 0 ) 00239 return( ret ); 00240 } 00241 else /* DECRYPT */ 00242 { 00243 ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, input, len ); 00244 if( ret != 0 ) 00245 return( ret ); 00246 00247 ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output ); 00248 if( ret != 0 ) 00249 return( ret ); 00250 } 00251 00252 return( 0 ); 00253 } 00254 00255 int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx, 00256 unsigned char mac[16] ) 00257 { 00258 int ret; 00259 unsigned char len_block[16]; 00260 00261 if( ( ctx == NULL ) || ( mac == NULL ) ) 00262 { 00263 return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); 00264 } 00265 else if( ctx->state == CHACHAPOLY_STATE_INIT ) 00266 { 00267 return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE ); 00268 } 00269 00270 if( ctx->state == CHACHAPOLY_STATE_AAD ) 00271 { 00272 ret = chachapoly_pad_aad( ctx ); 00273 if( ret != 0 ) 00274 return( ret ); 00275 } 00276 else if( ctx->state == CHACHAPOLY_STATE_CIPHERTEXT ) 00277 { 00278 ret = chachapoly_pad_ciphertext( ctx ); 00279 if( ret != 0 ) 00280 return( ret ); 00281 } 00282 00283 ctx->state = CHACHAPOLY_STATE_FINISHED; 00284 00285 /* The lengths of the AAD and ciphertext are processed by 00286 * Poly1305 as the final 128-bit block, encoded as little-endian integers. 00287 */ 00288 len_block[ 0] = (unsigned char)( ctx->aad_len ); 00289 len_block[ 1] = (unsigned char)( ctx->aad_len >> 8 ); 00290 len_block[ 2] = (unsigned char)( ctx->aad_len >> 16 ); 00291 len_block[ 3] = (unsigned char)( ctx->aad_len >> 24 ); 00292 len_block[ 4] = (unsigned char)( ctx->aad_len >> 32 ); 00293 len_block[ 5] = (unsigned char)( ctx->aad_len >> 40 ); 00294 len_block[ 6] = (unsigned char)( ctx->aad_len >> 48 ); 00295 len_block[ 7] = (unsigned char)( ctx->aad_len >> 56 ); 00296 len_block[ 8] = (unsigned char)( ctx->ciphertext_len ); 00297 len_block[ 9] = (unsigned char)( ctx->ciphertext_len >> 8 ); 00298 len_block[10] = (unsigned char)( ctx->ciphertext_len >> 16 ); 00299 len_block[11] = (unsigned char)( ctx->ciphertext_len >> 24 ); 00300 len_block[12] = (unsigned char)( ctx->ciphertext_len >> 32 ); 00301 len_block[13] = (unsigned char)( ctx->ciphertext_len >> 40 ); 00302 len_block[14] = (unsigned char)( ctx->ciphertext_len >> 48 ); 00303 len_block[15] = (unsigned char)( ctx->ciphertext_len >> 56 ); 00304 00305 ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, len_block, 16U ); 00306 if( ret != 0 ) 00307 return( ret ); 00308 00309 ret = mbedtls_poly1305_finish( &ctx->poly1305_ctx, mac ); 00310 00311 return( ret ); 00312 } 00313 00314 static int chachapoly_crypt_and_tag( mbedtls_chachapoly_context *ctx, 00315 mbedtls_chachapoly_mode_t mode, 00316 size_t length, 00317 const unsigned char nonce[12], 00318 const unsigned char *aad, 00319 size_t aad_len, 00320 const unsigned char *input, 00321 unsigned char *output, 00322 unsigned char tag[16] ) 00323 { 00324 int ret; 00325 00326 ret = mbedtls_chachapoly_starts( ctx, nonce, mode ); 00327 if( ret != 0 ) 00328 goto cleanup; 00329 00330 ret = mbedtls_chachapoly_update_aad( ctx, aad, aad_len ); 00331 if( ret != 0 ) 00332 goto cleanup; 00333 00334 ret = mbedtls_chachapoly_update( ctx, length, input, output ); 00335 if( ret != 0 ) 00336 goto cleanup; 00337 00338 ret = mbedtls_chachapoly_finish( ctx, tag ); 00339 00340 cleanup: 00341 return( ret ); 00342 } 00343 00344 int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx, 00345 size_t length, 00346 const unsigned char nonce[12], 00347 const unsigned char *aad, 00348 size_t aad_len, 00349 const unsigned char *input, 00350 unsigned char *output, 00351 unsigned char tag[16] ) 00352 { 00353 return( chachapoly_crypt_and_tag( ctx, MBEDTLS_CHACHAPOLY_ENCRYPT, 00354 length, nonce, aad, aad_len, 00355 input, output, tag ) ); 00356 } 00357 00358 int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx, 00359 size_t length, 00360 const unsigned char nonce[12], 00361 const unsigned char *aad, 00362 size_t aad_len, 00363 const unsigned char tag[16], 00364 const unsigned char *input, 00365 unsigned char *output ) 00366 { 00367 int ret; 00368 unsigned char check_tag[16]; 00369 size_t i; 00370 int diff; 00371 00372 if( tag == NULL ) 00373 return( MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ); 00374 00375 if( ( ret = chachapoly_crypt_and_tag( ctx, 00376 MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce, 00377 aad, aad_len, input, output, check_tag ) ) != 0 ) 00378 { 00379 return( ret ); 00380 } 00381 00382 /* Check tag in "constant-time" */ 00383 for( diff = 0, i = 0; i < sizeof( check_tag ); i++ ) 00384 diff |= tag[i] ^ check_tag[i]; 00385 00386 if( diff != 0 ) 00387 { 00388 mbedtls_platform_zeroize( output, length ); 00389 return( MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED ); 00390 } 00391 00392 return( 0 ); 00393 } 00394 00395 #endif /* MBEDTLS_CHACHAPOLY_ALT */ 00396 00397 #if defined(MBEDTLS_SELF_TEST) 00398 00399 static const unsigned char test_key[1][32] = 00400 { 00401 { 00402 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 00403 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 00404 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 00405 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f 00406 } 00407 }; 00408 00409 static const unsigned char test_nonce[1][12] = 00410 { 00411 { 00412 0x07, 0x00, 0x00, 0x00, /* 32-bit common part */ 00413 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 /* 64-bit IV */ 00414 } 00415 }; 00416 00417 static const unsigned char test_aad[1][12] = 00418 { 00419 { 00420 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3, 00421 0xc4, 0xc5, 0xc6, 0xc7 00422 } 00423 }; 00424 00425 static const size_t test_aad_len[1] = 00426 { 00427 12U 00428 }; 00429 00430 static const unsigned char test_input[1][114] = 00431 { 00432 { 00433 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61, 00434 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c, 00435 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 00436 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73, 00437 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39, 00438 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63, 00439 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66, 00440 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f, 00441 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, 00442 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20, 00443 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75, 00444 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73, 00445 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f, 00446 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69, 00447 0x74, 0x2e 00448 } 00449 }; 00450 00451 static const unsigned char test_output[1][114] = 00452 { 00453 { 00454 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb, 00455 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2, 00456 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe, 00457 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6, 00458 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12, 00459 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b, 00460 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29, 00461 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36, 00462 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c, 00463 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58, 00464 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94, 00465 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc, 00466 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d, 00467 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b, 00468 0x61, 0x16 00469 } 00470 }; 00471 00472 static const size_t test_input_len[1] = 00473 { 00474 114U 00475 }; 00476 00477 static const unsigned char test_mac[1][16] = 00478 { 00479 { 00480 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a, 00481 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91 00482 } 00483 }; 00484 00485 #define ASSERT( cond, args ) \ 00486 do \ 00487 { \ 00488 if( ! ( cond ) ) \ 00489 { \ 00490 if( verbose != 0 ) \ 00491 mbedtls_printf args; \ 00492 \ 00493 return( -1 ); \ 00494 } \ 00495 } \ 00496 while( 0 ) 00497 00498 int mbedtls_chachapoly_self_test( int verbose ) 00499 { 00500 mbedtls_chachapoly_context ctx; 00501 unsigned i; 00502 int ret; 00503 unsigned char output[200]; 00504 unsigned char mac[16]; 00505 00506 for( i = 0U; i < 1U; i++ ) 00507 { 00508 if( verbose != 0 ) 00509 mbedtls_printf( " ChaCha20-Poly1305 test %u ", i ); 00510 00511 mbedtls_chachapoly_init( &ctx ); 00512 00513 ret = mbedtls_chachapoly_setkey( &ctx, test_key[i] ); 00514 ASSERT( 0 == ret, ( "setkey() error code: %i\n", ret ) ); 00515 00516 ret = mbedtls_chachapoly_encrypt_and_tag( &ctx, 00517 test_input_len[i], 00518 test_nonce[i], 00519 test_aad[i], 00520 test_aad_len[i], 00521 test_input[i], 00522 output, 00523 mac ); 00524 00525 ASSERT( 0 == ret, ( "crypt_and_tag() error code: %i\n", ret ) ); 00526 00527 ASSERT( 0 == memcmp( output, test_output[i], test_input_len[i] ), 00528 ( "failure (wrong output)\n" ) ); 00529 00530 ASSERT( 0 == memcmp( mac, test_mac[i], 16U ), 00531 ( "failure (wrong MAC)\n" ) ); 00532 00533 mbedtls_chachapoly_free( &ctx ); 00534 00535 if( verbose != 0 ) 00536 mbedtls_printf( "passed\n" ); 00537 } 00538 00539 if( verbose != 0 ) 00540 mbedtls_printf( "\n" ); 00541 00542 return( 0 ); 00543 } 00544 00545 #endif /* MBEDTLS_SELF_TEST */ 00546 00547 #endif /* MBEDTLS_CHACHAPOLY_C */
Generated on Tue Jul 12 2022 15:15:41 by
