1/* 2 * Self-test demonstration program 3 * 4 * Copyright The Mbed TLS Contributors 5 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 6 */ 7 8#include "mbedtls/build_info.h" 9 10#include "mbedtls/entropy.h" 11#include "mbedtls/hmac_drbg.h" 12#include "mbedtls/ctr_drbg.h" 13#include "mbedtls/dhm.h" 14#include "mbedtls/gcm.h" 15#include "mbedtls/ccm.h" 16#include "mbedtls/cmac.h" 17#include "mbedtls/md5.h" 18#include "mbedtls/ripemd160.h" 19#include "mbedtls/sha1.h" 20#include "mbedtls/sha256.h" 21#include "mbedtls/sha512.h" 22#include "mbedtls/sha3.h" 23#include "mbedtls/des.h" 24#include "mbedtls/aes.h" 25#include "mbedtls/camellia.h" 26#include "mbedtls/aria.h" 27#include "mbedtls/chacha20.h" 28#include "mbedtls/poly1305.h" 29#include "mbedtls/chachapoly.h" 30#include "mbedtls/base64.h" 31#include "mbedtls/bignum.h" 32#include "mbedtls/rsa.h" 33#include "mbedtls/x509.h" 34#include "mbedtls/pkcs5.h" 35#include "mbedtls/ecp.h" 36#include "mbedtls/ecjpake.h" 37#include "mbedtls/timing.h" 38#include "mbedtls/nist_kw.h" 39#include "mbedtls/debug.h" 40 41#include <limits.h> 42#include <string.h> 43 44#include "mbedtls/platform.h" 45 46#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) 47#include "mbedtls/memory_buffer_alloc.h" 48#endif 49 50 51#if defined MBEDTLS_SELF_TEST 52/* Sanity check for malloc. This is not expected to fail, and is rather 53 * intended to display potentially useful information about the platform, 54 * in particular the behavior of malloc(0). */ 55static int calloc_self_test(int verbose) 56{ 57 int failures = 0; 58 void *empty1 = mbedtls_calloc(0, 1); 59 void *empty2 = mbedtls_calloc(0, 1); 60 void *buffer1 = mbedtls_calloc(1, 1); 61 void *buffer2 = mbedtls_calloc(1, 1); 62 unsigned int buffer_3_size = 256; 63 unsigned int buffer_4_size = 4097; /* Allocate more than the usual page size */ 64 unsigned char *buffer3 = mbedtls_calloc(buffer_3_size, 1); 65 unsigned char *buffer4 = mbedtls_calloc(buffer_4_size, 1); 66 67 if (empty1 == NULL && empty2 == NULL) { 68 if (verbose) { 69 mbedtls_printf(" CALLOC(0,1): passed (NULL)\n"); 70 } 71 } else if (empty1 == NULL || empty2 == NULL) { 72 if (verbose) { 73 mbedtls_printf(" CALLOC(0,1): failed (mix of NULL and non-NULL)\n"); 74 } 75 ++failures; 76 } else if (empty1 == empty2) { 77 if (verbose) { 78 mbedtls_printf(" CALLOC(0,1): passed (same non-null)\n"); 79 } 80 empty2 = NULL; 81 } else { 82 if (verbose) { 83 mbedtls_printf(" CALLOC(0,1): passed (distinct non-null)\n"); 84 } 85 } 86 87 mbedtls_free(empty1); 88 mbedtls_free(empty2); 89 90 empty1 = mbedtls_calloc(1, 0); 91 empty2 = mbedtls_calloc(1, 0); 92 if (empty1 == NULL && empty2 == NULL) { 93 if (verbose) { 94 mbedtls_printf(" CALLOC(1,0): passed (NULL)\n"); 95 } 96 } else if (empty1 == NULL || empty2 == NULL) { 97 if (verbose) { 98 mbedtls_printf(" CALLOC(1,0): failed (mix of NULL and non-NULL)\n"); 99 } 100 ++failures; 101 } else if (empty1 == empty2) { 102 if (verbose) { 103 mbedtls_printf(" CALLOC(1,0): passed (same non-null)\n"); 104 } 105 empty2 = NULL; 106 } else { 107 if (verbose) { 108 mbedtls_printf(" CALLOC(1,0): passed (distinct non-null)\n"); 109 } 110 } 111 112 if (buffer1 == NULL || buffer2 == NULL) { 113 if (verbose) { 114 mbedtls_printf(" CALLOC(1): failed (NULL)\n"); 115 } 116 ++failures; 117 } else if (buffer1 == buffer2) { 118 if (verbose) { 119 mbedtls_printf(" CALLOC(1): failed (same buffer twice)\n"); 120 } 121 ++failures; 122 buffer2 = NULL; 123 } else { 124 if (verbose) { 125 mbedtls_printf(" CALLOC(1): passed\n"); 126 } 127 } 128 129 mbedtls_free(buffer1); 130 buffer1 = mbedtls_calloc(1, 1); 131 if (buffer1 == NULL) { 132 if (verbose) { 133 mbedtls_printf(" CALLOC(1 again): failed (NULL)\n"); 134 } 135 ++failures; 136 } else { 137 if (verbose) { 138 mbedtls_printf(" CALLOC(1 again): passed\n"); 139 } 140 } 141 142 for (unsigned int i = 0; i < buffer_3_size; i++) { 143 if (buffer3[i] != 0) { 144 ++failures; 145 if (verbose) { 146 mbedtls_printf(" CALLOC(%u): failed (memory not initialized to 0)\n", 147 buffer_3_size); 148 } 149 break; 150 } 151 } 152 153 for (unsigned int i = 0; i < buffer_4_size; i++) { 154 if (buffer4[i] != 0) { 155 ++failures; 156 if (verbose) { 157 mbedtls_printf(" CALLOC(%u): failed (memory not initialized to 0)\n", 158 buffer_4_size); 159 } 160 break; 161 } 162 } 163 164 if (verbose) { 165 mbedtls_printf("\n"); 166 } 167 mbedtls_free(empty1); 168 mbedtls_free(empty2); 169 mbedtls_free(buffer1); 170 mbedtls_free(buffer2); 171 mbedtls_free(buffer3); 172 mbedtls_free(buffer4); 173 return failures; 174} 175#endif /* MBEDTLS_SELF_TEST */ 176 177static int test_snprintf(size_t n, const char *ref_buf, int ref_ret) 178{ 179 int ret; 180 char buf[10] = "xxxxxxxxx"; 181 const char ref[10] = "xxxxxxxxx"; 182 183 ret = mbedtls_snprintf(buf, n, "%s", "123"); 184 if (ret < 0 || (size_t) ret >= n) { 185 ret = -1; 186 } 187 188 if (strncmp(ref_buf, buf, sizeof(buf)) != 0 || 189 ref_ret != ret || 190 memcmp(buf + n, ref + n, sizeof(buf) - n) != 0) { 191 return 1; 192 } 193 194 return 0; 195} 196 197static int run_test_snprintf(void) 198{ 199 return test_snprintf(0, "xxxxxxxxx", -1) != 0 || 200 test_snprintf(1, "", -1) != 0 || 201 test_snprintf(2, "1", -1) != 0 || 202 test_snprintf(3, "12", -1) != 0 || 203 test_snprintf(4, "123", 3) != 0 || 204 test_snprintf(5, "123", 3) != 0; 205} 206 207/* 208 * Check if a seed file is present, and if not create one for the entropy 209 * self-test. If this fails, we attempt the test anyway, so no error is passed 210 * back. 211 */ 212#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_ENTROPY_C) 213#if defined(MBEDTLS_ENTROPY_NV_SEED) && !defined(MBEDTLS_NO_PLATFORM_ENTROPY) 214static void create_entropy_seed_file(void) 215{ 216 int result; 217 size_t output_len = 0; 218 unsigned char seed_value[MBEDTLS_ENTROPY_BLOCK_SIZE]; 219 220 /* Attempt to read the entropy seed file. If this fails - attempt to write 221 * to the file to ensure one is present. */ 222 result = mbedtls_platform_std_nv_seed_read(seed_value, 223 MBEDTLS_ENTROPY_BLOCK_SIZE); 224 if (0 == result) { 225 return; 226 } 227 228 result = mbedtls_platform_entropy_poll(NULL, 229 seed_value, 230 MBEDTLS_ENTROPY_BLOCK_SIZE, 231 &output_len); 232 if (0 != result) { 233 return; 234 } 235 236 if (MBEDTLS_ENTROPY_BLOCK_SIZE != output_len) { 237 return; 238 } 239 240 mbedtls_platform_std_nv_seed_write(seed_value, MBEDTLS_ENTROPY_BLOCK_SIZE); 241} 242#endif 243 244int mbedtls_entropy_self_test_wrapper(int verbose) 245{ 246#if defined(MBEDTLS_ENTROPY_NV_SEED) && !defined(MBEDTLS_NO_PLATFORM_ENTROPY) 247 create_entropy_seed_file(); 248#endif 249 return mbedtls_entropy_self_test(verbose); 250} 251#endif 252 253#if defined(MBEDTLS_SELF_TEST) 254#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) 255int mbedtls_memory_buffer_alloc_free_and_self_test(int verbose) 256{ 257 if (verbose != 0) { 258#if defined(MBEDTLS_MEMORY_DEBUG) 259 mbedtls_memory_buffer_alloc_status(); 260#endif 261 } 262 mbedtls_memory_buffer_alloc_free(); 263 return mbedtls_memory_buffer_alloc_self_test(verbose); 264} 265#endif 266 267typedef struct { 268 const char *name; 269 int (*function)(int); 270} selftest_t; 271 272const selftest_t selftests[] = 273{ 274 { "calloc", calloc_self_test }, 275#if defined(MBEDTLS_MD5_C) 276 { "md5", mbedtls_md5_self_test }, 277#endif 278#if defined(MBEDTLS_RIPEMD160_C) 279 { "ripemd160", mbedtls_ripemd160_self_test }, 280#endif 281#if defined(MBEDTLS_SHA1_C) 282 { "sha1", mbedtls_sha1_self_test }, 283#endif 284#if defined(MBEDTLS_SHA224_C) 285 { "sha224", mbedtls_sha224_self_test }, 286#endif 287#if defined(MBEDTLS_SHA256_C) 288 { "sha256", mbedtls_sha256_self_test }, 289#endif 290#if defined(MBEDTLS_SHA384_C) 291 { "sha384", mbedtls_sha384_self_test }, 292#endif 293#if defined(MBEDTLS_SHA512_C) 294 { "sha512", mbedtls_sha512_self_test }, 295#endif 296#if defined(MBEDTLS_SHA3_C) 297 { "sha3", mbedtls_sha3_self_test }, 298#endif 299#if defined(MBEDTLS_DES_C) 300 { "des", mbedtls_des_self_test }, 301#endif 302#if defined(MBEDTLS_AES_C) 303 { "aes", mbedtls_aes_self_test }, 304#endif 305#if defined(MBEDTLS_GCM_C) && defined(MBEDTLS_AES_C) 306 { "gcm", mbedtls_gcm_self_test }, 307#endif 308#if defined(MBEDTLS_CCM_C) && defined(MBEDTLS_AES_C) 309 { "ccm", mbedtls_ccm_self_test }, 310#endif 311#if defined(MBEDTLS_NIST_KW_C) && defined(MBEDTLS_AES_C) 312 { "nist_kw", mbedtls_nist_kw_self_test }, 313#endif 314#if defined(MBEDTLS_CMAC_C) 315 { "cmac", mbedtls_cmac_self_test }, 316#endif 317#if defined(MBEDTLS_CHACHA20_C) 318 { "chacha20", mbedtls_chacha20_self_test }, 319#endif 320#if defined(MBEDTLS_POLY1305_C) 321 { "poly1305", mbedtls_poly1305_self_test }, 322#endif 323#if defined(MBEDTLS_CHACHAPOLY_C) 324 { "chacha20-poly1305", mbedtls_chachapoly_self_test }, 325#endif 326#if defined(MBEDTLS_BASE64_C) 327 { "base64", mbedtls_base64_self_test }, 328#endif 329#if defined(MBEDTLS_BIGNUM_C) 330 { "mpi", mbedtls_mpi_self_test }, 331#endif 332#if defined(MBEDTLS_RSA_C) 333 { "rsa", mbedtls_rsa_self_test }, 334#endif 335#if defined(MBEDTLS_CAMELLIA_C) 336 { "camellia", mbedtls_camellia_self_test }, 337#endif 338#if defined(MBEDTLS_ARIA_C) 339 { "aria", mbedtls_aria_self_test }, 340#endif 341#if defined(MBEDTLS_CTR_DRBG_C) 342 { "ctr_drbg", mbedtls_ctr_drbg_self_test }, 343#endif 344#if defined(MBEDTLS_HMAC_DRBG_C) 345 { "hmac_drbg", mbedtls_hmac_drbg_self_test }, 346#endif 347#if defined(MBEDTLS_ECP_C) 348 { "ecp", mbedtls_ecp_self_test }, 349#endif 350#if defined(MBEDTLS_ECJPAKE_C) 351 { "ecjpake", mbedtls_ecjpake_self_test }, 352#endif 353#if defined(MBEDTLS_DHM_C) 354 { "dhm", mbedtls_dhm_self_test }, 355#endif 356#if defined(MBEDTLS_ENTROPY_C) 357 { "entropy", mbedtls_entropy_self_test_wrapper }, 358#endif 359#if defined(MBEDTLS_PKCS5_C) 360 { "pkcs5", mbedtls_pkcs5_self_test }, 361#endif 362/* Heap test comes last */ 363#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) 364 { "memory_buffer_alloc", mbedtls_memory_buffer_alloc_free_and_self_test }, 365#endif 366 { NULL, NULL } 367}; 368#endif /* MBEDTLS_SELF_TEST */ 369 370int main(int argc, char *argv[]) 371{ 372#if defined(MBEDTLS_SELF_TEST) 373 const selftest_t *test; 374#endif /* MBEDTLS_SELF_TEST */ 375 char **argp; 376 int v = 1; /* v=1 for verbose mode */ 377 int exclude_mode = 0; 378 int suites_tested = 0, suites_failed = 0; 379#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && defined(MBEDTLS_SELF_TEST) 380 unsigned char buf[1000000]; 381#endif 382 void *pointer; 383 384 /* 385 * Check some basic platform requirements as specified in README.md 386 */ 387 if (SIZE_MAX < INT_MAX || SIZE_MAX < UINT_MAX) { 388 mbedtls_printf("SIZE_MAX must be at least as big as INT_MAX and UINT_MAX\n"); 389 mbedtls_exit(MBEDTLS_EXIT_FAILURE); 390 } 391 392 if (sizeof(int) < 4) { 393 mbedtls_printf("int must be at least 32 bits\n"); 394 mbedtls_exit(MBEDTLS_EXIT_FAILURE); 395 } 396 397 if (sizeof(size_t) < 4) { 398 mbedtls_printf("size_t must be at least 32 bits\n"); 399 mbedtls_exit(MBEDTLS_EXIT_FAILURE); 400 } 401 402 uint32_t endian_test = 0x12345678; 403 char *p = (char *) &endian_test; 404 if (!(p[0] == 0x12 && p[1] == 0x34 && p[2] == 0x56 && p[3] == 0x78) && 405 !(p[3] == 0x12 && p[2] == 0x34 && p[1] == 0x56 && p[0] == 0x78)) { 406 mbedtls_printf("Mixed-endian platforms are not supported\n"); 407 mbedtls_exit(MBEDTLS_EXIT_FAILURE); 408 } 409 410 /* 411 * The C standard doesn't guarantee that all-bits-0 is the representation 412 * of a NULL pointer. We do however use that in our code for initializing 413 * structures, which should work on every modern platform. Let's be sure. 414 */ 415 memset(&pointer, 0, sizeof(void *)); 416 if (pointer != NULL) { 417 mbedtls_printf("all-bits-zero is not a NULL pointer\n"); 418 mbedtls_exit(MBEDTLS_EXIT_FAILURE); 419 } 420 421 /* 422 * The C standard allows padding bits in the representation 423 * of standard integer types, but our code does currently not 424 * support them. 425 * 426 * Here we check that the underlying C implementation doesn't 427 * use padding bits, and fail cleanly if it does. 428 * 429 * The check works by casting the maximum value representable 430 * by a given integer type into the unpadded integer type of the 431 * same bit-width and checking that it agrees with the maximum value 432 * of that unpadded type. For example, for a 4-byte int, 433 * MAX_INT should be 0x7fffffff in int32_t. This assumes that 434 * CHAR_BIT == 8, which is checked in check_config.h. 435 * 436 * We assume that [u]intxx_t exist and that they don't 437 * have padding bits, as the standard requires. 438 */ 439 440#define CHECK_PADDING_SIGNED(TYPE, NAME) \ 441 do \ 442 { \ 443 if (sizeof(TYPE) == 2 || sizeof(TYPE) == 4 || \ 444 sizeof(TYPE) == 8) { \ 445 if ((sizeof(TYPE) == 2 && \ 446 (int16_t) NAME ## _MAX != 0x7FFF) || \ 447 (sizeof(TYPE) == 4 && \ 448 (int32_t) NAME ## _MAX != 0x7FFFFFFF) || \ 449 (sizeof(TYPE) == 8 && \ 450 (int64_t) NAME ## _MAX != 0x7FFFFFFFFFFFFFFF)) \ 451 { \ 452 mbedtls_printf("Type '" #TYPE "' has padding bits\n"); \ 453 mbedtls_exit(MBEDTLS_EXIT_FAILURE); \ 454 } \ 455 } else { \ 456 mbedtls_printf("Padding checks only implemented for types of size 2, 4 or 8" \ 457 " - cannot check type '" #TYPE "' of size %" MBEDTLS_PRINTF_SIZET "\n", \ 458 sizeof(TYPE)); \ 459 mbedtls_exit(MBEDTLS_EXIT_FAILURE); \ 460 } \ 461 } while (0) 462 463#define CHECK_PADDING_UNSIGNED(TYPE, NAME) \ 464 do \ 465 { \ 466 if ((sizeof(TYPE) == 2 && \ 467 (uint16_t) NAME ## _MAX != 0xFFFF) || \ 468 (sizeof(TYPE) == 4 && \ 469 (uint32_t) NAME ## _MAX != 0xFFFFFFFF) || \ 470 (sizeof(TYPE) == 8 && \ 471 (uint64_t) NAME ## _MAX != 0xFFFFFFFFFFFFFFFF)) \ 472 { \ 473 mbedtls_printf("Type '" #TYPE "' has padding bits\n"); \ 474 mbedtls_exit(MBEDTLS_EXIT_FAILURE); \ 475 } \ 476 } while (0) 477 478 CHECK_PADDING_SIGNED(short, SHRT); 479 CHECK_PADDING_SIGNED(int, INT); 480 CHECK_PADDING_SIGNED(long, LONG); 481 CHECK_PADDING_SIGNED(long long, LLONG); 482 CHECK_PADDING_SIGNED(ptrdiff_t, PTRDIFF); 483 484 CHECK_PADDING_UNSIGNED(unsigned short, USHRT); 485 CHECK_PADDING_UNSIGNED(unsigned, UINT); 486 CHECK_PADDING_UNSIGNED(unsigned long, ULONG); 487 CHECK_PADDING_UNSIGNED(unsigned long long, ULLONG); 488 CHECK_PADDING_UNSIGNED(size_t, SIZE); 489 490#undef CHECK_PADDING_SIGNED 491#undef CHECK_PADDING_UNSIGNED 492 493 /* 494 * Make sure we have a snprintf that correctly zero-terminates 495 */ 496 if (run_test_snprintf() != 0) { 497 mbedtls_printf("the snprintf implementation is broken\n"); 498 mbedtls_exit(MBEDTLS_EXIT_FAILURE); 499 } 500 501 for (argp = argv + (argc >= 1 ? 1 : argc); *argp != NULL; ++argp) { 502 if (strcmp(*argp, "--quiet") == 0 || 503 strcmp(*argp, "-q") == 0) { 504 v = 0; 505 } else if (strcmp(*argp, "--exclude") == 0 || 506 strcmp(*argp, "-x") == 0) { 507 exclude_mode = 1; 508 } else { 509 break; 510 } 511 } 512 513 if (v != 0) { 514 mbedtls_printf("\n"); 515 } 516 517#if defined(MBEDTLS_SELF_TEST) 518 519#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) 520 mbedtls_memory_buffer_alloc_init(buf, sizeof(buf)); 521#endif 522 523 if (*argp != NULL && exclude_mode == 0) { 524 /* Run the specified tests */ 525 for (; *argp != NULL; argp++) { 526 for (test = selftests; test->name != NULL; test++) { 527 if (!strcmp(*argp, test->name)) { 528 if (test->function(v) != 0) { 529 suites_failed++; 530 } 531 suites_tested++; 532 break; 533 } 534 } 535 if (test->name == NULL) { 536 mbedtls_printf(" Test suite %s not available -> failed\n\n", *argp); 537 suites_failed++; 538 } 539 } 540 } else { 541 /* Run all the tests except excluded ones */ 542 for (test = selftests; test->name != NULL; test++) { 543 if (exclude_mode) { 544 char **excluded; 545 for (excluded = argp; *excluded != NULL; ++excluded) { 546 if (!strcmp(*excluded, test->name)) { 547 break; 548 } 549 } 550 if (*excluded) { 551 if (v) { 552 mbedtls_printf(" Skip: %s\n", test->name); 553 } 554 continue; 555 } 556 } 557 if (test->function(v) != 0) { 558 suites_failed++; 559 } 560 suites_tested++; 561 } 562 } 563 564#else 565 (void) exclude_mode; 566 mbedtls_printf(" MBEDTLS_SELF_TEST not defined.\n"); 567#endif 568 569 if (v != 0) { 570 mbedtls_printf(" Executed %d test suites\n\n", suites_tested); 571 572 if (suites_failed > 0) { 573 mbedtls_printf(" [ %d tests FAIL ]\n\n", suites_failed); 574 } else { 575 mbedtls_printf(" [ All tests PASS ]\n\n"); 576 } 577 } 578 579 if (suites_failed > 0) { 580 mbedtls_exit(MBEDTLS_EXIT_FAILURE); 581 } 582 583 mbedtls_exit(MBEDTLS_EXIT_SUCCESS); 584} 585