// Copyright 2017 The Fuchsia Authors // // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file or at // https://opensource.org/licenses/MIT #include #include #include #include #include #include #include #include #include #include #include #include namespace crypto { namespace entropy { #if ENABLE_ENTROPY_COLLECTOR_TEST #ifndef ENTROPY_COLLECTOR_TEST_MAXLEN #define ENTROPY_COLLECTOR_TEST_MAXLEN (1024u * 1024u) #endif namespace { uint8_t entropy_buf[ENTROPY_COLLECTOR_TEST_MAXLEN]; size_t entropy_len; } // namespace fbl::RefPtr entropy_vmo; bool entropy_was_lost = false; static void SetupEntropyVmo(uint level) { if (VmObjectPaged::Create(PMM_ALLOC_FLAG_ANY, 0u, entropy_len, &entropy_vmo) != ZX_OK) { printf("entropy-boot-test: Failed to create entropy_vmo (data lost)\n"); entropy_was_lost = true; return; } size_t actual; if (entropy_vmo->Write(entropy_buf, 0, entropy_len, &actual) != ZX_OK) { printf("entropy-boot-test: Failed to write to entropy_vmo (data lost)\n"); entropy_was_lost = true; return; } if (actual < entropy_len) { printf("entropy-boot-test: partial write to entropy_vmo (data lost)\n"); entropy_was_lost = true; return; } constexpr const char *name = "debug/entropy.bin"; if (entropy_vmo->set_name(name, strlen(name)) != ZX_OK) { // The name is needed because devmgr uses it to add the VMO as a file in // the /boot filesystem. printf("entropy-boot-test: could not name entropy_vmo (data lost)\n"); entropy_was_lost = true; return; } } // Run the entropy collector test. void EarlyBootTest() { const char* src_name = cmdline_get("kernel.entropy-test.src"); if (!src_name) { src_name = ""; } entropy::Collector* collector = nullptr; entropy::Collector* candidate; char candidate_name[ZX_MAX_NAME_LEN]; // TODO(andrewkrieger): find a nicer way to enumerate all entropy collectors if (HwRngCollector::GetInstance(&candidate) == ZX_OK) { candidate->get_name(candidate_name, sizeof(candidate_name)); if (strncmp(candidate_name, src_name, ZX_MAX_NAME_LEN) == 0) { collector = candidate; } } if (!collector && JitterentropyCollector::GetInstance(&candidate) == ZX_OK) { candidate->get_name(candidate_name, sizeof(candidate_name)); if (strncmp(candidate_name, src_name, ZX_MAX_NAME_LEN) == 0) { collector = candidate; } } // TODO(andrewkrieger): add other entropy collectors. if (!collector) { printf("entropy-boot-test: unrecognized source \"%s\"\n", src_name); printf("entropy-boot-test: skipping test.\n"); return; } entropy_len = cmdline_get_uint64("kernel.entropy-test.len", sizeof(entropy_buf)); if (entropy_len > sizeof(entropy_buf)) { entropy_len = sizeof(entropy_buf); printf("entropy-boot-test: only recording %zu bytes (try defining " "ENTROPY_COLLECTOR_TEST_MAXLEN)\n", sizeof(entropy_buf)); } zx_time_t start = current_time(); size_t result = collector->DrawEntropy(entropy_buf, entropy_len); zx_time_t end = current_time(); if (result < entropy_len) { printf("entropy-boot-test: source only returned %zu bytes.\n", result); entropy_len = result; } else { printf("entropy-boot-test: successful draw in %" PRIu64 " nanoseconds.\n", end - start); } } #else // ENABLE_ENTROPY_COLLECTOR_TEST void EarlyBootTest() { } #endif // ENABLE_ENTROPY_COLLECTOR_TEST } // namespace entropy } // namespace crypto #if ENABLE_ENTROPY_COLLECTOR_TEST LK_INIT_HOOK(setup_entropy_vmo, crypto::entropy::SetupEntropyVmo, LK_INIT_LEVEL_VM + 1); #endif