From: Eric Biggers <ebiggers@kernel.org>
To: linux-crypto@vger.kernel.org, Herbert Xu <herbert@gondor.apana.org.au>
Cc: "Stephan Müller" <smueller@chronox.de>,
"Eric Biggers" <ebiggers@kernel.org>
Subject: [PATCH 07/14] crypto: drbg - Add self-test for library API
Date: Sun, 18 Oct 2026 13:46:11 -0700 [thread overview]
Message-ID: <20261018204618.104876-8-ebiggers@kernel.org> (raw)
In-Reply-To: <20261018204618.104876-1-ebiggers@kernel.org>
With the SP800-90A DRBG now being accessible through a library API, it
now needs to handle the self-test internally instead of relying on
"testmgr". Implement it, using the existing test vectors.
Run the self-test at module_init time or on first call to
crypto_drbg_alloc(), whichever comes first, if either
CONFIG_CRYPTO_SELFTESTS is enabled or the kernel is booted with fips=1.
Also run the existing drbg_healthcheck_sanity() at the same time if
fips=1; previously that ran only at module_init time. If fips=1 and
either test fails, the kernel panics, as required by FIPS module tests.
When fips=1, if the tests pass, "DRBG: self-tests passed" is printed to
the log. This is for parity with testmgr.c which printed a similar
message. If the tests fail, for now don't bother calling
fips_fail_notify() before panicking: most of the FIPS self-tests already
don't call it, and those notifications only go to one driver, so clearly
that notifier chain isn't a finished feature anyway.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/drbg-testvecs.h | 228 +++++++++++++++++++++++++++++++++++++++++
crypto/drbg.c | 123 +++++++++++++++++++---
2 files changed, 338 insertions(+), 13 deletions(-)
create mode 100644 crypto/drbg-testvecs.h
diff --git a/crypto/drbg-testvecs.h b/crypto/drbg-testvecs.h
new file mode 100644
index 0000000000000..d073257eb3d18
--- /dev/null
+++ b/crypto/drbg-testvecs.h
@@ -0,0 +1,228 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright 2026 Google LLC
+ */
+#ifndef _CRYPTO_DRBG_TESTVECS_H
+#define _CRYPTO_DRBG_TESTVECS_H
+
+#include <linux/types.h>
+
+struct drbg_testvec {
+ /* Instantiate */
+ const u8 *entropy;
+ size_t entropylen;
+ const u8 *pers;
+ size_t perslen;
+
+ /* Reseed (optional) */
+ const u8 *ent_reseed;
+ size_t ent_reseed_len;
+ const u8 *addtl_reseed;
+ size_t addtl_reseed_len;
+
+ /* Generate (twice) */
+ const u8 *addtla;
+ const u8 *addtlb;
+ size_t addtllen;
+
+ /* Expected output from last call to Generate */
+ const u8 *expected;
+ size_t expectedlen;
+};
+
+static const struct drbg_testvec drbg_testvecs[] = {
+ /*
+ * Borrowed from the first applicable test vector from ACVP:
+ * https://github.com/usnistgov/ACVP-Server/blob/v1.1.0.33/gen-val/json-files/hmacDRBG-1.0/prompt.json#L4596
+ * https://github.com/usnistgov/ACVP-Server/blob/v1.1.0.33/gen-val/json-files/hmacDRBG-1.0/expectedResults.json#L986
+ */
+ {
+ /* .entropy = ACVP entropyInput || nonce */
+ .entropy = "\x47\x28\x33\x05\x82\xE8\xA7\x58\x05\xBD\x07\x9E"
+ "\xDB\x59\x87\x08\x3B\x82\x40\x70\xA1\xB7\x33\x4F"
+ "\x0F\x53\xBE\xF6\x98\x75\xFA\x21\x00\x04\xBC\x58"
+ "\x9B\xB1\xB3\xBC\x2A\xF6\xA4\x2A\xE1\xB3\x65\x24"
+ "\xA8\xEE\x56\x70\x5E\x28\x06\x04\x80\xCE\xB7\x36"
+ "\xA4\xD1\x4E\xAA\xE7\xE8\x51\x40\x7D\x30\xF7\x91"
+ "\xF2\x9E\x98\xA7\xBB\xB3\x1D\xC6\x8A\x62\xC7\xE7"
+ "\x1F\xE1\x0A\x52\x45\x39\x88\x92\x43\xA6\x5B\xC3"
+ "\x9D\x60\xDE\xFE\x79\xEF\x87\x6F\xD5\x76\x51\x69"
+ "\x7B\x4C\x3D\x08\x60\xFA\xDC\x00\x94\xEC\x0A\xC5"
+ "\xE7\xCB\x30\x05\x9F\xCC\x07\x44\x07\x14\xF4\xF9"
+ "\xBC\x7D\xC0\x66\x63\x5B\xD3\x2A\xA7\xF2\x1D\x75"
+ "\x3F\x28\x5F\x4A\xEB\x63\xD7\x92\x5A\x9A\x7C\x3A"
+ "\x56\xEA\xCB\xA9\xA0\xF9\x5B\x99\xC2\x7D\x31\xBF"
+ "\x44\xC7\x64\x6B\x7E\x64\x60\x64\x05\x86\xF0\x6B"
+ "\x76\xA7\x3E\x63\xAD\xB6\x76\xED\x3D\x05\x2E\xC7"
+ "\xC7\x52\x8F\x07\x56\x23\xFC\x2F\x93\xD5\xF2\x29"
+ "\xC6\x84\x48\xD1\x88\xB9\x3F\x84\xB2\x93\xFC\x2F"
+ "\x00\xB1\xBC\xBE\xAC\xC4\x94\x36\xF1\x2B\xF0\xC7"
+ "\x36\xE8\x1D\x45\x0A\xA2\xFE\x72\xD7\x3E\x15\x6A"
+ "\x74\x23\xB2\xD1\x3C\x20\xF2\xB7\x19\xC5\xF0\x74"
+ "\x69\x06\xD1\x92\x47\xC9\x68\xDC\xEE\xBC\xF4\x3A"
+ "\x8B\x7C\xA4\xA4\x4A\x15\xF4\xF0\x26\x26\xC5\x7D"
+ "\x57\xDC\x00\x59\x07\xDF\x84\x2A\x23\xA9\xC1\xAF"
+ "\x47\x49\x88\xCC\x2F\x3B\x90\x39\xA0\x09\xAE\x3C"
+ "\x79\xF9\x97\x9D\xEF\x13\x1D\x2B\xB6\x18\xDB\xCF"
+ "\x95\x98\x17\x7F\xF6\x95\x44\x3A\x40\x90\x63\x16"
+ "\x70\x38\x22\xC5\xD8\xE4\x57\xA0\x8E\x51\x6B\xED"
+ "\x03\x18\xC6\x74\xFA\xCA\xF2\xD5\xB2\x5A\x0C\x02"
+ "\x48\x9F\x70\x0B\x1C\x0A\xD1\xD6\x4F\x3F\x70\x3C"
+ "\x1A\x62\x29\x63\xD0\x92\x76\x30\x7C\xB9\x54\xEC"
+ "\xF6\x92\xA3\x11\x66\xB2\x56\xE0\x75\x3D\x27\x01",
+ .entropylen = 384,
+ .pers = "\x03\x75\x33\x7B\x6B\xE5\x14\xAF\x0E\x43\x33\xCC\xD3"
+ "\xF4\xF0\x8B\x8A\xCC\xFE\x95\xC1\x20\xB9\x56\x3D\x2C"
+ "\x34\xC7\xA1\x4C\xBC\xDC\x0A\x8D\xBE\x68\x28\x89\x2A"
+ "\x92\x10\x05\x4E\xF9\xE2\x51\xF7\x4F\xF4\x48\x76\xC9"
+ "\xCE\xA8\x6D\xC1\xDE\x5C\x05\x95\x77\x24\xB4\x5D\x3D"
+ "\x16\x1D\xCB\x43\xE5\xD3\x01\x96\xCC\x3E\x2E\xE1\x97"
+ "\xB3\x42\xC2\xAB\xEC\x56\xA9\xF9\xF2\x28\x59\x01\x4E"
+ "\xFC\x8A\xC0\x5E\x4E\x33\x30\x91\x96\x93\xBA\xFA\xE1"
+ "\x9F\x20\xC3\xC1\xD1\xC6\xC3\x2C\x59\x8F\x56\xD5\x73"
+ "\xE8\x8D\xCF\xAC\xB1\x85\x3E\xC7\x73\x21\x59\x8D\x0F"
+ "\xF4\xA4\xC4\x0C\xD2\x18\x81\x5F\x3E\x37\xC9\x9F\xD9"
+ "\xDE\x3F\x15\x6F\xAC\x1A\xEC\x5E\x28\xD5\x56\xA2\x65"
+ "\xD2\x7C\x41\xDE\x57\x8C\x60\xAB\xA5\x03\x42\xC8\x3C"
+ "\x70\xC2\xD1\x11\x62\x25\x4E\x17\x58\xBB\x08\x51\x79"
+ "\xE6\xED\xBA\x9A\xA7\x07\xD5\x0E\x89\x43\x31\x4F\x99"
+ "\xEE\xED\xF1\x36\xFA\x1E\xC0\x25\x01\xDA\x19\xC2\x7D"
+ "\x5D\x78\x74\x5C\xC0\x72\x2E\xF1\x7B\x4E\x9C\xDB\xFE"
+ "\x60\x89\x62\x71\x9C\xEA\xD3\xDF\x82\xC7\x8B\xB4\x7B"
+ "\x7B\x7F\x6A\x62\x3C\x57\x76\xA5\x67\x5F\x70\xFB\xE0"
+ "\x1B\x23\x79\x71\xB5\x7C\xEA\x76\x99",
+ .perslen = 256,
+
+ .ent_reseed = "\xE0\x5B\x69\xC5\xF9\xD4\x5A\x1F\xC1\x71\x0C"
+ "\x37\x6F\xFE\x31\xE0\xEF\x3E\x9B\xD5\x46\x43"
+ "\xA2\x15\xFA\x86\x75\x1C\x95\x9F\xE6\xD6\x41"
+ "\x50\x36\x0F\x67\x68\x4A\x72\x32\x85\xB0\xCB"
+ "\xA4\x0D\x1F\xA2\x43\xCA\x30\xF1\x42\xF8\xC4"
+ "\x17\x6A\xD1\x2D\x43\x46\x8C\xA5\x72\x3C\xB1"
+ "\x44\x8E\xA1\x75\xAA\x20\x30\xDD\xCD\x0B\x5A"
+ "\x0D\xE6\x28\xCA\xBC\xA9\x3B\x11\x23\x88\x85"
+ "\xDF\xD8\x84\x11\x89\x7A\x4F\x00\x90\x0B\xD8"
+ "\x8A\x35\xE9\x5F\xEC\x05\x42\x15\xCA\x7E\xA3"
+ "\xEF\xEF\xE3\xB7\xBE\x96\x8C\x36\x7D\x15\x3C"
+ "\x7A\x78\x00\x61\xAF\x62\x45\xA7\x4B\xAE\x4A"
+ "\xFD\xC9\xE0\x89\x53\x36\x71\x8F\x38\xC4\x00"
+ "\x57\xD9\xE6\xC1\xEC\xBF\xF7\x4B\x3F\x55\xD6"
+ "\x54\x15\x72\xB2\x23\x76\xD1\x4E\x8E\x7E\xFB"
+ "\xC8\xD6\xA4\xA4\x7E\x8E\xD8\x76\xD3\xEB\x90"
+ "\x90\xEB\xB3\x84\x26\x34\x93\x36\xCA\xA9\x12"
+ "\xD3\x6D\x84\x07\xE1\x0E\xE7\x63\x24\x54\x90"
+ "\x42\x8C\x6B\xE7\x21\x53\x2D\x16\xE9\x68\xA9"
+ "\xC2\x9A\x7A\x93\x31\x5E\x35\x72\xE2\x0F\x3D"
+ "\x55\x41\x8C\xC5\xD1\xBB\xEE\x5F\x3C\x95\x52"
+ "\x2A\x65\x47\xB6\x84\x6A\x05\x19\xD9\xE7\x68"
+ "\x15\xFA\x49\xD9\x9D\xFD\x47\x9F\xB9\xA6\xBB"
+ "\xA8\xD4\x22\x6C\x8B\x59\x47\xEF\xD1\xD0\xBF"
+ "\xBC\xE4\x53\x31\x2F\xA5\xD4\x2C\x89\xCA\xE5"
+ "\x29\x64\xF8\x51\x2A\x02\xDE\x31\x0D\x54\x0E"
+ "\x0E\xB8\x78\xE6\x2A\x3E\x31\xA2\xA4\xCD\x91"
+ "\x79\xF2\x9B\x04\xA0\xDB\x78\xAC\x0D\xB5\xCA"
+ "\x60\x4C\x08\x96\xCA\x8A\xE9\x93\x9F\x62\x38"
+ "\xAE",
+ .ent_reseed_len = 320,
+ .addtl_reseed = "\xD5\x46\x71\x38\x46\xE0\xC1\x27\x2C\xF1\x07"
+ "\xDD\x29\x73\xD7\xF4\x5A\x3A\xE0\x99\x98\x0A"
+ "\xEB\xA5\x9E\x2E\x49\x21\x7B\x18\xC0\xD8\x3D"
+ "\xEE\x49\xF9\x52\x7C\x55\x5E\x5E\x06\xC2\x7E"
+ "\x34\x3A\xA5\xB7\x78\x21\xC1\xB8\x8B\x4E\x07"
+ "\x1F\x3F\xC4\xB4\x9B\x3F\x20\x2D\xEE\x70\x3B"
+ "\x18\xCF\x2B\x50\x15\x1B\xF3\x6C\xE7\x9F\x2A"
+ "\x2B\x69\x53\xCA\x88\x41\xA9\x07\x31\x14\x55"
+ "\xBD\x75\x49\x68\x98\x48\xCA\x46\xA5\xEC\xAA"
+ "\x9D\x8E\x6F\x40\xBA\xCA\xC8\xE9\x9F\xA4\xC5"
+ "\x94\x89\x2C\x4D\xE4\x0A\x66\xD3\xDB\x1A\xD9"
+ "\xA7\x3F\x6B\x0A\xE0\xE4\xDC\x0B\x8B\x64\xBF"
+ "\xB4\x95\xA1\xAE\x92\xA8\x7C\xE2\x4B\xED\xFD"
+ "\xFD\xE0\x54\x48\x7C\x25\xD6\xD1\x0A\xAB\x5E"
+ "\x33\x2F\x1D\xD3\x62\x47\xAB\x35\x8C\xA1\xC2"
+ "\x75\xDD\x75\xCA\x09\xE1\x38\xDE\x87\x79\x0C"
+ "\xD7\x5D\x3E\x6D\x28\x8F\x12\x98\x2C\x26\x34"
+ "\x91\x0B\x6B\xB7\x73",
+ .addtl_reseed_len = 192,
+
+ .addtla = "\xC8\xE1\x03\x59\xEA\x9F\xD3\x1F\xCC\xCB\x5A\x3E"
+ "\x23\xDB\x47\x75\x1B\x3A\x6C\x0B\xED\xE6\xC0\xB6"
+ "\x4B\x82\x53\x5B\x6D\xEE\x2B\x97\x0F\x59\x07\xA4"
+ "\xFE\xE2\x26\x4F\xFF\xF7\x46\xAF\x62\xC4\x42\xE8"
+ "\x06\xFA\x1F\xAA\x66\xF3\xA4\xCF\x85\x02\x3C\x11"
+ "\xEF\xD2\x16\x13\x7A\xBD\x03\x66\xC3\x4D\x6F\x3A"
+ "\xE5\xD3\xFF\x92\xB6\x45\xB8\x88\x94\x42\x2E\x84"
+ "\x02\xA5\x54\x12\xBF\xCB\xF1\x6E\x1C\x0C\x23\xFE"
+ "\x8A\xFD\xF5\x1A\x4C\xD6\x2A\x34\x7F\x21\x50\xBB"
+ "\x06\x64\x9A\x77\x70\x59\x1D\x12\xD1\xA0\x10\x70"
+ "\xD7\x4F\x3C\xEE\x82\xEF\x5B\x35\x8F\x05\xF6\x51"
+ "\xBC\x28\xE1\xB1\x54\xFF\x25\x12\x16\x2C\x62\xFC"
+ "\xB9\x74\x5E\x78\x41\xB2\x04\x80\x4E\xB1\x43\x2E"
+ "\x88\x7F\x34\xA4\x33\x66\xE8\x68\x60\x54\xEB\xCE"
+ "\xD1\x5F\xC4\xD6\x21\x5E\x22\x1A\x7E\xC5\x6D\xB7"
+ "\x93\x8F\x9C\x77\x6E\x56\xA5\xA8\xF7\xB2\x10\x19",
+ .addtlb = "\xB8\x1E\x9E\xE2\xB3\xE4\x04\x43\x51\x7B\x96\x32"
+ "\xAC\x95\xF2\x1E\x5E\x7A\xBF\x68\xE3\x7A\xCE\xE5"
+ "\x2B\x3B\xB0\x34\x7F\xE1\xB5\x37\x3C\x5B\xD2\x6B"
+ "\x17\xF6\x18\xAF\x7C\x01\xA5\x84\xFE\x07\x0B\x46"
+ "\xCC\x96\x61\xAB\xCD\x81\x95\x8A\x8A\xB6\xD8\xCC"
+ "\x94\x80\x45\xF6\xFF\x95\x3A\xB8\xDC\xBF\xB4\xBF"
+ "\x26\x8C\xE9\x79\x05\x58\x9C\x03\x08\x45\xB5\xC4"
+ "\xD8\xB4\xCD\x76\x13\xAE\x2B\xCC\xB5\x3E\x3C\x65"
+ "\x7A\xAA\xDC\x9B\x0B\x13\x8B\x82\x5A\x39\x60\x9A"
+ "\xF7\xA8\x38\xB5\x83\x8E\x0B\xD1\xE6\xBF\xA1\xDC"
+ "\x30\x45\xCC\x67\x41\x0F\xF9\x86\x27\xE0\x22\x3E"
+ "\x0D\x1F\x92\x13\x16\x9B\x84\x79\x91\xFE\xBC\xDF"
+ "\x15\x6C\xDC\xAE\xC5\x64\x46\x9C\xE8\xEA\xBB\x9D"
+ "\x27\xA2\x1E\xDF\xB2\xF2\x98\xB4\x88\x4E\x22\x5F"
+ "\x3C\xD0\x35\x2C\x5C\x89\xC7\xEC\xE3\xF3\x09\x60"
+ "\xEF\xAC\x78\xBF\x94\xAA\x8C\x30\x7F\xCF\xE4\x4B",
+ .addtllen = 192,
+
+ .expected = "\x93\xFF\x4F\x4A\xA7\xE0\xFC\x3B\xCF\xCE\x57\xCD"
+ "\xFD\xE9\x94\x6D\x0D\x45\x7E\xA3\x98\xBB\xE6\x54"
+ "\x36\xF9\x92\xE6\xBB\xC5\x93\x16\x69\x35\x01\xF0"
+ "\x5A\xE2\x43\xFC\x73\x7C\xA3\x5C\x5B\x49\x72\x69"
+ "\x6A\xC4\xB6\xD4\xB2\x48\x27\x72\xCA\xE3\xF3\xB8"
+ "\xD6\x95\x9F\x39\xC8\xD7\x72\xAF\xC2\x7C\x75\xE5"
+ "\xA4\xF7\x52\x4F\xDF\x80\x75\xCA\x4B\xFA\x75\x9A"
+ "\x7A\x8D\x48\x94\x30\x1C\x82\x5E\xD6\x3F\xF1\x78"
+ "\x84\xAA\x8D\x8B\x4F\x6A\x20\x12\xA2\x65\xC5\x02"
+ "\x32\xA1\xE4\x6B\x86\x2F\xCF\x92\xCD\x01\x55\xF7"
+ "\xB8\xAB\xC3\x2C\x42\xC3\xFD\x9B\x59\x2D\x47\x8E"
+ "\xB6\x8D\xE7\x04\x2E\x67\xD9\x07\x14\xA3\xF2\x74"
+ "\x79\x9C\xAB\xC6\xD6\x52\x3E\x91\x81\xA4\x3C\x9A"
+ "\x3E\x10\x1E\xD0\x28\xBC\x1C\x50\xF0\xB6\xEC\x01"
+ "\xE5\x40\x16\x08\xB5\x58\xE0\xC4\xC2\x9A\xBB\x13"
+ "\xAB\x10\x4B\x07\x24\x09\xEB\xF9\x5E\xAA\x3E\x3A"
+ "\x25\x34\x5B\x97\x92\xF9\x46\x8A\x8E\x5A\x06\x9C"
+ "\x2B\x1C\x8E\x47\x19\xC3\x3B\x14\x8A\xC1\xEB\xF7"
+ "\xB0\xA2\x05\xE0\x70\x12\x88\x21\xFF\xC0\x35\x6D"
+ "\xE9\x08\x7E\x11\x6E\xD7\x16\x48\x24\x43\xAF\x33"
+ "\xA3\x48\x44\x91\xC5\x32\x1D\x87\xF6\x9B\x10\x1C"
+ "\xA4\x7A\x74\x23\xB3\xFC\xB9\x87\x08\xE6\x9A\xEF"
+ "\xD5\x93\x82\x17\xD4\x78\xDA\x46\x34\xC2\x61\x8C"
+ "\xB7\x53\x89\xC4\x8A\xD8\xA0\x2E\xCE\xCA\x24\x16"
+ "\xF0\x18\x7F\xC3\x12\x3F\xD0\xB1\xEF\x37\x99\xA8"
+ "\x04\x1F\x76\x50\x81\x08\xCD\x4D\x43\xEF\x64\xB6"
+ "\x03\x57\xB7\x5F\xDD\xF6\xBA\x34\xE2\x88\xE7\x1F"
+ "\x62\xA5\xA4\x05\xEB\x1A\xFE\x0B\xFE\x74\x7D\x64"
+ "\x29\x83\xE8\x0B\x97\x7D\x94\x5B\xF9\x3C\x8E\xC8"
+ "\x6B\xCD\xAD\x63\x32\x6E\x00\xBF\x8E\x57\xF2\x32"
+ "\x88\x53\x17\x40\xE3\xF8\xF8\xD9\xFD\xCD\x76\x84"
+ "\xC6\xFD\xB1\x10\x40\xED\x75\xDD\xBD\x78\x8B\x0A"
+ "\x61\x1E\xCC\xC4\x4F\x95\xF1\x2F\x8F\x5A\xF0\x12"
+ "\x00\xCE\x75\xB8\xE9\xAB\x63\xC0\x7A\xF6\x9A\x47"
+ "\xD2\x3C\xB0\xAD\xAF\x03\xDF\x25\xDD\x0C\x0F\xB6"
+ "\x29\x09\x0F\x28\x5E\xA8\x67\xBB\xC9\x78\xBE\x12"
+ "\xD8\xD6\xD0\x98\x82\x29\xA3\x82\xFB\x8E\x1C\x79"
+ "\x28\x52\x22\x73\x3C\x6F\xB5\x33\xFF\x40\x26\x4C"
+ "\x30\xE4\xE0\x39\x59\x72\x65\x79\x9F\xB7\x89\x87"
+ "\x64\xAC\x45\x11\x0D\xDD\xC0\x44\x5E\x0D\xDF\xDB"
+ "\x91\x42\x5F\x52\x7F\xBB\x66\xEE\x32\x90\x8F\x6F"
+ "\xF8\xB9\xFE\xEA\x42\xFB\x60\x2B\xE3\xD9\xB2\xD1"
+ "\x74\x37\x14\xC6\xDA\x68\xE6\x09",
+ .expectedlen = 512,
+ }
+};
+
+#endif /* _CRYPTO_DRBG_TESTVECS_H */
diff --git a/crypto/drbg.c b/crypto/drbg.c
index 7d8be036e9be8..9c99b2d510e0a 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -93,10 +93,12 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
+#include <linux/once.h>
#include <linux/slab.h>
#include <linux/string_choices.h>
#include <linux/unaligned.h>
#include "drbg.h"
+#include "drbg-testvecs.h"
#include "jitterentropy-kcapi.h"
/* State length in bytes */
@@ -522,7 +524,9 @@ static void drbg_kcapi_exit(struct crypto_tfm *tfm)
* Public API
***************************************************************/
-struct drbg_state *crypto_drbg_alloc(void)
+static int drbg_selftest(void);
+
+static struct drbg_state *__crypto_drbg_alloc(void)
{
struct drbg_state *drbg = kzalloc_obj(*drbg);
@@ -532,6 +536,15 @@ struct drbg_state *crypto_drbg_alloc(void)
mutex_init(&drbg->drbg_mutex);
return drbg;
}
+
+struct drbg_state *crypto_drbg_alloc(void)
+{
+ int err = drbg_selftest();
+
+ if (err)
+ return ERR_PTR(err);
+ return __crypto_drbg_alloc();
+}
EXPORT_SYMBOL_NS_GPL(crypto_drbg_alloc, "CRYPTO_INTERNAL");
/* Set test entropy in the DRBG. */
@@ -635,20 +648,16 @@ EXPORT_SYMBOL_NS_GPL(crypto_drbg_free, "CRYPTO_INTERNAL");
* Note 2: There is no sensible way of testing the reseed counter
* enforcement, so skip it.
*/
-static inline int __init drbg_healthcheck_sanity(void)
+static void drbg_healthcheck_sanity(void)
{
#define OUTBUFLEN 16
u8 buf[OUTBUFLEN];
struct drbg_state *drbg = NULL;
int ret;
- /* only perform test in FIPS mode */
- if (!fips_enabled)
- return 0;
-
drbg = kzalloc_obj(struct drbg_state);
if (!drbg)
- return -ENOMEM;
+ panic("DRBG: out of memory");
guard(mutex_init)(&drbg->drbg_mutex);
drbg->instantiated = true;
@@ -677,8 +686,8 @@ static inline int __init drbg_healthcheck_sanity(void)
pr_devel("DRBG: Sanity tests for failure code paths successfully "
"completed\n");
- kfree(drbg);
- return 0;
+ mutex_destroy(&drbg->drbg_mutex);
+ kfree_sensitive(drbg);
}
static struct rng_alg drbg_alg = {
@@ -694,13 +703,101 @@ static struct rng_alg drbg_alg = {
.base.cra_exit = drbg_kcapi_exit,
};
+DEFINE_FREE(crypto_drbg_free, struct drbg_state *, crypto_drbg_free(_T))
+
+static int drbg_selftest_one_vec(const struct drbg_testvec *test)
+{
+ struct drbg_state *drbg __free(crypto_drbg_free) = NULL;
+ unsigned char *buf __free(kfree_sensitive) = NULL;
+ int err;
+
+ buf = kzalloc(test->expectedlen, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ drbg = __crypto_drbg_alloc();
+ if (IS_ERR(drbg))
+ return PTR_ERR(drbg);
+
+ crypto_drbg_set_entropy(drbg, test->entropy, test->entropylen);
+ err = crypto_drbg_seed(drbg, test->pers, test->perslen);
+ if (err) {
+ pr_err("DRBG: Instantiation failed: %d\n", err);
+ return err;
+ }
+
+ if (test->ent_reseed_len) {
+ crypto_drbg_set_entropy(drbg, test->ent_reseed,
+ test->ent_reseed_len);
+ err = crypto_drbg_seed(drbg, test->addtl_reseed,
+ test->addtl_reseed_len);
+ if (err) {
+ pr_err("DRBG: Reseed failed: %d\n", err);
+ return err;
+ }
+ }
+
+ err = crypto_drbg_get_bytes(drbg, buf, test->expectedlen, test->addtla,
+ test->addtllen);
+ if (err) {
+ pr_err("DRBG: Generation failed (first): %d\n", err);
+ return err;
+ }
+
+ err = crypto_drbg_get_bytes(drbg, buf, test->expectedlen, test->addtlb,
+ test->addtllen);
+ if (err) {
+ pr_err("DRBG: Generation failed (second): %d\n", err);
+ return err;
+ }
+
+ if (memcmp(test->expected, buf, test->expectedlen) != 0) {
+ pr_err("DRBG: Actual output doesn't match expected output\n");
+ return -ELIBBAD;
+ }
+ return 0;
+}
+
+static int drbg_selftest_err;
+
+static void drbg_selftest_once(void)
+{
+ if (!fips_enabled && !IS_ENABLED(CONFIG_CRYPTO_SELFTESTS))
+ return;
+
+ if (fips_enabled)
+ drbg_healthcheck_sanity();
+
+ for (size_t i = 0; i < ARRAY_SIZE(drbg_testvecs); i++) {
+ int err = drbg_selftest_one_vec(&drbg_testvecs[i]);
+
+ if (err) {
+ if (fips_enabled)
+ panic("DRBG self-test %zu failed: %d\n", i,
+ err);
+ else
+ WARN(1, "DRBG self-test %zu failed: %d\n", i,
+ err);
+ drbg_selftest_err = err;
+ break;
+ }
+ }
+ if (fips_enabled)
+ pr_info("DRBG: self-tests passed\n");
+}
+
+static int drbg_selftest(void)
+{
+ DO_ONCE_SLEEPABLE(drbg_selftest_once);
+ return drbg_selftest_err;
+}
+
static int __init drbg_init(void)
{
- int ret;
+ int err = drbg_selftest();
- ret = drbg_healthcheck_sanity();
- if (ret)
- return ret;
+ if (err)
+ return err;
/*
* In FIPS mode, boost the algorithm priority to ensure that when users
--
2.56.0
next prev parent reply other threads:[~2026-10-18 20:49 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-18 20:46 [PATCH 00/14] crypto: Remove the unnecessary crypto_rng API Eric Biggers
2026-10-18 20:46 ` [PATCH 01/14] crypto: drbg - Don't use uninitialized stack data Eric Biggers
2026-10-18 20:46 ` [PATCH 02/14] crypto: rng - Remove unnecessary inclusions of internal/rng.h Eric Biggers
2026-10-18 20:46 ` [PATCH 03/14] crypto: jitterentropy - Move health check to first use Eric Biggers
2026-10-18 20:46 ` [PATCH 04/14] crypto: jitterentropy - Add library API Eric Biggers
2026-10-18 20:46 ` [PATCH 05/14] crypto: drbg - Use jitterentropy " Eric Biggers
2026-10-18 20:46 ` [PATCH 06/14] crypto: drbg - Add " Eric Biggers
2026-10-18 20:46 ` Eric Biggers [this message]
2026-10-18 20:46 ` [PATCH 08/14] crypto: algif_rng - Use DRBG and jitterentropy library APIs Eric Biggers
2026-10-18 20:46 ` [PATCH 09/14] crypto: stdrng - Reimplement "stdrng" using direct DRBG calls Eric Biggers
2026-10-18 20:46 ` [PATCH 10/14] crypto: drbg - Remove crypto_rng support Eric Biggers
2026-10-18 20:46 ` [PATCH 11/14] crypto: jitterentropy " Eric Biggers
2026-10-18 20:46 ` [PATCH 12/14] crypto: jitterentropy - Remove the kconfig prompt Eric Biggers
2026-10-18 20:46 ` [PATCH 13/14] crypto: rng - Remove the rng algorithm type Eric Biggers
2026-10-18 20:46 ` [PATCH 14/14] crypto: stdrng - Make crypto_stdrng_get_bytes() take size_t Eric Biggers
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261018204618.104876-8-ebiggers@kernel.org \
--to=ebiggers@kernel.org \
--cc=herbert@gondor.apana.org.au \
--cc=linux-crypto@vger.kernel.org \
--cc=smueller@chronox.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.