1 /** 2 * \file chacha20.c 3 * 4 * \brief ChaCha20 cipher. 5 * 6 * \author Daniel King <damaki.gh@gmail.com> 7 * 8 * Copyright The Mbed TLS Contributors 9 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 10 */ 11 12 #include "common.h" 13 14 #if defined(MBEDTLS_CHACHA20_C) 15 16 #include "mbedtls/chacha20.h" 17 #include "mbedtls/platform_util.h" 18 #include "mbedtls/error.h" 19 20 #include <stddef.h> 21 #include <string.h> 22 23 #include "mbedtls/platform.h" 24 25 #if !defined(MBEDTLS_CHACHA20_ALT) 26 27 #define ROTL32(value, amount) \ 28 ((uint32_t) ((value) << (amount)) | ((value) >> (32 - (amount)))) 29 30 #define CHACHA20_CTR_INDEX (12U) 31 32 #define CHACHA20_BLOCK_SIZE_BYTES (4U * 16U) 33 34 /** 35 * \brief ChaCha20 quarter round operation. 36 * 37 * The quarter round is defined as follows (from RFC 7539): 38 * 1. a += b; d ^= a; d <<<= 16; 39 * 2. c += d; b ^= c; b <<<= 12; 40 * 3. a += b; d ^= a; d <<<= 8; 41 * 4. c += d; b ^= c; b <<<= 7; 42 * 43 * \param state ChaCha20 state to modify. 44 * \param a The index of 'a' in the state. 45 * \param b The index of 'b' in the state. 46 * \param c The index of 'c' in the state. 47 * \param d The index of 'd' in the state. 48 */ 49 static inline void chacha20_quarter_round(uint32_t state[16], 50 size_t a, 51 size_t b, 52 size_t c, 53 size_t d) 54 { 55 /* a += b; d ^= a; d <<<= 16; */ 56 state[a] += state[b]; 57 state[d] ^= state[a]; 58 state[d] = ROTL32(state[d], 16); 59 60 /* c += d; b ^= c; b <<<= 12 */ 61 state[c] += state[d]; 62 state[b] ^= state[c]; 63 state[b] = ROTL32(state[b], 12); 64 65 /* a += b; d ^= a; d <<<= 8; */ 66 state[a] += state[b]; 67 state[d] ^= state[a]; 68 state[d] = ROTL32(state[d], 8); 69 70 /* c += d; b ^= c; b <<<= 7; */ 71 state[c] += state[d]; 72 state[b] ^= state[c]; 73 state[b] = ROTL32(state[b], 7); 74 } 75 76 /** 77 * \brief Perform the ChaCha20 inner block operation. 78 * 79 * This function performs two rounds: the column round and the 80 * diagonal round. 81 * 82 * \param state The ChaCha20 state to update. 83 */ 84 static void chacha20_inner_block(uint32_t state[16]) 85 { 86 chacha20_quarter_round(state, 0, 4, 8, 12); 87 chacha20_quarter_round(state, 1, 5, 9, 13); 88 chacha20_quarter_round(state, 2, 6, 10, 14); 89 chacha20_quarter_round(state, 3, 7, 11, 15); 90 91 chacha20_quarter_round(state, 0, 5, 10, 15); 92 chacha20_quarter_round(state, 1, 6, 11, 12); 93 chacha20_quarter_round(state, 2, 7, 8, 13); 94 chacha20_quarter_round(state, 3, 4, 9, 14); 95 } 96 97 /** 98 * \brief Generates a keystream block. 99 * 100 * \param initial_state The initial ChaCha20 state (key, nonce, counter). 101 * \param keystream Generated keystream bytes are written to this buffer. 102 */ 103 static void chacha20_block(const uint32_t initial_state[16], 104 unsigned char keystream[64]) 105 { 106 uint32_t working_state[16]; 107 size_t i; 108 109 memcpy(working_state, 110 initial_state, 111 CHACHA20_BLOCK_SIZE_BYTES); 112 113 for (i = 0U; i < 10U; i++) { 114 chacha20_inner_block(working_state); 115 } 116 117 working_state[0] += initial_state[0]; 118 working_state[1] += initial_state[1]; 119 working_state[2] += initial_state[2]; 120 working_state[3] += initial_state[3]; 121 working_state[4] += initial_state[4]; 122 working_state[5] += initial_state[5]; 123 working_state[6] += initial_state[6]; 124 working_state[7] += initial_state[7]; 125 working_state[8] += initial_state[8]; 126 working_state[9] += initial_state[9]; 127 working_state[10] += initial_state[10]; 128 working_state[11] += initial_state[11]; 129 working_state[12] += initial_state[12]; 130 working_state[13] += initial_state[13]; 131 working_state[14] += initial_state[14]; 132 working_state[15] += initial_state[15]; 133 134 for (i = 0U; i < 16; i++) { 135 size_t offset = i * 4U; 136 137 MBEDTLS_PUT_UINT32_LE(working_state[i], keystream, offset); 138 } 139 140 mbedtls_platform_zeroize(working_state, sizeof(working_state)); 141 } 142 143 void mbedtls_chacha20_init(mbedtls_chacha20_context *ctx) 144 { 145 mbedtls_platform_zeroize(ctx->state, sizeof(ctx->state)); 146 mbedtls_platform_zeroize(ctx->keystream8, sizeof(ctx->keystream8)); 147 148 /* Initially, there's no keystream bytes available */ 149 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES; 150 } 151 152 void mbedtls_chacha20_free(mbedtls_chacha20_context *ctx) 153 { 154 if (ctx != NULL) { 155 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_chacha20_context)); 156 } 157 } 158 159 int mbedtls_chacha20_setkey(mbedtls_chacha20_context *ctx, 160 const unsigned char key[32]) 161 { 162 /* ChaCha20 constants - the string "expand 32-byte k" */ 163 ctx->state[0] = 0x61707865; 164 ctx->state[1] = 0x3320646e; 165 ctx->state[2] = 0x79622d32; 166 ctx->state[3] = 0x6b206574; 167 168 /* Set key */ 169 ctx->state[4] = MBEDTLS_GET_UINT32_LE(key, 0); 170 ctx->state[5] = MBEDTLS_GET_UINT32_LE(key, 4); 171 ctx->state[6] = MBEDTLS_GET_UINT32_LE(key, 8); 172 ctx->state[7] = MBEDTLS_GET_UINT32_LE(key, 12); 173 ctx->state[8] = MBEDTLS_GET_UINT32_LE(key, 16); 174 ctx->state[9] = MBEDTLS_GET_UINT32_LE(key, 20); 175 ctx->state[10] = MBEDTLS_GET_UINT32_LE(key, 24); 176 ctx->state[11] = MBEDTLS_GET_UINT32_LE(key, 28); 177 178 return 0; 179 } 180 181 int mbedtls_chacha20_starts(mbedtls_chacha20_context *ctx, 182 const unsigned char nonce[12], 183 uint32_t counter) 184 { 185 /* Counter */ 186 ctx->state[12] = counter; 187 188 /* Nonce */ 189 ctx->state[13] = MBEDTLS_GET_UINT32_LE(nonce, 0); 190 ctx->state[14] = MBEDTLS_GET_UINT32_LE(nonce, 4); 191 ctx->state[15] = MBEDTLS_GET_UINT32_LE(nonce, 8); 192 193 mbedtls_platform_zeroize(ctx->keystream8, sizeof(ctx->keystream8)); 194 195 /* Initially, there's no keystream bytes available */ 196 ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES; 197 198 return 0; 199 } 200 201 int mbedtls_chacha20_update(mbedtls_chacha20_context *ctx, 202 size_t size, 203 const unsigned char *input, 204 unsigned char *output) 205 { 206 size_t offset = 0U; 207 208 /* Use leftover keystream bytes, if available */ 209 while (size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES) { 210 output[offset] = input[offset] 211 ^ ctx->keystream8[ctx->keystream_bytes_used]; 212 213 ctx->keystream_bytes_used++; 214 offset++; 215 size--; 216 } 217 218 /* Process full blocks */ 219 while (size >= CHACHA20_BLOCK_SIZE_BYTES) { 220 /* Generate new keystream block and increment counter */ 221 chacha20_block(ctx->state, ctx->keystream8); 222 ctx->state[CHACHA20_CTR_INDEX]++; 223 224 mbedtls_xor(output + offset, input + offset, ctx->keystream8, 64U); 225 226 offset += CHACHA20_BLOCK_SIZE_BYTES; 227 size -= CHACHA20_BLOCK_SIZE_BYTES; 228 } 229 230 /* Last (partial) block */ 231 if (size > 0U) { 232 /* Generate new keystream block and increment counter */ 233 chacha20_block(ctx->state, ctx->keystream8); 234 ctx->state[CHACHA20_CTR_INDEX]++; 235 236 mbedtls_xor(output + offset, input + offset, ctx->keystream8, size); 237 238 ctx->keystream_bytes_used = size; 239 240 } 241 242 return 0; 243 } 244 245 int mbedtls_chacha20_crypt(const unsigned char key[32], 246 const unsigned char nonce[12], 247 uint32_t counter, 248 size_t data_len, 249 const unsigned char *input, 250 unsigned char *output) 251 { 252 mbedtls_chacha20_context ctx; 253 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 254 255 mbedtls_chacha20_init(&ctx); 256 257 ret = mbedtls_chacha20_setkey(&ctx, key); 258 if (ret != 0) { 259 goto cleanup; 260 } 261 262 ret = mbedtls_chacha20_starts(&ctx, nonce, counter); 263 if (ret != 0) { 264 goto cleanup; 265 } 266 267 ret = mbedtls_chacha20_update(&ctx, data_len, input, output); 268 269 cleanup: 270 mbedtls_chacha20_free(&ctx); 271 return ret; 272 } 273 274 #endif /* !MBEDTLS_CHACHA20_ALT */ 275 276 #if defined(MBEDTLS_SELF_TEST) 277 278 static const unsigned char test_keys[2][32] = 279 { 280 { 281 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 282 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 283 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 284 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 285 }, 286 { 287 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 288 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 289 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 290 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 291 } 292 }; 293 294 static const unsigned char test_nonces[2][12] = 295 { 296 { 297 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 298 0x00, 0x00, 0x00, 0x00 299 }, 300 { 301 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 302 0x00, 0x00, 0x00, 0x02 303 } 304 }; 305 306 static const uint32_t test_counters[2] = 307 { 308 0U, 309 1U 310 }; 311 312 static const unsigned char test_input[2][375] = 313 { 314 { 315 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 316 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 317 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 318 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 319 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 320 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 321 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 322 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 323 }, 324 { 325 0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d, 326 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74, 327 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45, 328 0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e, 329 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 330 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72, 331 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66, 332 0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 333 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, 334 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72, 335 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, 336 0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46, 337 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 338 0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20, 339 0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61, 340 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73, 341 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 342 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69, 343 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 344 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 345 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49, 346 0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69, 347 0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20, 348 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72, 349 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49, 350 0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74, 351 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 352 0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20, 353 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 354 0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 355 0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20, 356 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 357 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45, 358 0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69, 359 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20, 360 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20, 361 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20, 362 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63, 363 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63, 364 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 365 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61, 366 0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e, 367 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f, 368 0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c, 369 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61, 370 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 371 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f 372 } 373 }; 374 375 static const unsigned char test_output[2][375] = 376 { 377 { 378 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90, 379 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28, 380 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a, 381 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7, 382 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d, 383 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37, 384 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c, 385 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86 386 }, 387 { 388 0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde, 389 0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70, 390 0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd, 391 0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec, 392 0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15, 393 0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05, 394 0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f, 395 0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d, 396 0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa, 397 0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e, 398 0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7, 399 0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50, 400 0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05, 401 0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c, 402 0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05, 403 0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a, 404 0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0, 405 0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66, 406 0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4, 407 0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d, 408 0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91, 409 0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28, 410 0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87, 411 0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b, 412 0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2, 413 0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f, 414 0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76, 415 0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c, 416 0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b, 417 0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84, 418 0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd, 419 0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b, 420 0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe, 421 0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0, 422 0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80, 423 0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f, 424 0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3, 425 0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62, 426 0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91, 427 0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6, 428 0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64, 429 0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85, 430 0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41, 431 0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab, 432 0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba, 433 0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd, 434 0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21 435 } 436 }; 437 438 static const size_t test_lengths[2] = 439 { 440 64U, 441 375U 442 }; 443 444 /* Make sure no other definition is already present. */ 445 #undef ASSERT 446 447 #define ASSERT(cond, args) \ 448 do \ 449 { \ 450 if (!(cond)) \ 451 { \ 452 if (verbose != 0) \ 453 mbedtls_printf args; \ 454 \ 455 return -1; \ 456 } \ 457 } \ 458 while (0) 459 460 int mbedtls_chacha20_self_test(int verbose) 461 { 462 unsigned char output[381]; 463 unsigned i; 464 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 465 466 for (i = 0U; i < 2U; i++) { 467 if (verbose != 0) { 468 mbedtls_printf(" ChaCha20 test %u ", i); 469 } 470 471 ret = mbedtls_chacha20_crypt(test_keys[i], 472 test_nonces[i], 473 test_counters[i], 474 test_lengths[i], 475 test_input[i], 476 output); 477 478 ASSERT(0 == ret, ("error code: %i\n", ret)); 479 480 ASSERT(0 == memcmp(output, test_output[i], test_lengths[i]), 481 ("failed (output)\n")); 482 483 if (verbose != 0) { 484 mbedtls_printf("passed\n"); 485 } 486 } 487 488 if (verbose != 0) { 489 mbedtls_printf("\n"); 490 } 491 492 return 0; 493 } 494 495 #endif /* MBEDTLS_SELF_TEST */ 496 497 #endif /* !MBEDTLS_CHACHA20_C */ 498