xref: /netbsd-src/sys/lib/libkern/rngtest.c (revision 8efd1f3e957f4d611bf77a14b269acbd17cf6366)
1*8efd1f3eSriastradh /*	$NetBSD: rngtest.c,v 1.4 2018/09/03 18:52:33 riastradh Exp $ */
23afd44cfStls 
33afd44cfStls /*-
43afd44cfStls  * Copyright (c) 2011 The NetBSD Foundation, Inc.
53afd44cfStls  * All rights reserved.
63afd44cfStls  *
73afd44cfStls  * This code is derived from software contributed to The NetBSD Foundation
83afd44cfStls  * by Thor Lancelot Simon.
93afd44cfStls  *
103afd44cfStls  * Redistribution and use in source and binary forms, with or without
113afd44cfStls  * modification, are permitted provided that the following conditions
123afd44cfStls  * are met:
133afd44cfStls  * 1. Redistributions of source code must retain the above copyright
143afd44cfStls  *    notice, this list of conditions and the following disclaimer.
153afd44cfStls  * 2. Redistributions in binary form must reproduce the above copyright
163afd44cfStls  *    notice, this list of conditions and the following disclaimer in the
173afd44cfStls  *    documentation and/or other materials provided with the distribution.
183afd44cfStls  *
193afd44cfStls  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
203afd44cfStls  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
213afd44cfStls  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
223afd44cfStls  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
233afd44cfStls  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
243afd44cfStls  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
253afd44cfStls  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
263afd44cfStls  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
273afd44cfStls  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
283afd44cfStls  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
293afd44cfStls  * POSSIBILITY OF SUCH DAMAGE.
303afd44cfStls  */
313afd44cfStls 
323afd44cfStls /* fips140.c	1.5 (Qualcomm) 02/09/02 */
333afd44cfStls /*
343afd44cfStls This software is free for commercial and non-commercial use
353afd44cfStls subject to the following conditions.
363afd44cfStls 
373afd44cfStls Copyright remains vested in QUALCOMM Incorporated, and Copyright
383afd44cfStls notices in the code are not to be removed.  If this package is used in
393afd44cfStls a product, QUALCOMM should be given attribution as the author this
403afd44cfStls software.  This can be in the form of a textual message at program
413afd44cfStls startup or in documentation (online or textual) provided with the
423afd44cfStls package.
433afd44cfStls 
443afd44cfStls Redistribution and use in source and binary forms, with or without
453afd44cfStls modification, are permitted provided that the following conditions are
463afd44cfStls met:
473afd44cfStls 
483afd44cfStls 1. Redistributions of source code must retain the copyright notice,
493afd44cfStls    this list of conditions and the following disclaimer.
503afd44cfStls 
513afd44cfStls 2. Redistributions in binary form must reproduce the above copyright
523afd44cfStls    notice, this list of conditions and the following disclaimer in the
533afd44cfStls    documentation and/or other materials provided with the
543afd44cfStls    distribution.
553afd44cfStls 
563afd44cfStls 3. All advertising materials mentioning features or use of this
573afd44cfStls    software must display the following acknowledgement:  This product
583afd44cfStls    includes software developed by QUALCOMM Incorporated.
593afd44cfStls 
603afd44cfStls THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
613afd44cfStls WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
623afd44cfStls MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
633afd44cfStls IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
643afd44cfStls INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
653afd44cfStls (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
663afd44cfStls SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
673afd44cfStls HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
683afd44cfStls STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
693afd44cfStls IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
703afd44cfStls POSSIBILITY OF SUCH DAMAGE.
713afd44cfStls 
723afd44cfStls The license and distribution terms for any publically available version
733afd44cfStls or derivative of this code cannot be changed, that is, this code cannot
743afd44cfStls simply be copied and put under another distribution license including
753afd44cfStls the GNU Public License.
763afd44cfStls */
773afd44cfStls 
783afd44cfStls /* Run FIPS 140 statistical tests on a file */
793afd44cfStls 
803afd44cfStls /* written by Greg Rose, Copyright C 2000 QUALCOMM Incorporated */
813afd44cfStls 
823afd44cfStls /*
833afd44cfStls  * Modified for in-kernel use (API adjustments, conversion from
843afd44cfStls  * floating to fixed-point chi-sq computation) by Thor Lancelot
853afd44cfStls  * Simon.
863afd44cfStls  *
873afd44cfStls  * A comment on appropriate use of this test and the infamous FIPS 140
883afd44cfStls  * "continuous output test" (COT):  Both tests are very appropriate for
893afd44cfStls  * software interfaces to hardware implementations, and will quickly tell
903afd44cfStls  * you if any number of very bad things have happened to your RNG: perhaps
913afd44cfStls  * it has come disconnected from the rest of the system, somehow, and you
923afd44cfStls  * are getting only unconditioned bus noise (read: clock edges from the
933afd44cfStls  * loudest thing in your system).  Perhaps it has ceased to latch a shift
943afd44cfStls  * register and is feeding you the same data over and over again.  Perhaps
953afd44cfStls  * it is not really random at all but was sold to you as such.  Perhaps it
963afd44cfStls  * is not actually *there* (Intel chipset RNG anyone?) but claims to be,
973afd44cfStls  * and is feeding you 01010101 on every register read.
983afd44cfStls  *
993afd44cfStls  * However, when applied to software RNGs, the situation is quite different.
1003afd44cfStls  * Most software RNGs use a modern hash function or cipher as an output
1013afd44cfStls  * stage.  The resulting bitstream assuredly *should* pass both the
1023afd44cfStls  * "continuous output" (no two consecutive samples identical) and
1033afd44cfStls  * statistical tests: if it does not, the cryptographic primitive or its
1043afd44cfStls  * implementation is terribly broken.
1053afd44cfStls  *
1063afd44cfStls  * There is still value to this test: it will tell you if you inadvertently
1073afd44cfStls  * terribly break your implementation of the software RNG.  Which is a thing
1083afd44cfStls  * that has in fact happened from time to time, even to the careful (or
1093afd44cfStls  * paranoid).  But it will not tell you if there is a problem with the
1103afd44cfStls  * _input_ to that final cryptographic primitive -- the bits that are hashed
1113afd44cfStls  * or the key to the cipher -- and if an adversary can find one, you're
1123afd44cfStls  * still toast.
1133afd44cfStls  *
1143afd44cfStls  * The situation is -- sadly -- similar with hardware RNGs that are
1153afd44cfStls  * certified to one of the standards such as X9.31 or SP800-90.  In these
1163afd44cfStls  * cases the hardware vendor has hidden the actual random bitstream behind
1173afd44cfStls  * a hardware cipher/hash implementation that should, indeed, produce good
1183afd44cfStls  * quality random numbers that pass will pass this test -- whether the
1193afd44cfStls  * underlying bitstream is trustworthy or not.
1203afd44cfStls  *
1213afd44cfStls  * However, this test (and the COT) will still probably tell you if the
1223afd44cfStls  * thing fell off the bus, etc.  Which is a thing that has in fact
1233afd44cfStls  * happened from time to time, even to the fully certified...
1243afd44cfStls  *
1253afd44cfStls  * This module does not (yet?) implement the Continuous Output Test.  When
1263afd44cfStls  * I call that test "infamous", it's because it obviously reduces the
1273afd44cfStls  * backtracking resistance of any implementation that includes it -- the
1283afd44cfStls  * implementation has to store the entire previous RNG output in order to
1293afd44cfStls  * perform the required comparison; not just periodically but all the time
1303afd44cfStls  * when operating at all.  Nonetheless, it has obvious value for
1313afd44cfStls  * hardware implementations where it will quickly and surely detect a
1323afd44cfStls  * severe failure; but as of this writing several of the latest comments
1333afd44cfStls  * on SP800-90 recommend removing any requirement for the COT and my
1343afd44cfStls  * personal tendency is to agree.  It's easy to add if you really need it.
1353afd44cfStls  *
1363afd44cfStls  */
1373afd44cfStls 
1383afd44cfStls #include <sys/types.h>
1393afd44cfStls #include <sys/systm.h>
1403afd44cfStls #include <sys/rngtest.h>
1413afd44cfStls 
1423afd44cfStls #include <lib/libkern/libkern.h>
1433afd44cfStls 
1443afd44cfStls #include <sys/cdefs.h>
145*8efd1f3eSriastradh __KERNEL_RCSID(0, "$NetBSD: rngtest.c,v 1.4 2018/09/03 18:52:33 riastradh Exp $");
1463afd44cfStls 
1473afd44cfStls #ifndef _KERNEL
1483afd44cfStls static inline int
printf(const char * __restrict format,...)149916c58b8Sjoerg printf(const char * __restrict format, ...)
1503afd44cfStls {
1513afd44cfStls 	return 0;	/* XXX no standard way to do output in libkern? */
1523afd44cfStls }
1533afd44cfStls #endif
1543afd44cfStls 
1553afd44cfStls int bitnum = 0;
1563afd44cfStls 
1573afd44cfStls const int minrun[7] = {0, 2315, 1114, 527, 240, 103, 103};
1583afd44cfStls const int maxrun[7] = {0, 2685, 1386, 723, 384, 209, 209};
1593afd44cfStls #define LONGRUN	26
1603afd44cfStls #define MINONES 9725
1613afd44cfStls #define MAXONES 10275
1623afd44cfStls #define MINPOKE 2.16
1633afd44cfStls #define MAXPOKE 46.17
1643afd44cfStls #define PRECISION 100000
1653afd44cfStls 
1663afd44cfStls const int longrun = LONGRUN;
1673afd44cfStls const int minones = MINONES;
1683afd44cfStls const int maxones = MAXONES;
1693afd44cfStls const long long minpoke = (MINPOKE * PRECISION);
1703afd44cfStls const long long maxpoke = (MAXPOKE * PRECISION);
1713afd44cfStls 
1723afd44cfStls /* end of run */
1733afd44cfStls static void
endrun(rngtest_t * const rc,const int last,int run)1743afd44cfStls endrun(rngtest_t *const rc, const int last, int run)
1753afd44cfStls {
1763afd44cfStls 	if (run >= longrun) {
1773afd44cfStls 		printf("Kernel RNG \"%s\" long run test FAILURE: "
1783afd44cfStls 		       "Run of %d %ds found\n", rc->rt_name, run, last);
1793afd44cfStls 		++rc->rt_nerrs;
1803afd44cfStls 	}
1813afd44cfStls 	if (run > 6)
1823afd44cfStls 		run = 6;
1833afd44cfStls 	++rc->rt_runs[last][run];
1843afd44cfStls }
1853afd44cfStls 
1863afd44cfStls int
rngtest(rngtest_t * const rc)1873afd44cfStls rngtest(rngtest_t *const rc)
1883afd44cfStls {
1893afd44cfStls 	int i;
1903afd44cfStls 	uint8_t *p;
1913afd44cfStls 	int c;
1923afd44cfStls 	long long X;
1933afd44cfStls 	int last;
1943afd44cfStls 	int run;
1953afd44cfStls 
1963afd44cfStls 	/* Enforce sanity for most members of the context */
1973afd44cfStls 	memset(rc->rt_poker, 0, sizeof(rc->rt_poker));
1983afd44cfStls 	memset(rc->rt_runs, 0, sizeof(rc->rt_runs));
1993afd44cfStls 	rc->rt_nerrs = 0;
2003afd44cfStls 	rc->rt_name[sizeof(rc->rt_name) - 1] = '\0';
2013afd44cfStls 
2023afd44cfStls 	/* monobit test */
2033afd44cfStls 	for (p = rc->rt_b, c = 0; p < &rc->rt_b[sizeof rc->rt_b]; ++p)
204*8efd1f3eSriastradh 		c += popcount(*p);
2053afd44cfStls 	if (c <= minones || maxones <= c) {
2063afd44cfStls 		printf("Kernel RNG \"%s\" monobit test FAILURE: %d ones\n",
2073afd44cfStls 		       rc->rt_name, c);
2083afd44cfStls 		++rc->rt_nerrs;
2093afd44cfStls 	}
2103afd44cfStls 	/* poker test */
2113afd44cfStls 	for (p = rc->rt_b; p < &rc->rt_b[sizeof rc->rt_b]; ++p) {
2123afd44cfStls 		++rc->rt_poker[*p & 0xF];
2133afd44cfStls 		++rc->rt_poker[(*p >> 4) & 0xF];
2143afd44cfStls 	}
2153afd44cfStls 	for (X = i = 0; i < 16; ++i) {
2163afd44cfStls 		X += rc->rt_poker[i] * rc->rt_poker[i];
2173afd44cfStls 	}
2183afd44cfStls 	X *= PRECISION;
2193afd44cfStls 	X = 16 * X / 5000 - 5000 * PRECISION;
2203afd44cfStls 	if (X <= minpoke || maxpoke <= X) {
2213afd44cfStls 		printf("Kernel RNG \"%s\" poker test failure: "
2223afd44cfStls 		       "parameter X = %lld.%lld\n", rc->rt_name,
2233afd44cfStls 		       (X / PRECISION), (X % PRECISION));
2243afd44cfStls 		++rc->rt_nerrs;
2253afd44cfStls 	}
2263afd44cfStls 	/* runs test */
2273afd44cfStls 	last = (rc->rt_b[0] >> 7) & 1;
2283afd44cfStls 	run = 0;
2293afd44cfStls 	for (p = rc->rt_b; p < &rc->rt_b[sizeof rc->rt_b]; ++p) {
2303afd44cfStls 		c = *p;
2313afd44cfStls 		for (i = 7; i >= 0; --i) {
2323afd44cfStls 			if (((c >> i) & 1) != last) {
2333afd44cfStls 				endrun(rc, last, run);
2343afd44cfStls 				run = 0;
2353afd44cfStls 				last = (c >> i) & 1;
2363afd44cfStls 			}
2373afd44cfStls 			++run;
2383afd44cfStls 		}
2393afd44cfStls 	}
2403afd44cfStls 	endrun(rc, last, run);
2413afd44cfStls 
2423afd44cfStls 	for (run = 1; run <= 6; ++run) {
2433afd44cfStls 		for (last = 0; last <= 1; ++last) {
2443afd44cfStls 			if (rc->rt_runs[last][run] <= minrun[run]) {
2453afd44cfStls 				printf("Kernel RNG \"%s\" runs test FAILURE: "
24696b890b3Sriastradh 				       "too few runs of %d %ds (%d <= %d)\n",
2473afd44cfStls 				       rc->rt_name, run, last,
2483afd44cfStls 				       rc->rt_runs[last][run], minrun[run]);
2493afd44cfStls 				++rc->rt_nerrs;
2503afd44cfStls 			} else if (rc->rt_runs[last][run] >= maxrun[run]) {
2513afd44cfStls 				printf("Kernel RNG \"%s\" runs test FAILURE: "
25296b890b3Sriastradh 				       "too many runs of %d %ds (%d >= %d)\n",
2533afd44cfStls 				       rc->rt_name, run, last,
2543afd44cfStls 				       rc->rt_runs[last][run], maxrun[run]);
2553afd44cfStls 				++rc->rt_nerrs;
2563afd44cfStls 			}
2573afd44cfStls 		}
2583afd44cfStls 	}
2593afd44cfStls 	memset(rc->rt_b, 0, sizeof(rc->rt_b));
2603afd44cfStls 	return rc->rt_nerrs;
2613afd44cfStls }
262