Module Name:    src
Committed By:   riastradh
Date:           Mon Sep  2 20:09:30 UTC 2019

Modified Files:
        src/sys/conf: files
        src/sys/dev: rndpseudo.c
        src/sys/kern: subr_cprng.c
        src/sys/rump/kern/lib/libcrypto: Makefile
        src/sys/rump/librump/rumpkern: Makefile.rumpkern
        src/sys/sys: cprng.h
Added Files:
        src/sys/crypto/nist_hash_drbg: files.nist_hash_drbg nist_hash_drbg.c
            nist_hash_drbg.h
Removed Files:
        src/sys/crypto/nist_ctr_drbg: files.nist_ctr_drbg
            nist_ctr_aes_rijndael.h nist_ctr_drbg.c nist_ctr_drbg.h
            nist_ctr_drbg_aes128.h nist_ctr_drbg_aes256.h
            nist_ctr_drbg_config.h

Log Message:
Switch from NIST CTR_DRBG with AES to NIST Hash_DRBG with SHA-256.

Benefits:

- larger seeds -- a 128-bit key alone is not enough for `128-bit security'
- better resistance to timing side channels than AES
- a better-understood security story (https://eprint.iacr.org/2018/349)
- no loss in compliance with US government standards that nobody ever
  got fired for choosing, at least in the US-dominated western world
- no dirty endianness tricks
- self-tests

Drawbacks:

- performance hit: throughput is reduced to about 1/3 in naive measurements
  => possible to mitigate by using hardware SHA-256 instructions
  => all you really need is 32 bytes to seed a userland PRNG anyway
  => if we just used ChaCha this would go away...

XXX pullup-7
XXX pullup-8
XXX pullup-9


To generate a diff of this commit:
cvs rdiff -u -r1.1237 -r1.1238 src/sys/conf/files
cvs rdiff -u -r1.1 -r0 src/sys/crypto/nist_ctr_drbg/files.nist_ctr_drbg \
    src/sys/crypto/nist_ctr_drbg/nist_ctr_drbg.c \
    src/sys/crypto/nist_ctr_drbg/nist_ctr_drbg_config.h
cvs rdiff -u -r1.2 -r0 src/sys/crypto/nist_ctr_drbg/nist_ctr_aes_rijndael.h \
    src/sys/crypto/nist_ctr_drbg/nist_ctr_drbg_aes128.h \
    src/sys/crypto/nist_ctr_drbg/nist_ctr_drbg_aes256.h
cvs rdiff -u -r1.3 -r0 src/sys/crypto/nist_ctr_drbg/nist_ctr_drbg.h
cvs rdiff -u -r0 -r1.1 src/sys/crypto/nist_hash_drbg/files.nist_hash_drbg \
    src/sys/crypto/nist_hash_drbg/nist_hash_drbg.c \
    src/sys/crypto/nist_hash_drbg/nist_hash_drbg.h
cvs rdiff -u -r1.37 -r1.38 src/sys/dev/rndpseudo.c
cvs rdiff -u -r1.30 -r1.31 src/sys/kern/subr_cprng.c
cvs rdiff -u -r1.4 -r1.5 src/sys/rump/kern/lib/libcrypto/Makefile
cvs rdiff -u -r1.175 -r1.176 src/sys/rump/librump/rumpkern/Makefile.rumpkern
cvs rdiff -u -r1.14 -r1.15 src/sys/sys/cprng.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/conf/files
diff -u src/sys/conf/files:1.1237 src/sys/conf/files:1.1238
--- src/sys/conf/files:1.1237	Sat Jun 15 06:40:34 2019
+++ src/sys/conf/files	Mon Sep  2 20:09:29 2019
@@ -1,4 +1,4 @@
-#	$NetBSD: files,v 1.1237 2019/06/15 06:40:34 maxv Exp $
+#	$NetBSD: files,v 1.1238 2019/09/02 20:09:29 riastradh Exp $
 #	@(#)files.newconf	7.5 (Berkeley) 5/10/93
 
 version 	20171118
@@ -196,8 +196,8 @@ include "crypto/camellia/files.camellia"
 # General-purpose crypto processing framework.
 include "opencrypto/files.opencrypto"
 
-# NIST SP800.90 CTR DRBG
-include "crypto/nist_ctr_drbg/files.nist_ctr_drbg"
+# NIST SP800-90A Hash_DRBG
+include "crypto/nist_hash_drbg/files.nist_hash_drbg"
 
 # ChaCha-based fast PRNG
 include "crypto/cprng_fast/files.cprng_fast"

Index: src/sys/dev/rndpseudo.c
diff -u src/sys/dev/rndpseudo.c:1.37 src/sys/dev/rndpseudo.c:1.38
--- src/sys/dev/rndpseudo.c:1.37	Mon Sep  3 16:29:30 2018
+++ src/sys/dev/rndpseudo.c	Mon Sep  2 20:09:30 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: rndpseudo.c,v 1.37 2018/09/03 16:29:30 riastradh Exp $	*/
+/*	$NetBSD: rndpseudo.c,v 1.38 2019/09/02 20:09:30 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 1997-2013 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rndpseudo.c,v 1.37 2018/09/03 16:29:30 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rndpseudo.c,v 1.38 2019/09/02 20:09:30 riastradh Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_compat_netbsd.h"
@@ -360,11 +360,12 @@ rnd_read(struct file *fp, off_t *offp, s
 	 * Choose a CPRNG to use -- either the per-open CPRNG, if this
 	 * is /dev/random or a long read, or the per-CPU one otherwise.
 	 *
-	 * XXX NIST_BLOCK_KEYLEN_BYTES is a detail of the cprng(9)
+	 * XXX NIST_HASH_DRBG_MIN_SEEDLEN_BYTES is a detail of the cprng(9)
 	 * implementation and as such should not be mentioned here.
 	 */
 	struct cprng_strong *const cprng =
-	    ((ctx->rc_hard || (uio->uio_resid > NIST_BLOCK_KEYLEN_BYTES))?
+	    ((ctx->rc_hard ||
+		(uio->uio_resid > NIST_HASH_DRBG_MIN_SEEDLEN_BYTES))?
 		rnd_ctx_cprng(ctx) : rnd_percpu_cprng());
 
 	/*

Index: src/sys/kern/subr_cprng.c
diff -u src/sys/kern/subr_cprng.c:1.30 src/sys/kern/subr_cprng.c:1.31
--- src/sys/kern/subr_cprng.c:1.30	Wed Jul 10 17:32:37 2019
+++ src/sys/kern/subr_cprng.c	Mon Sep  2 20:09:30 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: subr_cprng.c,v 1.30 2019/07/10 17:32:37 maxv Exp $ */
+/*	$NetBSD: subr_cprng.c,v 1.31 2019/09/02 20:09:30 riastradh Exp $ */
 
 /*-
  * Copyright (c) 2011-2013 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_cprng.c,v 1.30 2019/07/10 17:32:37 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_cprng.c,v 1.31 2019/09/02 20:09:30 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -53,7 +53,7 @@ __KERNEL_RCSID(0, "$NetBSD: subr_cprng.c
 #include <sys/rngtest.h>
 #endif
 
-#include <crypto/nist_ctr_drbg/nist_ctr_drbg.h>
+#include <crypto/nist_hash_drbg/nist_hash_drbg.h>
 
 #if defined(__HAVE_CPU_COUNTER)
 #include <machine/cpu_counter.h>
@@ -77,7 +77,8 @@ cprng_init(void)
 {
 	static struct sysctllog *random_sysctllog;
 
-	nist_ctr_initialize();
+	if (nist_hash_drbg_initialize() != 0)
+		panic("NIST Hash_DRBG failed self-test");
 
 	sysctl_createv(&random_sysctllog, 0, NULL, NULL,
 		       CTLFLAG_PERMANENT,
@@ -120,7 +121,7 @@ struct cprng_strong {
 	struct selinfo	cs_selq;
 	struct rndsink	*cs_rndsink;
 	bool		cs_ready;
-	NIST_CTR_DRBG	cs_drbg;
+	NIST_HASH_DRBG	cs_drbg;
 
 	/* XXX Kludge for /dev/random `information-theoretic' properties.   */
 	unsigned int	cs_remaining;
@@ -146,23 +147,23 @@ cprng_strong_create(const char *name, in
 	mutex_init(&cprng->cs_lock, MUTEX_DEFAULT, ipl);
 	cv_init(&cprng->cs_cv, cprng->cs_name);
 	selinit(&cprng->cs_selq);
-	cprng->cs_rndsink = rndsink_create(NIST_BLOCK_KEYLEN_BYTES,
+	cprng->cs_rndsink = rndsink_create(NIST_HASH_DRBG_MIN_SEEDLEN_BYTES,
 	    &cprng_strong_rndsink_callback, cprng);
 
 	/* Get some initial entropy.  Record whether it is full entropy.  */
-	uint8_t seed[NIST_BLOCK_KEYLEN_BYTES];
+	uint8_t seed[NIST_HASH_DRBG_MIN_SEEDLEN_BYTES];
 	mutex_enter(&cprng->cs_lock);
 	cprng->cs_ready = rndsink_request(cprng->cs_rndsink, seed,
 	    sizeof(seed));
-	if (nist_ctr_drbg_instantiate(&cprng->cs_drbg, seed, sizeof(seed),
+	if (nist_hash_drbg_instantiate(&cprng->cs_drbg, seed, sizeof(seed),
 		&cc, sizeof(cc), cprng->cs_name, sizeof(cprng->cs_name)))
-		/* XXX Fix nist_ctr_drbg API so this can't happen.  */
-		panic("cprng %s: NIST CTR_DRBG instantiation failed",
+		/* XXX Fix nist_hash_drbg API so this can't happen.  */
+		panic("cprng %s: NIST Hash_DRBG instantiation failed",
 		    cprng->cs_name);
 	explicit_memset(seed, 0, sizeof(seed));
 
 	if (ISSET(flags, CPRNG_HARD))
-		cprng->cs_remaining = NIST_BLOCK_KEYLEN_BYTES;
+		cprng->cs_remaining = NIST_HASH_DRBG_MIN_SEEDLEN_BYTES;
 	else
 		cprng->cs_remaining = 0;
 
@@ -188,7 +189,7 @@ cprng_strong_destroy(struct cprng_strong
 	KASSERT(!select_has_waiters(&cprng->cs_selq)) /* XXX ? */
 #endif
 
-	nist_ctr_drbg_destroy(&cprng->cs_drbg);
+	nist_hash_drbg_destroy(&cprng->cs_drbg);
 	seldestroy(&cprng->cs_selq);
 	cv_destroy(&cprng->cs_cv);
 	mutex_destroy(&cprng->cs_lock);
@@ -233,18 +234,20 @@ cprng_strong(struct cprng_strong *cprng,
 	 */
 	if (__predict_false(ISSET(cprng->cs_flags, CPRNG_HARD))) {
 		KASSERT(0 < cprng->cs_remaining);
-		KASSERT(cprng->cs_remaining <= NIST_BLOCK_KEYLEN_BYTES);
+		KASSERT(cprng->cs_remaining <=
+		    NIST_HASH_DRBG_MIN_SEEDLEN_BYTES);
 		if (bytes < cprng->cs_remaining) {
 			cprng->cs_remaining -= bytes;
 		} else {
 			bytes = cprng->cs_remaining;
-			cprng->cs_remaining = NIST_BLOCK_KEYLEN_BYTES;
+			cprng->cs_remaining = NIST_HASH_DRBG_MIN_SEEDLEN_BYTES;
 			cprng->cs_ready = false;
 			rndsink_schedule(cprng->cs_rndsink);
 		}
-		KASSERT(bytes <= NIST_BLOCK_KEYLEN_BYTES);
+		KASSERT(bytes <= NIST_HASH_DRBG_MIN_SEEDLEN_BYTES);
 		KASSERT(0 < cprng->cs_remaining);
-		KASSERT(cprng->cs_remaining <= NIST_BLOCK_KEYLEN_BYTES);
+		KASSERT(cprng->cs_remaining <=
+		    NIST_HASH_DRBG_MIN_SEEDLEN_BYTES);
 	}
 
 	cprng_strong_generate(cprng, buffer, bytes);
@@ -365,22 +368,22 @@ cprng_strong_poll(struct cprng_strong *c
 }
 
 /*
- * XXX Move nist_ctr_drbg_reseed_advised_p and
- * nist_ctr_drbg_reseed_needed_p into the nist_ctr_drbg API and make
- * the NIST_CTR_DRBG structure opaque.
+ * XXX Move nist_hash_drbg_reseed_advised_p and
+ * nist_hash_drbg_reseed_needed_p into the nist_hash_drbg API and make
+ * the NIST_HASH_DRBG structure opaque.
  */
 static bool
-nist_ctr_drbg_reseed_advised_p(NIST_CTR_DRBG *drbg)
+nist_hash_drbg_reseed_advised_p(NIST_HASH_DRBG *drbg)
 {
 
-	return (drbg->reseed_counter > (NIST_CTR_DRBG_RESEED_INTERVAL / 2));
+	return (drbg->reseed_counter > (NIST_HASH_DRBG_RESEED_INTERVAL / 2));
 }
 
 static bool
-nist_ctr_drbg_reseed_needed_p(NIST_CTR_DRBG *drbg)
+nist_hash_drbg_reseed_needed_p(NIST_HASH_DRBG *drbg)
 {
 
-	return (drbg->reseed_counter >= NIST_CTR_DRBG_RESEED_INTERVAL);
+	return (drbg->reseed_counter >= NIST_HASH_DRBG_RESEED_INTERVAL);
 }
 
 /*
@@ -395,27 +398,27 @@ cprng_strong_generate(struct cprng_stron
 	KASSERT(mutex_owned(&cprng->cs_lock));
 
 	/*
-	 * Generate some data from the NIST CTR_DRBG.  Caller
+	 * Generate some data from the NIST Hash_DRBG.  Caller
 	 * guarantees reseed if we're not ready, and if we exhaust the
 	 * generator, we mark ourselves not ready.  Consequently, this
-	 * call to the CTR_DRBG should not fail.
+	 * call to the Hash_DRBG should not fail.
 	 */
-	if (__predict_false(nist_ctr_drbg_generate(&cprng->cs_drbg, buffer,
+	if (__predict_false(nist_hash_drbg_generate(&cprng->cs_drbg, buffer,
 		    bytes, &cc, sizeof(cc))))
-		panic("cprng %s: NIST CTR_DRBG failed", cprng->cs_name);
+		panic("cprng %s: NIST Hash_DRBG failed", cprng->cs_name);
 
 	/*
 	 * If we've been seeing a lot of use, ask for some fresh
 	 * entropy soon.
 	 */
-	if (__predict_false(nist_ctr_drbg_reseed_advised_p(&cprng->cs_drbg)))
+	if (__predict_false(nist_hash_drbg_reseed_advised_p(&cprng->cs_drbg)))
 		rndsink_schedule(cprng->cs_rndsink);
 
 	/*
 	 * If we just exhausted the generator, inform the next user
 	 * that we need a reseed.
 	 */
-	if (__predict_false(nist_ctr_drbg_reseed_needed_p(&cprng->cs_drbg))) {
+	if (__predict_false(nist_hash_drbg_reseed_needed_p(&cprng->cs_drbg))) {
 		cprng->cs_ready = false;
 		rndsink_schedule(cprng->cs_rndsink); /* paranoia */
 	}
@@ -427,7 +430,7 @@ cprng_strong_generate(struct cprng_stron
 static void
 cprng_strong_reseed(struct cprng_strong *cprng)
 {
-	uint8_t seed[NIST_BLOCK_KEYLEN_BYTES];
+	uint8_t seed[NIST_HASH_DRBG_MIN_SEEDLEN_BYTES];
 
 	KASSERT(mutex_owned(&cprng->cs_lock));
 
@@ -446,7 +449,7 @@ cprng_strong_reseed_from(struct cprng_st
 {
 	const uint32_t cc = cprng_counter();
 
-	KASSERT(bytes == NIST_BLOCK_KEYLEN_BYTES);
+	KASSERT(bytes == NIST_HASH_DRBG_MIN_SEEDLEN_BYTES);
 	KASSERT(mutex_owned(&cprng->cs_lock));
 
 	/*
@@ -474,9 +477,11 @@ cprng_strong_reseed_from(struct cprng_st
 			    cprng->cs_name);
 	}
 
-	if (nist_ctr_drbg_reseed(&cprng->cs_drbg, seed, bytes, &cc, sizeof(cc)))
-		/* XXX Fix nist_ctr_drbg API so this can't happen.  */
-		panic("cprng %s: NIST CTR_DRBG reseed failed", cprng->cs_name);
+	if (nist_hash_drbg_reseed(&cprng->cs_drbg, seed, bytes, &cc,
+		sizeof(cc)))
+		/* XXX Fix nist_hash_drbg API so this can't happen.  */
+		panic("cprng %s: NIST Hash_DRBG reseed failed",
+		    cprng->cs_name);
 
 #if DIAGNOSTIC
 	cprng_strong_rngtest(cprng);
@@ -501,9 +506,9 @@ cprng_strong_rngtest(struct cprng_strong
 
 	(void)strlcpy(rt->rt_name, cprng->cs_name, sizeof(rt->rt_name));
 
-	if (nist_ctr_drbg_generate(&cprng->cs_drbg, rt->rt_b, sizeof(rt->rt_b),
-		NULL, 0))
-		panic("cprng %s: NIST CTR_DRBG failed after reseed",
+	if (nist_hash_drbg_generate(&cprng->cs_drbg, rt->rt_b,
+		sizeof(rt->rt_b), NULL, 0))
+		panic("cprng %s: NIST Hash_DRBG failed after reseed",
 		    cprng->cs_name);
 
 	if (rngtest(rt)) {

Index: src/sys/rump/kern/lib/libcrypto/Makefile
diff -u src/sys/rump/kern/lib/libcrypto/Makefile:1.4 src/sys/rump/kern/lib/libcrypto/Makefile:1.5
--- src/sys/rump/kern/lib/libcrypto/Makefile:1.4	Mon Oct 19 16:16:37 2015
+++ src/sys/rump/kern/lib/libcrypto/Makefile	Mon Sep  2 20:09:30 2019
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.4 2015/10/19 16:16:37 pooka Exp $
+#	$NetBSD: Makefile,v 1.5 2019/09/02 20:09:30 riastradh Exp $
 #
 
 .PATH:	${.CURDIR}/../../../../crypto/arc4				\
@@ -28,8 +28,7 @@ SRCS+=	cast128.c
 SRCS+=	des_ecb.c des_setkey.c des_enc.c des_cbc.c des_module.c
 
 # rijndael
-# rijndael is in rumpkern due to it being used by cprng
-#SRCS+=	rijndael-alg-fst.c rijndael-api-fst.c rijndael.c
+SRCS+=	rijndael-alg-fst.c rijndael-api-fst.c rijndael.c
 
 # skipjack
 SRCS+=	skipjack.c

Index: src/sys/rump/librump/rumpkern/Makefile.rumpkern
diff -u src/sys/rump/librump/rumpkern/Makefile.rumpkern:1.175 src/sys/rump/librump/rumpkern/Makefile.rumpkern:1.176
--- src/sys/rump/librump/rumpkern/Makefile.rumpkern:1.175	Mon May 13 17:49:05 2019
+++ src/sys/rump/librump/rumpkern/Makefile.rumpkern	Mon Sep  2 20:09:30 2019
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile.rumpkern,v 1.175 2019/05/13 17:49:05 bad Exp $
+#	$NetBSD: Makefile.rumpkern,v 1.176 2019/09/02 20:09:30 riastradh Exp $
 #
 
 IOCONFDIR:=	${.PARSEDIR}
@@ -15,8 +15,7 @@ MAN=		rump.3 rump_lwproc.3
 	${RUMPTOP}/../uvm					\
 	${RUMPTOP}/../conf					\
 	${RUMPTOP}/../dev					\
-	${RUMPTOP}/../crypto/nist_ctr_drbg			\
-	${RUMPTOP}/../crypto/rijndael				\
+	${RUMPTOP}/../crypto/nist_hash_drbg			\
 	${RUMPTOP}/../crypto/cprng_fast				\
 	${RUMPTOP}/../secmodel					\
 	${RUMPTOP}/../secmodel/suser				\
@@ -154,10 +153,7 @@ SRCS+=	clock_subr.c
 # sys/dev/crypto
 # Note: these are here only for cprng.  More crypto algos for drivers
 # are available from the rumpkern_crypto component
-SRCS+=	nist_ctr_drbg.c
-SRCS+=	rijndael-alg-fst.c
-SRCS+=	rijndael-api-fst.c
-SRCS+=	rijndael.c
+SRCS+=	nist_hash_drbg.c
 SRCS+=	cprng_fast.c
 
 .include "${RUMPTOP}/Makefile.rump"

Index: src/sys/sys/cprng.h
diff -u src/sys/sys/cprng.h:1.14 src/sys/sys/cprng.h:1.15
--- src/sys/sys/cprng.h:1.14	Sun Apr 29 11:42:09 2018
+++ src/sys/sys/cprng.h	Mon Sep  2 20:09:30 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: cprng.h,v 1.14 2018/04/29 11:42:09 maxv Exp $ */
+/*	$NetBSD: cprng.h,v 1.15 2019/09/02 20:09:30 riastradh Exp $ */
 
 /*-
  * Copyright (c) 2011-2013 The NetBSD Foundation, Inc.
@@ -38,11 +38,11 @@
 
 #include <sys/types.h>
 
-#include <crypto/nist_ctr_drbg/nist_ctr_drbg.h>
+#include <crypto/nist_hash_drbg/nist_hash_drbg.h>
 #include <crypto/cprng_fast/cprng_fast.h>
 
 /*
- * NIST SP800-90 says 2^19 bytes per request for the CTR_DRBG.
+ * NIST SP800-90 says 2^19 bytes per request for the Hash_DRBG.
  */
 #define CPRNG_MAX_LEN	524288
 

Added files:

Index: src/sys/crypto/nist_hash_drbg/files.nist_hash_drbg
diff -u /dev/null src/sys/crypto/nist_hash_drbg/files.nist_hash_drbg:1.1
--- /dev/null	Mon Sep  2 20:09:30 2019
+++ src/sys/crypto/nist_hash_drbg/files.nist_hash_drbg	Mon Sep  2 20:09:29 2019
@@ -0,0 +1,3 @@
+#	$NetBSD: files.nist_hash_drbg,v 1.1 2019/09/02 20:09:29 riastradh Exp $
+
+file	crypto/nist_hash_drbg/nist_hash_drbg.c
Index: src/sys/crypto/nist_hash_drbg/nist_hash_drbg.c
diff -u /dev/null src/sys/crypto/nist_hash_drbg/nist_hash_drbg.c:1.1
--- /dev/null	Mon Sep  2 20:09:30 2019
+++ src/sys/crypto/nist_hash_drbg/nist_hash_drbg.c	Mon Sep  2 20:09:29 2019
@@ -0,0 +1,1127 @@
+/*	$NetBSD: nist_hash_drbg.c,v 1.1 2019/09/02 20:09:29 riastradh Exp $	*/
+
+/*-
+ * Copyright (c) 2019 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Taylor R. Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This file implements Hash_DRBG, a `deterministic random bit
+ * generator' (more commonly known in lay terms and in the cryptography
+ * literature as a pseudorandom bit generator or pseudorandom number
+ * generator), described in
+ *
+ *	Elaine Barker and John Kelsey, `Recommendation for Random
+ *	Number Generation Using Deterministic Random Bit Generators',
+ *	NIST SP800-90A, June 2015.
+ *
+ * This code is meant to work in userland or in kernel.  For a test
+ * program, compile with -DNIST_HASH_DRBG_MAIN to define a `main'
+ * function; for verbose debugging output, compile with
+ * -DNIST_HASH_DRBG_DEBUG, mainly useful if you need to change
+ * something and have to diagnose what's wrong with the known-answer
+ * tests.
+ */
+
+#ifdef _KERNEL
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: nist_hash_drbg.c,v 1.1 2019/09/02 20:09:29 riastradh Exp $");
+#endif
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/sha2.h>
+
+#ifdef _KERNEL
+#include <sys/systm.h>			/* memcpy */
+#include <lib/libkern/libkern.h>	/* KASSERT */
+#define	ASSERT		KASSERT
+#else
+#include <assert.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#define	ASSERT		assert
+#define	CTASSERT	__CTASSERT
+#endif
+
+#include "nist_hash_drbg.h"
+
+#define	secret	/* must not use in variable-time operations; should zero */
+#define	arraycount(A)	(sizeof(A)/sizeof(A[0]))
+
+CTASSERT(0 < NIST_HASH_DRBG_RESEED_INTERVAL);
+CTASSERT(NIST_HASH_DRBG_RESEED_INTERVAL <= INT_MAX);
+CTASSERT(NIST_HASH_DRBG_RESEED_INTERVAL <= ~(~0ull << 48));
+
+/* Instantiation: SHA-256 */
+#define	HASH_LENGTH	SHA256_DIGEST_LENGTH
+#define	HASH_CTX	SHA256_CTX
+#define	hash_init	SHA256_Init
+#define	hash_update	SHA256_Update
+#define	hash_final	SHA256_Final
+
+#define	SEEDLEN_BYTES	NIST_HASH_DRBG_SEEDLEN_BYTES
+
+struct hvec {
+	const void	*hv_base;
+	size_t		hv_len;
+};
+
+static void	hashgen(secret uint8_t *, size_t,
+		    const secret uint8_t[SEEDLEN_BYTES]);
+static void	add8(secret uint8_t *, size_t, const secret uint8_t *, size_t);
+static void	hash_df(secret void *, size_t, const struct hvec *, size_t);
+static void	hash_df_block(secret void *, uint8_t, uint8_t[4],
+		    const struct hvec *, size_t);
+
+/* 10.1.1 Hash_DRBG */
+
+int
+nist_hash_drbg_destroy(struct nist_hash_drbg *D)
+{
+
+	explicit_memset(D, 0, sizeof(*D));
+	D->reseed_counter = UINT_MAX; /* paranoia: make generate fail */
+
+	/* Always return zero for hysterical raisins.  (XXX) */
+	return 0;
+}
+
+/* 10.1.1.2 Instantiation of Hash_DRBG */
+
+int
+nist_hash_drbg_instantiate(secret struct nist_hash_drbg *D,
+    const secret void *entropy, size_t entropylen,
+    const void *nonce, size_t noncelen,
+    const void *personalization, size_t personalizationlen)
+{
+	/*
+	 * 1. seed_material = entropy_input || nonce || personalization_string
+	 */
+	const struct hvec seed_material[] = {
+		{ .hv_base = entropy, .hv_len = entropylen },
+		{ .hv_base = nonce, .hv_len = noncelen },
+		{ .hv_base = personalization, .hv_len = personalizationlen },
+	};
+
+	/*
+	 * 2. seed = Hash_df(seed_material, seedlen)
+	 * 3. V = seed
+	 */
+	CTASSERT(sizeof D->V == SEEDLEN_BYTES);
+	hash_df(D->V, sizeof D->V, seed_material, arraycount(seed_material));
+
+	/* 4. C = Hash_df((0x00 || V), seedlen) */
+	const struct hvec hv[] = {
+		{ .hv_base = (const uint8_t[]) {0x00}, .hv_len = 1 },
+		{ .hv_base = D->V, .hv_len = sizeof D->V },
+	};
+	CTASSERT(sizeof D->C == SEEDLEN_BYTES);
+	hash_df(D->C, sizeof D->C, hv, arraycount(hv));
+
+	/* 5. reseed_counter = 1 */
+	D->reseed_counter = 1;
+
+	/* Always return zero for hysterical raisins.  (XXX) */
+	return 0;
+}
+
+/* 10.1.1.3 Reseeding a Hash_DRBG Instantiation */
+
+int
+nist_hash_drbg_reseed(secret struct nist_hash_drbg *D,
+    const secret void *entropy, size_t entropylen,
+    const void *additional, size_t additionallen)
+{
+	/* 1. seed_material = 0x01 || V || entropy_input || additional_input */
+	const struct hvec seed_material[] = {
+		{ .hv_base = (const uint8_t[]) {0x01}, .hv_len = 1 },
+		{ .hv_base = D->V, .hv_len = sizeof D->V },
+		{ .hv_base = entropy, .hv_len = entropylen },
+		{ .hv_base = additional, .hv_len = additionallen },
+	};
+	uint8_t seed[SEEDLEN_BYTES];
+
+	/*
+	 * 2. seed = Hash_df(seed_material, seedlen)
+	 * 3. V = seed
+	 */
+	CTASSERT(sizeof D->V == SEEDLEN_BYTES);
+	hash_df(seed, sizeof seed, seed_material, arraycount(seed_material));
+	memcpy(D->V, seed, sizeof D->V);
+
+	/* 3. C = Hash_df((0x00 || V), seedlen) */
+	const struct hvec hv[] = {
+		{ .hv_base = (const uint8_t[]) {0x00}, .hv_len = 1 },
+		{ .hv_base = D->V, .hv_len = sizeof D->V },
+	};
+	CTASSERT(sizeof D->C == SEEDLEN_BYTES);
+	hash_df(D->C, sizeof D->C, hv, arraycount(hv));
+
+	/* 5. reseed_counter = 1 */
+	D->reseed_counter = 1;
+
+	/* Always return zero for hysterical raisins.  (XXX) */
+	return 0;
+}
+
+/* 10.1.1.4 Generating Pseudorandom Bits Using Hash_DRBG */
+
+int
+nist_hash_drbg_generate(secret struct nist_hash_drbg *D,
+    secret void *output, size_t outputlen,
+    const void *additional, size_t additionallen)
+{
+	secret HASH_CTX ctx;
+	secret uint8_t H[HASH_LENGTH];
+	uint8_t reseed_counter[4];
+
+	ASSERT(outputlen <= NIST_HASH_DRBG_MAX_REQUEST_BYTES);
+
+	/*
+	 * 1. If reseed_counter > reseed_interval, then return an
+	 * indication that a reseed is required.
+	 */
+	if (D->reseed_counter > NIST_HASH_DRBG_RESEED_INTERVAL)
+		return 1;
+
+	/* 2. If (additional_input != Null), then do: */
+	if (additionallen) {
+		/* 2.1 w = Hash(0x02 || V || additional_input) */
+		secret uint8_t w[HASH_LENGTH];
+
+		hash_init(&ctx);
+		hash_update(&ctx, (const uint8_t[]) {0x02}, 1);
+		hash_update(&ctx, D->V, sizeof D->V);
+		hash_update(&ctx, additional, additionallen);
+		hash_final(w, &ctx);
+
+		/* 2.2 V = (V + w) mod 2^seedlen */
+		add8(D->V, sizeof D->V, w, sizeof w);
+
+		explicit_memset(w, 0, sizeof w);
+	}
+
+	/* 3. (returned_bits) = Hashgen(requested_number_of_bits, V) */
+	hashgen(output, outputlen, D->V);
+
+	/* 4. H = Hash(0x03 || V) */
+	hash_init(&ctx);
+	hash_update(&ctx, (const uint8_t[]) {0x03}, 1);
+	hash_update(&ctx, D->V, sizeof D->V);
+	hash_final(H, &ctx);
+
+	/* 5. V = (V + H + C + reseed_counter) mod 2^seedlen */
+	be32enc(reseed_counter, D->reseed_counter);
+	add8(D->V, sizeof D->V, H, sizeof H);
+	add8(D->V, sizeof D->V, D->C, sizeof D->C);
+	add8(D->V, sizeof D->V, reseed_counter, sizeof reseed_counter);
+
+	/* 6. reseed_counter = reseed_counter + 1 */
+	D->reseed_counter++;
+
+	explicit_memset(&ctx, 0, sizeof ctx);
+	explicit_memset(H, 0, sizeof H);
+
+	/* 7. Return SUCCESS, ... */
+	return 0;
+}
+
+/*
+ * p := H(V) || H(V + 1) || H(V + 2) || ...
+ */
+static void
+hashgen(secret uint8_t *p, size_t n, const secret uint8_t V[SEEDLEN_BYTES])
+{
+	secret uint8_t data[SEEDLEN_BYTES];
+	secret HASH_CTX ctx;
+
+	/* Save a copy so that we can increment it.  */
+	memcpy(data, V, SEEDLEN_BYTES);
+
+	/* Generate block by block into p directly.  */
+	while (HASH_LENGTH <= n) {
+		hash_init(&ctx);
+		hash_update(&ctx, data, SEEDLEN_BYTES);
+		hash_final(p, &ctx);
+
+		p += HASH_LENGTH;
+		n -= HASH_LENGTH;
+		add8(data, sizeof data, (const uint8_t[]) {1}, 1);
+	}
+
+	/*
+	 * If any partial block requested, generate a full block and
+	 * copy the part we need.
+	 */
+	if (n) {
+		secret uint8_t t[HASH_LENGTH];
+
+		hash_init(&ctx);
+		hash_update(&ctx, data, SEEDLEN_BYTES);
+		hash_final(t, &ctx);
+
+		memcpy(p, t, n);
+		explicit_memset(t, 0, sizeof t);
+	}
+
+	explicit_memset(data, 0, sizeof data);
+	explicit_memset(&ctx, 0, sizeof ctx);
+}
+
+/*
+ * s := s + a (big-endian, radix-2^8)
+ */
+static void
+add8(secret uint8_t *s, size_t slen, const secret uint8_t *a, size_t alen)
+{
+	const size_t smax = slen - 1, amax = alen - 1;
+	size_t i;
+	secret unsigned c = 0;
+
+	/* 2^8 c + s_i := s_i + a_i + c */
+	for (i = 0; i < MIN(slen, alen); i++) {
+		c += s[smax - i] + a[amax - i];
+		s[smax - i] = c & 0xff;
+		c >>= 8;
+	}
+
+	/* 2^8 c + s_i := s_i + c */
+	for (; i < slen; i++) {
+		c += s[smax - i];
+		s[smax - i] = c & 0xff;
+		c >>= 8;
+	}
+
+	explicit_memset(&c, 0, sizeof c);
+}
+
+/* 10.4.1 Derivation Function Using a Hash Function (Hash_df) */
+
+static void
+hash_df(void *h, size_t hlen, const struct hvec *input, size_t inputlen)
+{
+	uint8_t *p = h;
+	size_t n = hlen;
+	uint8_t counter = 1;
+	uint8_t hbits[4];
+
+	ASSERT(hlen <= 255*HASH_LENGTH);
+	ASSERT(hlen <= UINT32_MAX/8);
+	be32enc(hbits, 8*hlen);
+
+	while (HASH_LENGTH <= n) {
+		hash_df_block(p, counter++, hbits, input, inputlen);
+		p += HASH_LENGTH;
+		n -= HASH_LENGTH;
+	}
+
+	if (n) {
+		secret uint8_t t[HASH_LENGTH];
+
+		hash_df_block(t, counter, hbits, input, inputlen);
+		memcpy(p, t, n);
+
+		explicit_memset(t, 0, sizeof t);
+	}
+}
+
+static void
+hash_df_block(secret void *h, uint8_t counter, uint8_t hbits[4],
+    const struct hvec *input, size_t inputlen)
+{
+	secret HASH_CTX ctx;
+	size_t i;
+
+	/*
+	 * Hash_df Process, step 4.1:
+	 * Hash(counter || no_of_bits_to_return || input_string)
+	 */
+	hash_init(&ctx);
+	hash_update(&ctx, &counter, 1);
+	hash_update(&ctx, hbits, 4);
+	for (i = 0; i < inputlen; i++) {
+		if (input[i].hv_len)
+			hash_update(&ctx, input[i].hv_base, input[i].hv_len);
+	}
+	hash_final(h, &ctx);
+
+	explicit_memset(&ctx, 0, sizeof ctx);
+}
+
+/*
+ * Known-answer test vectors for Hash_DRBG with SHA-256
+ */
+
+/* Hash_DRBG.PDF, p. 190 */
+static const uint8_t kat_entropy[3][SEEDLEN_BYTES] = {
+	[0] = {
+		0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07,
+		0x08,0x09,0x0a,0x0b, 0x0c,0x0d,0x0e,0x0f,
+		0x10,0x11,0x12,0x13, 0x14,0x15,0x16,0x17,
+		0x18,0x19,0x1a,0x1b, 0x1c,0x1d,0x1e,0x1f,
+		0x20,0x21,0x22,0x23, 0x24,0x25,0x26,0x27,
+		0x28,0x29,0x2a,0x2b, 0x2c,0x2d,0x2e,0x2f,
+		0x30,0x31,0x32,0x33, 0x34,0x35,0x36,
+	},
+	[1] = {			/* for reseed1 */
+		0x80,0x81,0x82,0x83, 0x84,0x85,0x86,0x87,
+		0x88,0x89,0x8a,0x8b, 0x8c,0x8d,0x8e,0x8f,
+		0x90,0x91,0x92,0x93, 0x94,0x95,0x96,0x97,
+		0x98,0x99,0x9a,0x9b, 0x9c,0x9d,0x9e,0x9f,
+		0xa0,0xa1,0xa2,0xa3, 0xa4,0xa5,0xa6,0xa7,
+		0xa8,0xa9,0xaa,0xab, 0xac,0xad,0xae,0xaf,
+		0xb0,0xb1,0xb2,0xb3, 0xb4,0xb5,0xb6,
+	},
+	[2] = {			/* for reseed2 */
+		0xc0,0xc1,0xc2,0xc3, 0xc4,0xc5,0xc6,0xc7,
+		0xc8,0xc9,0xca,0xcb, 0xcc,0xcd,0xce,0xcf,
+		0xd0,0xd1,0xd2,0xd3, 0xd4,0xd5,0xd6,0xd7,
+		0xd8,0xd9,0xda,0xdb, 0xdc,0xdd,0xde,0xdf,
+		0xe0,0xe1,0xe2,0xe3, 0xe4,0xe5,0xe6,0xe7,
+		0xe8,0xe9,0xea,0xeb, 0xec,0xed,0xee,0xef,
+		0xf0,0xf1,0xf2,0xf3, 0xf4,0xf5,0xf6,
+	},
+};
+
+static const uint8_t kat_nonce[] = {
+	0x20,0x21,0x22,0x23, 0x24,0x25,0x26,0x27,
+};
+
+static const struct hvec kat_zero = { .hv_base = 0, .hv_len = 0 };
+
+static const struct hvec kat_personalization = {
+	.hv_len = 55,
+	.hv_base = (const void *)(const uint8_t[]) { /* p. 208 */
+		0x40,0x41,0x42,0x43, 0x44,0x45,0x46,0x47,
+		0x48,0x49,0x4a,0x4b, 0x4c,0x4d,0x4e,0x4f,
+		0x50,0x51,0x52,0x53, 0x54,0x55,0x56,0x57,
+		0x58,0x59,0x5a,0x5b, 0x5c,0x5d,0x5e,0x5f,
+		0x60,0x61,0x62,0x63, 0x64,0x65,0x66,0x67,
+		0x68,0x69,0x6a,0x6b, 0x6c,0x6d,0x6e,0x6f,
+		0x70,0x71,0x72,0x73, 0x74,0x75,0x76,
+	},
+};
+
+static const struct hvec *const kat_no_additional[] = {
+	[0] = &kat_zero,
+	[1] = &kat_zero,
+};
+
+static const struct hvec *const kat_additional[] = {
+	[0] = &(const struct hvec) {
+		.hv_len = 55,
+		.hv_base = (const void *)(const uint8_t[]) {
+			0x60,0x61,0x62,0x63, 0x64,0x65,0x66,0x67,
+			0x68,0x69,0x6a,0x6b, 0x6c,0x6d,0x6e,0x6f,
+			0x70,0x71,0x72,0x73, 0x74,0x75,0x76,0x77,
+			0x78,0x79,0x7a,0x7b, 0x7c,0x7d,0x7e,0x7f,
+			0x80,0x81,0x82,0x83, 0x84,0x85,0x86,0x87,
+			0x88,0x89,0x8a,0x8b, 0x8c,0x8d,0x8e,0x8f,
+			0x90,0x91,0x92,0x93, 0x94,0x95,0x96,
+		},
+	},
+	[1] = &(const struct hvec) {
+		.hv_len = 55,
+		.hv_base = (const void *)(const uint8_t[]) {
+			0xa0,0xa1,0xa2,0xa3, 0xa4,0xa5,0xa6,0xa7,
+			0xa8,0xa9,0xaa,0xab, 0xac,0xad,0xae,0xaf,
+			0xb0,0xb1,0xb2,0xb3, 0xb4,0xb5,0xb6,0xb7,
+			0xb8,0xb9,0xba,0xbb, 0xbc,0xbd,0xbe,0xbf,
+			0xc0,0xc1,0xc2,0xc3, 0xc4,0xc5,0xc6,0xc7,
+			0xc8,0xc9,0xca,0xcb, 0xcc,0xcd,0xce,0xcf,
+			0xd0,0xd1,0xd2,0xd3, 0xd4,0xd5,0xd6,
+		},
+	},
+};
+
+static const struct {
+	const struct hvec *personalization;
+	const struct hvec *const *additional;
+	bool reseed;
+	uint8_t C[SEEDLEN_BYTES];
+	uint8_t V[3][SEEDLEN_BYTES];
+	uint8_t rnd_val[2][64];
+} kat[] = {
+	[0] = {			/* Hash_DRBG.pdf, p. 190 */
+		.personalization = &kat_zero,
+		.additional = kat_no_additional,
+		.reseed = false,
+		.C = {		/* p. 193 */
+			0xe1,0x5d,0xe4,0xa8, 0xe3,0xb1,0x41,0x9b,
+			0x61,0xd5,0x34,0xf1, 0x5d,0xbd,0x31,0xee,
+			0x19,0xec,0x59,0x5f, 0x8b,0x98,0x11,0x1a,
+			0x94,0xf5,0x22,0x37, 0xad,0x5d,0x66,0xf0,
+			0xcf,0xaa,0xfd,0xdc, 0x90,0x19,0x59,0x02,
+			0xe9,0x79,0xf7,0x9b, 0x65,0x35,0x7f,0xea,
+			0x85,0x99,0x8e,0x4e, 0x37,0xd2,0xc1,
+		},
+		.V = {
+			[0] = {		/* p. 192 */
+				0xab,0x41,0xcd,0xe4, 0x37,0xab,0x8b,0x09,
+				0x1c,0xa7,0xc5,0x75, 0x5d,0x10,0xf0,0x11,
+				0x0c,0x1d,0xbd,0x46, 0x2f,0x22,0x6c,0xfd,
+				0xab,0xfb,0xb0,0x4a, 0x8b,0xcd,0xef,0x95,
+				0x16,0x7d,0x84,0xaf, 0x64,0x12,0x8c,0x0d,
+				0x71,0xf4,0xd5,0xb8, 0xc0,0xed,0xfb,0xbe,
+				0x3d,0xf4,0x04,0x48, 0xd2,0xd8,0xe1,
+			},
+			[1] = {		/* p. 195 */
+				0x8c,0x9f,0xb2,0x8d, 0x1b,0x5c,0xcc,0xa4,
+				0x7e,0x7c,0xfa,0x66, 0xba,0xce,0x21,0xff,
+				0x26,0x0a,0x16,0xa5, 0xba,0xba,0x7f,0x14,
+				0x4e,0x75,0x79,0x36, 0x8e,0x99,0x55,0xbe,
+				0xfb,0xe7,0x00,0xee, 0xf8,0x72,0x77,0x6b,
+				0x17,0xae,0xff,0xd5, 0x3d,0x76,0xf4,0xe3,
+				0xbe,0x65,0xe8,0xc9, 0x4b,0x70,0x8f,
+			},
+			[2] = {		/* p. 197 */
+				0x6d,0xfd,0x97,0x35, 0xff,0x0e,0x0e,0x3f,
+				0xe0,0x52,0x2f,0x58, 0x18,0x8b,0x53,0xed,
+				0x3f,0xf6,0x70,0x05, 0x46,0x52,0x90,0x44,
+				0xb6,0x2b,0xe1,0x7d, 0x1b,0x1c,0x21,0xd0,
+				0x91,0xb0,0x89,0xb1, 0x77,0x47,0x95,0xdb,
+				0x14,0x22,0xa8,0x6c, 0x95,0x46,0x34,0x80,
+				0x76,0xb4,0xb6,0x21, 0xc7,0x2f,0x91,
+			},
+		},
+		.rnd_val = {
+			[0] = {
+				0x77,0xe0,0x5a,0x0e, 0x7d,0xc7,0x8a,0xb5,
+				0xd8,0x93,0x4d,0x5e, 0x93,0xe8,0x2c,0x06,
+				0xa0,0x7c,0x04,0xce, 0xe6,0xc9,0xc5,0x30,
+				0x45,0xee,0xb4,0x85, 0x87,0x27,0x77,0xcf,
+				0x3b,0x3e,0x35,0xc4, 0x74,0xf9,0x76,0xb8,
+				0x94,0xbf,0x30,0x1a, 0x86,0xfa,0x65,0x1f,
+				0x46,0x39,0x70,0xe8, 0x9d,0x4a,0x05,0x34,
+				0xb2,0xec,0xad,0x29, 0xec,0x04,0x4e,0x7e,
+			},
+			{
+				0x5f,0xf4,0xba,0x49, 0x3c,0x40,0xcf,0xff,
+				0x3b,0x01,0xe4,0x72, 0xc5,0x75,0x66,0x8c,
+				0xce,0x38,0x80,0xb9, 0x29,0x0b,0x05,0xbf,
+				0xed,0xe5,0xec,0x96, 0xed,0x5e,0x9b,0x28,
+				0x98,0x50,0x8b,0x09, 0xbc,0x80,0x0e,0xee,
+				0x09,0x9a,0x3c,0x90, 0x60,0x2a,0xbd,0x4b,
+				0x1d,0x4f,0x34,0x3d, 0x49,0x7c,0x60,0x55,
+				0xc8,0x7b,0xb9,0x56, 0xd5,0x3b,0xf3,0x51,
+			},
+		},
+	},
+
+	[1] = {			/* Hash_DRBG.pdf, p. 198 */
+		.personalization = &kat_zero,
+		.additional = kat_additional,
+		.reseed = false,
+		.C = {		/* p. 201 */
+			0xe1,0x5d,0xe4,0xa8, 0xe3,0xb1,0x41,0x9b,
+			0x61,0xd5,0x34,0xf1, 0x5d,0xbd,0x31,0xee,
+			0x19,0xec,0x59,0x5f, 0x8b,0x98,0x11,0x1a,
+			0x94,0xf5,0x22,0x37, 0xad,0x5d,0x66,0xf0,
+			0xcf,0xaa,0xfd,0xdc, 0x90,0x19,0x59,0x02,
+			0xe9,0x79,0xf7,0x9b, 0x65,0x35,0x7f,0xea,
+			0x85,0x99,0x8e,0x4e, 0x37,0xd2,0xc1,
+		},
+		.V = {
+			[0] = {	/* p. 200 */
+				0xab,0x41,0xcd,0xe4, 0x37,0xab,0x8b,0x09,
+				0x1c,0xa7,0xc5,0x75, 0x5d,0x10,0xf0,0x11,
+				0x0c,0x1d,0xbd,0x46, 0x2f,0x22,0x6c,0xfd,
+				0xab,0xfb,0xb0,0x4a, 0x8b,0xcd,0xef,0x95,
+				0x16,0x7d,0x84,0xaf, 0x64,0x12,0x8c,0x0d,
+				0x71,0xf4,0xd5,0xb8, 0xc0,0xed,0xfb,0xbe,
+				0x3d,0xf4,0x04,0x48, 0xd2,0xd8,0xe1,
+			},
+			[1] = {	/* p. 204 */
+				0x8c,0x9f,0xb2,0x8d, 0x1b,0x5c,0xcc,0xa4,
+				0x7e,0x7c,0xfa,0x66, 0xba,0xce,0x21,0xff,
+				0x26,0x0a,0x16,0xa5, 0xba,0xba,0x7f,0x1f,
+				0xd3,0x3b,0x30,0x79, 0x8f,0xb2,0x9a,0x0f,
+				0xba,0x66,0x65,0x02, 0x7d,0x7f,0x10,0x58,
+				0x71,0xbf,0xb4,0x40, 0xdf,0xbe,0xde,0x81,
+				0xd0,0x4d,0x22,0xdf, 0xf7,0x89,0xe1,
+			},
+			[2] = {	/* p. 207 */
+				0x6d,0xfd,0x97,0x35, 0xff,0x0e,0x0e,0x3f,
+				0xe0,0x52,0x2f,0x58, 0x18,0x8b,0x53,0xed,
+				0x3f,0xf6,0x70,0x05, 0x46,0x52,0x90,0xe1,
+				0x7c,0x5a,0xd8,0x2d, 0xa9,0x2a,0x05,0x01,
+				0xaa,0x66,0x3a,0xa6, 0x9f,0xa5,0xa0,0xb0,
+				0x81,0x2b,0x4b,0x4f, 0xaf,0xf3,0xfe,0xce,
+				0x79,0xcc,0xf6,0xaa, 0xde,0xc1,0xd0,
+			},
+		},
+		.rnd_val = {
+			[0] = {	/* p. 203 */
+				0x51,0x07,0x24,0xb9, 0x3a,0xe9,0xa1,0x82,
+				0x70,0xe4,0x84,0x73, 0x71,0x1d,0x88,0x24,
+				0x63,0x1b,0xaa,0x7f, 0x1d,0x9a,0xc9,0x28,
+				0x4e,0x7e,0xc8,0xf3, 0x63,0x7f,0x7a,0x74,
+				0x3b,0x36,0x44,0xeb, 0x96,0xc9,0x86,0x27,
+				0xc8,0xfd,0x40,0x5a, 0x7a,0x46,0x03,0xf3,
+				0x8c,0xff,0x7c,0x89, 0xe9,0xc1,0x33,0xf5,
+				0x85,0x1f,0x40,0xe9, 0x20,0x30,0xfe,0xa2,
+			},
+			[1] = {	/* p. 206 */
+				0x62,0x53,0xda,0x3a, 0xae,0x8b,0x88,0xa3,
+				0xb7,0x46,0xe4,0xc8, 0xb2,0x63,0x5c,0x54,
+				0x0f,0x6e,0x9e,0xa7, 0x15,0x7e,0xe6,0x9d,
+				0xd7,0x1e,0xfb,0x2e, 0x8f,0xf7,0xbb,0xe1,
+				0xe3,0x33,0x68,0x88, 0x38,0xdd,0x7d,0xe4,
+				0x9c,0xc8,0x89,0x90, 0x30,0x9c,0x96,0xcd,
+				0xb2,0xab,0x92,0x95, 0x74,0x36,0xbf,0x83,
+				0xd1,0xbd,0x83,0x08, 0x19,0xc7,0x48,0xca,
+			},
+		},
+	},
+
+	[2] = {			/* Hash_DRBG.pdf, p. 208 */
+		.personalization = &kat_personalization,
+		.additional = kat_no_additional,
+		.reseed = false,
+		.C = {		/* p. 211 */
+			0x44,0x74,0x8a,0x78, 0xb1,0x6e,0x75,0x55,
+			0x9f,0x88,0x1d,0x51, 0xc1,0x5d,0xfe,0x6c,
+			0x52,0xcf,0xb0,0xbb, 0x71,0x62,0x01,0x69,
+			0xc7,0x93,0x34,0x27, 0x67,0xe7,0xf8,0x87,
+			0x5f,0x42,0xcb,0x6a, 0x20,0xc8,0x9d,0x7c,
+			0x6e,0xf3,0xdc,0x61, 0x0d,0x8f,0xf2,0x03,
+			0xd6,0x76,0x6c,0xed, 0x19,0x19,0xd0,
+		},
+		.V = {
+			[0] = {	/* p. 210 */
+				0xa3,0xe9,0x4e,0x39, 0x26,0xfd,0xa1,0x69,
+				0xc3,0x03,0xd6,0x64, 0x38,0x39,0x05,0xe0,
+				0xd7,0x99,0x62,0xd1, 0x65,0x44,0x6d,0x63,
+				0xbd,0xa6,0x54,0xd1, 0x32,0xf7,0x2d,0xb4,
+				0x71,0x56,0x4b,0x45, 0x6f,0xf2,0xee,0xc8,
+				0x36,0x42,0x2a,0xcc, 0x5a,0x02,0x99,0x35,
+				0xa7,0x99,0x29,0x90, 0x94,0xa1,0xca,
+			},
+			[1] = {	/* p. 213 */
+				0xe8,0x5d,0xd8,0xb1, 0xd8,0x6c,0x16,0xbf,
+				0x62,0x8b,0xf3,0xb5, 0xf9,0x97,0x04,0x4d,
+				0x2a,0x69,0x13,0x8c, 0xd6,0xa6,0x6e,0xe7,
+				0x36,0xdb,0xaa,0x3b, 0xf1,0xd0,0x28,0x3b,
+				0x71,0x7b,0x33,0x6e, 0xb3,0xae,0x5b,0xdd,
+				0x04,0x17,0x2e,0xa2, 0x6e,0x5a,0x48,0xf3,
+				0xb3,0xfb,0xab,0xf8, 0x2f,0x76,0x79,
+			},
+			[2] = {	/* p. 215 */
+				0x2c,0xd2,0x63,0x2a, 0x89,0xda,0x8c,0x15,
+				0x02,0x14,0x11,0x07, 0xba,0xf5,0x02,0xb9,
+				0x7d,0x38,0xc4,0x48, 0x48,0x08,0x71,0x0a,
+				0x66,0xf8,0x40,0x11, 0xd7,0x02,0x8d,0x14,
+				0xd3,0x15,0x5a,0x73, 0x79,0xad,0xd5,0x3c,
+				0xc8,0xea,0x84,0xd0, 0xfc,0x64,0x1d,0xfc,
+				0x62,0x9e,0x06,0x19, 0x1f,0x5f,0x6d,
+			},
+		},
+		.rnd_val = {
+			[0] = {	/* p. 213 */
+				0x4a,0x62,0x66,0x4f, 0x26,0x6e,0xe5,0x37,
+				0xb9,0x0d,0x64,0xb0, 0x5e,0x1d,0x81,0x3d,
+				0x28,0xb1,0x59,0xa9, 0x79,0xf1,0x50,0x9d,
+				0xde,0x31,0xb7,0x1d, 0xa4,0x3d,0x54,0x6e,
+				0xe8,0xe7,0x86,0x78, 0x20,0x2d,0xc2,0x37,
+				0xad,0x4a,0xfe,0x7d, 0xf3,0x10,0xc9,0xa4,
+				0x13,0xe3,0x8a,0xaf, 0x41,0x7d,0x2d,0x22,
+				0x5a,0xa3,0x65,0xec, 0x4a,0x7d,0x29,0x96,
+			},
+			[1] = {	/* p. 215 */
+				0x59,0x58,0x3d,0x3c, 0x0a,0xc3,0x71,0x30,
+				0xc4,0x78,0x9a,0x83, 0x11,0xb8,0xca,0x8f,
+				0x98,0x5e,0xf1,0xe8, 0xf9,0x4d,0x95,0x4e,
+				0x32,0xe3,0x44,0xa6, 0x21,0xc2,0x4b,0x2f,
+				0x37,0x1d,0xa9,0xba, 0x3c,0x33,0x15,0x3f,
+				0x09,0xe5,0x51,0x45, 0xe7,0x62,0x92,0x6b,
+				0x73,0xac,0x14,0x7a, 0x1e,0x86,0x31,0xd1,
+				0xcc,0xd0,0x85,0x67, 0xcf,0x67,0x7c,0x72,
+			},
+		},
+	},
+
+	[3] = {			/* Hash_DRBG.pdf, p. 215 */
+		.personalization = &kat_personalization,
+		.additional = kat_additional,
+		.reseed = false,
+		.C = {		/* p. 220 */
+			0x44,0x74,0x8a,0x78, 0xb1,0x6e,0x75,0x55,
+			0x9f,0x88,0x1d,0x51, 0xc1,0x5d,0xfe,0x6c,
+			0x52,0xcf,0xb0,0xbb, 0x71,0x62,0x01,0x69,
+			0xc7,0x93,0x34,0x27, 0x67,0xe7,0xf8,0x87,
+			0x5f,0x42,0xcb,0x6a, 0x20,0xc8,0x9d,0x7c,
+			0x6e,0xf3,0xdc,0x61, 0x0d,0x8f,0xf2,0x03,
+			0xd6,0x76,0x6c,0xed, 0x19,0x19,0xd0,
+		},
+		.V = {
+			[0] = {	/* p. 218 */
+				0xa3,0xe9,0x4e,0x39, 0x26,0xfd,0xa1,0x69,
+				0xc3,0x03,0xd6,0x64, 0x38,0x39,0x05,0xe0,
+				0xd7,0x99,0x62,0xd1, 0x65,0x44,0x6d,0x63,
+				0xbd,0xa6,0x54,0xd1, 0x32,0xf7,0x2d,0xb4,
+				0x71,0x56,0x4b,0x45, 0x6f,0xf2,0xee,0xc8,
+				0x36,0x42,0x2a,0xcc, 0x5a,0x02,0x99,0x35,
+				0xa7,0x99,0x29,0x90, 0x94,0xa1,0xca,
+			},
+			[1] = {	/* p. 222 */
+				0xe8,0x5d,0xd8,0xb1, 0xd8,0x6c,0x16,0xbf,
+				0x62,0x8b,0xf3,0xb5, 0xf9,0x97,0x04,0x4d,
+				0x2a,0x69,0x13,0x8c, 0xd6,0xa6,0x6f,0x8c,
+				0xa8,0x7b,0x87,0x43, 0x50,0x20,0x2e,0x1d,
+				0x8a,0xb0,0xb5,0xad, 0x47,0xac,0xc2,0x75,
+				0x40,0x28,0x9f,0xe3, 0xa8,0xe3,0x1f,0x7b,
+				0x56,0x58,0xdd,0xd1, 0x96,0x94,0x89,
+			},
+			[2] = {	/* p. 225 */
+				0x2c,0xd2,0x63,0x2a, 0x89,0xda,0x8c,0x15,
+				0x02,0x14,0x11,0x07, 0xba,0xf5,0x02,0xb9,
+				0x7d,0x38,0xc4,0x48, 0x48,0x08,0x71,0xb2,
+				0x77,0xae,0xc7,0xff, 0x8d,0xa2,0x3c,0x71,
+				0xef,0xf5,0x9d,0xc2, 0x4e,0x5e,0x4c,0x7f,
+				0x58,0x47,0xb0,0xc1, 0x2f,0x6a,0x59,0x9e,
+				0x6b,0x2e,0xda,0xc0, 0x30,0x6b,0xcd,
+			},
+		},
+		.rnd_val = {	/* p. 222 */
+			[0] = {
+				0xe0,0xb9,0x7c,0x82, 0x12,0x68,0xfd,0x3b,
+				0xb2,0xca,0xbf,0xd1, 0xf9,0x54,0x84,0x78,
+				0xae,0x8a,0x60,0x41, 0x7f,0x7b,0x09,0x4a,
+				0x26,0x13,0x95,0x46, 0x06,0x2b,0x52,0x1c,
+				0xfd,0x33,0xe4,0xe3, 0x9b,0x9d,0xcd,0x0a,
+				0x3d,0xa1,0x52,0x09, 0xc7,0x2a,0xdb,0xe5,
+				0x8c,0x20,0xab,0x34, 0x07,0x02,0x69,0x51,
+				0x29,0x7a,0xd2,0x54, 0x30,0x75,0x53,0xa5,
+			},
+			[1] = {	/* p. 225 */
+				0xc1,0xac,0xd3,0xad, 0xa4,0xc8,0xc4,0x95,
+				0xbf,0x17,0x9d,0xb5, 0x98,0x22,0xc3,0x51,
+				0xbc,0x47,0x9a,0xbe, 0x4e,0xb2,0x8f,0x84,
+				0x39,0x57,0xb1,0x1e, 0x3c,0x2b,0xc0,0x48,
+				0x83,0x96,0x42,0x97, 0x97,0x5b,0xd7,0x2d,
+				0x10,0x24,0xab,0xcf, 0x6f,0x66,0x15,0xd7,
+				0xf5,0xb4,0xfd,0x1e, 0x40,0xa6,0x4e,0xeb,
+				0x45,0xba,0x21,0x81, 0xb8,0x39,0x37,0xed,
+			},
+		},
+	},
+
+	[4] = {			/* Hash_DRBG.pdf, p. 225 */
+		.personalization = &kat_zero,
+		.additional = kat_no_additional,
+		.reseed = true,
+		.C = {		/* p. 229 */
+			0xe1,0x5d,0xe4,0xa8, 0xe3,0xb1,0x41,0x9b,
+			0x61,0xd5,0x34,0xf1, 0x5d,0xbd,0x31,0xee,
+			0x19,0xec,0x59,0x5f, 0x8b,0x98,0x11,0x1a,
+			0x94,0xf5,0x22,0x37, 0xad,0x5d,0x66,0xf0,
+			0xcf,0xaa,0xfd,0xdc, 0x90,0x19,0x59,0x02,
+			0xe9,0x79,0xf7,0x9b, 0x65,0x35,0x7f,0xea,
+			0x85,0x99,0x8e,0x4e, 0x37,0xd2,0xc1,
+		},
+		.V = {
+			[0] = {	/* p. 227 */
+				0xab,0x41,0xcd,0xe4, 0x37,0xab,0x8b,0x09,
+				0x1c,0xa7,0xc5,0x75, 0x5d,0x10,0xf0,0x11,
+				0x0c,0x1d,0xbd,0x46, 0x2f,0x22,0x6c,0xfd,
+				0xab,0xfb,0xb0,0x4a, 0x8b,0xcd,0xef,0x95,
+				0x16,0x7d,0x84,0xaf, 0x64,0x12,0x8c,0x0d,
+				0x71,0xf4,0xd5,0xb8, 0xc0,0xed,0xfb,0xbe,
+				0x3d,0xf4,0x04,0x48, 0xd2,0xd8,0xe1,
+			},
+			[1] = {	/* p. 234 */
+				0x23,0x97,0x6c,0x61, 0x63,0xd7,0xe2,0x4a,
+				0x1a,0x03,0x8f,0x2b, 0x2b,0x64,0x67,0x97,
+				0x50,0xca,0x9e,0xd8, 0xd1,0x40,0x69,0x8d,
+				0x64,0x22,0x39,0x7b, 0x02,0x96,0x9e,0x6e,
+				0xcd,0xd2,0x9d,0xac, 0xc5,0x76,0x7e,0x2c,
+				0xc2,0xd0,0xa1,0x56, 0xc8,0x7a,0xd0,0xb3,
+				0x57,0x89,0x05,0x07, 0xe0,0x37,0x77,
+			},
+			[2] = {	/* p. 239 */
+				0x92,0xfb,0x0e,0x48, 0x0e,0x86,0x99,0x13,
+				0xc7,0xad,0x45,0xc7, 0xe3,0xfd,0x46,0x10,
+				0x17,0xe5,0xa6,0xb7, 0x70,0xf3,0x3b,0x31,
+				0x3c,0x38,0x83,0xf1, 0xcc,0x56,0x71,0x89,
+				0x45,0x21,0xf5,0xed, 0xe6,0x2e,0xaa,0xb0,
+				0x83,0xb1,0x41,0xa7, 0x5b,0x5c,0xc0,0x22,
+				0x60,0x5a,0x8a,0x3d, 0xc7,0x1b,0xa7,
+			},
+		},
+		.rnd_val = {
+			[0] = {	/* p. 234 */
+				0x92,0x27,0x55,0x23, 0xc7,0x0e,0x56,0x7b,
+				0xcf,0x9b,0x35,0xec, 0x50,0xb9,0x33,0xf8,
+				0x12,0x61,0x6d,0xf5, 0x86,0xb7,0xf7,0x2e,
+				0xe1,0xbc,0x77,0x35, 0xa5,0xc2,0x65,0x43,
+				0x73,0xcb,0xbc,0x72, 0x31,0x6d,0xff,0x84,
+				0x20,0xa3,0x3b,0xf0, 0x2b,0x97,0xac,0x8d,
+				0x19,0x52,0x58,0x3f, 0x27,0x0a,0xcd,0x70,
+				0x05,0xcc,0x02,0x7f, 0x4c,0xf1,0x18,0x7e,
+			},
+			[1] = {	/* p. 239 */
+				0x68,0x1a,0x46,0xb2, 0xaa,0x86,0x94,0xa0,
+				0xfe,0x4d,0xee,0xa7, 0x20,0x92,0x7a,0x84,
+				0xea,0xaa,0x98,0x5e, 0x59,0xc1,0x9f,0x8b,
+				0xe0,0x98,0x4d,0x8c, 0xbe,0xf8,0xc6,0x9b,
+				0x75,0x41,0x67,0x64, 0x19,0x46,0xe0,0x40,
+				0xee,0x20,0x43,0xe1, 0xcc,0xb2,0x9d,0xcf,
+				0x06,0x3c,0x0a,0x50, 0x83,0x0e,0x42,0x8e,
+				0x6d,0xca,0x26,0x2e, 0xcd,0x77,0xc5,0x42,
+			},
+		},
+	},
+
+	[5] = {			/* Hash_DRBG.pdf, p. 239 */
+		.personalization = &kat_zero,
+		.additional = kat_additional,
+		.reseed = true,
+		.C = {		/* p. 243 */
+			0xe1,0x5d,0xe4,0xa8, 0xe3,0xb1,0x41,0x9b,
+			0x61,0xd5,0x34,0xf1, 0x5d,0xbd,0x31,0xee,
+			0x19,0xec,0x59,0x5f, 0x8b,0x98,0x11,0x1a,
+			0x94,0xf5,0x22,0x37, 0xad,0x5d,0x66,0xf0,
+			0xcf,0xaa,0xfd,0xdc, 0x90,0x19,0x59,0x02,
+			0xe9,0x79,0xf7,0x9b, 0x65,0x35,0x7f,0xea,
+			0x85,0x99,0x8e,0x4e, 0x37,0xd2,0xc1,
+		},
+		.V = {
+			[0] = {	/* p. 242 */
+				0xab,0x41,0xcd,0xe4, 0x37,0xab,0x8b,0x09,
+				0x1c,0xa7,0xc5,0x75, 0x5d,0x10,0xf0,0x11,
+				0x0c,0x1d,0xbd,0x46, 0x2f,0x22,0x6c,0xfd,
+				0xab,0xfb,0xb0,0x4a, 0x8b,0xcd,0xef,0x95,
+				0x16,0x7d,0x84,0xaf, 0x64,0x12,0x8c,0x0d,
+				0x71,0xf4,0xd5,0xb8, 0xc0,0xed,0xfb,0xbe,
+				0x3d,0xf4,0x04,0x48, 0xd2,0xd8,0xe1,
+			},
+			[1] = {	/* p. 249 */
+				0xb3,0x74,0x95,0x46, 0x81,0xcf,0xc9,0x5b,
+				0x8d,0xb8,0x39,0x52, 0x8c,0x71,0x08,0x83,
+				0x5e,0xb4,0xf3,0x0a, 0xd9,0x1c,0xbe,0x9e,
+				0xa0,0xd5,0x45,0xcc, 0xfd,0x18,0x13,0x2a,
+				0xf1,0xd3,0x76,0x8f, 0x47,0x02,0x77,0x2b,
+				0x69,0x15,0x9f,0x2c, 0xc0,0x7f,0x48,0x74,
+				0x1e,0xb5,0xb2,0xb1, 0x22,0x11,0x25,
+			},
+			[2] = {	/* p. 254 */
+				0xbf,0xe3,0xd6,0x81, 0xa2,0x0f,0xbe,0x39,
+				0x03,0x8f,0x4d,0x66, 0x77,0x7c,0x1b,0xe5,
+				0x79,0xee,0xb4,0x85, 0x7b,0x42,0xf2,0x1c,
+				0x3f,0x59,0x8b,0x59, 0x62,0xb7,0xaa,0x48,
+				0x0e,0xa5,0x65,0xfe, 0xea,0xbd,0xfb,0xd6,
+				0xa7,0xec,0xcb,0x96, 0x02,0xc1,0x4b,0xfa,
+				0x30,0xf0,0xf9,0x81, 0x90,0x0c,0xd0,
+			},
+		},
+		.rnd_val = {
+			[0] = {	/* p. 249 */
+				0x11,0x60,0x1b,0x72, 0xca,0x60,0x89,0x73,
+				0x6b,0x20,0x47,0x44, 0xb2,0x9d,0xa1,0xaa,
+				0xaf,0xba,0xca,0xa5, 0x28,0x8f,0x06,0xbe,
+				0x48,0x45,0x69,0xcc, 0xed,0xbe,0xce,0x03,
+				0xe8,0x22,0xea,0xa5, 0xb1,0x4f,0x0e,0x04,
+				0x94,0x8c,0x05,0xcd, 0x3c,0xc2,0xe2,0x88,
+				0x9a,0x89,0xfa,0x03, 0xd6,0x5d,0x4d,0x74,
+				0xac,0x50,0xff,0x6b, 0xd8,0x56,0xe5,0x79,
+			},
+			[1] = {	/* p. 255 */
+				0x05,0x5b,0xc1,0x28, 0xcc,0x2d,0x0e,0x25,
+				0x0f,0x47,0xe4,0xe4, 0xf5,0x82,0x37,0x5d,
+				0xe3,0xee,0x5e,0x9f, 0xe8,0x31,0x68,0x74,
+				0x97,0xe5,0xaf,0x1e, 0x7c,0xb6,0x9e,0xfd,
+				0xeb,0xd2,0xfd,0x31, 0xc7,0xce,0x2b,0xba,
+				0x0d,0xbc,0x6c,0x74, 0xc8,0xa2,0x0a,0x7d,
+				0x72,0xf6,0x0e,0x6d, 0x9f,0x63,0xed,0x50,
+				0x9e,0x96,0x3e,0x54, 0xa6,0x9e,0x90,0x48,
+			},
+		},
+	},
+
+	[6] = {			/* Hash_DRBG.pdf, p. 255 */
+		.personalization = &kat_personalization,
+		.additional = kat_no_additional,
+		.reseed = true,
+		.C = {		/* p. 259 */
+			0x44,0x74,0x8a,0x78, 0xb1,0x6e,0x75,0x55,
+			0x9f,0x88,0x1d,0x51, 0xc1,0x5d,0xfe,0x6c,
+			0x52,0xcf,0xb0,0xbb, 0x71,0x62,0x01,0x69,
+			0xc7,0x93,0x34,0x27, 0x67,0xe7,0xf8,0x87,
+			0x5f,0x42,0xcb,0x6a, 0x20,0xc8,0x9d,0x7c,
+			0x6e,0xf3,0xdc,0x61, 0x0d,0x8f,0xf2,0x03,
+			0xd6,0x76,0x6c,0xed, 0x19,0x19,0xd0,
+		},
+		.V = {
+			[0] = {	/* p. 257 */
+				0xa3,0xe9,0x4e,0x39, 0x26,0xfd,0xa1,0x69,
+				0xc3,0x03,0xd6,0x64, 0x38,0x39,0x05,0xe0,
+				0xd7,0x99,0x62,0xd1, 0x65,0x44,0x6d,0x63,
+				0xbd,0xa6,0x54,0xd1, 0x32,0xf7,0x2d,0xb4,
+				0x71,0x56,0x4b,0x45, 0x6f,0xf2,0xee,0xc8,
+				0x36,0x42,0x2a,0xcc, 0x5a,0x02,0x99,0x35,
+				0xa7,0x99,0x29,0x90, 0x94,0xa1,0xca,
+			},
+			[1] = {	/* p. 264 */
+				0xaa,0x11,0x1b,0x0e, 0xd5,0x6c,0xf4,0xa6,
+				0xcc,0xe4,0xad,0xe7, 0xf1,0x1b,0x06,0x10,
+				0x45,0xbf,0x10,0x92, 0xcb,0xb3,0x8f,0xf3,
+				0x23,0x95,0xea,0x62, 0xd2,0x6b,0x27,0xc8,
+				0x86,0x89,0x45,0xc5, 0x93,0xba,0x70,0xc3,
+				0x84,0xad,0xad,0x45, 0x77,0x1c,0x93,0xb0,
+				0x9c,0x27,0x69,0x07, 0x52,0xd1,0xd8,
+			},
+			[2] = {	/* p. 269 */
+				0x5f,0x0f,0xd4,0x0c, 0x8c,0x82,0xef,0x41,
+				0x03,0x14,0xb8,0x30, 0xc2,0x0f,0xcc,0xea,
+				0x71,0x59,0x18,0x9a, 0xea,0x13,0xe8,0x48,
+				0x75,0x68,0x68,0x18, 0xcd,0x4f,0x12,0xb9,
+				0xde,0xa8,0x82,0x58, 0x16,0xa4,0x13,0xa2,
+				0x95,0x72,0x5e,0xb3, 0x3e,0x33,0xb9,0xad,
+				0xfe,0xe0,0xb1,0xc2, 0x34,0x0a,0xe0,
+			},
+		},
+		.rnd_val = {
+			[0] = {	/* p. 264 */
+				0x7a,0x33,0xd3,0x90, 0x33,0xf8,0x60,0x58,
+				0x9f,0x37,0x5e,0x73, 0x35,0x30,0x75,0x52,
+				0x96,0x58,0xbb,0xed, 0x99,0xc8,0xa0,0xef,
+				0x5e,0x28,0xb3,0x51, 0xb2,0xdf,0x33,0x58,
+				0xb3,0xd8,0x9b,0xac, 0x72,0x25,0xdf,0x9e,
+				0x3b,0xcd,0x08,0x36, 0xb9,0x9b,0x5d,0xbf,
+				0x36,0x3a,0x17,0x0c, 0x7b,0xb9,0xbe,0x41,
+				0xa4,0xaa,0x97,0x44, 0x5e,0xce,0xe4,0x1e,
+			},
+			[1] = {	/* p. 269 */
+				0x04,0x1a,0xbd,0x94, 0x07,0x9a,0x05,0x71,
+				0x88,0x5f,0x16,0x65, 0x94,0x4e,0x0e,0x7f,
+				0x1b,0xfa,0xcd,0xea, 0xea,0xe9,0xd4,0x4e,
+				0xed,0xc1,0x1f,0xad, 0xd8,0x4c,0x34,0xc7,
+				0xca,0xa7,0x3d,0x09, 0xa0,0x19,0x31,0x93,
+				0xfa,0x40,0xa1,0x9f, 0x64,0x4f,0x04,0x8d,
+				0x2a,0x54,0x17,0x04, 0x25,0x53,0xdf,0x52,
+				0x51,0x74,0x1b,0x40, 0xea,0xcf,0xeb,0x98,
+			},
+		},
+	},
+
+	[7] = {			/* Hash_DRBG.pdf, p. 269 */
+		.personalization = &kat_personalization,
+		.additional = kat_additional,
+		.reseed = true,
+		.C = {		/* p. 274 */
+			0x44,0x74,0x8a,0x78, 0xb1,0x6e,0x75,0x55,
+			0x9f,0x88,0x1d,0x51, 0xc1,0x5d,0xfe,0x6c,
+			0x52,0xcf,0xb0,0xbb, 0x71,0x62,0x01,0x69,
+			0xc7,0x93,0x34,0x27, 0x67,0xe7,0xf8,0x87,
+			0x5f,0x42,0xcb,0x6a, 0x20,0xc8,0x9d,0x7c,
+			0x6e,0xf3,0xdc,0x61, 0x0d,0x8f,0xf2,0x03,
+			0xd6,0x76,0x6c,0xed, 0x19,0x19,0xd0,
+		},
+		.V = {
+			[0] = {	/* p. 272 */
+				0xa3,0xe9,0x4e,0x39, 0x26,0xfd,0xa1,0x69,
+				0xc3,0x03,0xd6,0x64, 0x38,0x39,0x05,0xe0,
+				0xd7,0x99,0x62,0xd1, 0x65,0x44,0x6d,0x63,
+				0xbd,0xa6,0x54,0xd1, 0x32,0xf7,0x2d,0xb4,
+				0x71,0x56,0x4b,0x45, 0x6f,0xf2,0xee,0xc8,
+				0x36,0x42,0x2a,0xcc, 0x5a,0x02,0x99,0x35,
+				0xa7,0x99,0x29,0x90, 0x94,0xa1,0xca,
+			},
+			[1] = {	/* p. 279 */
+				0xaa,0xf6,0xb9,0x9b, 0x7f,0x84,0xb0,0x36,
+				0xe1,0xcc,0xbc,0x9d, 0x57,0x3a,0x36,0xb8,
+				0xbd,0xd4,0x7c,0x35, 0x8b,0xb5,0xf3,0xc1,
+				0xd6,0xe7,0x90,0x3a, 0xaa,0x29,0xf1,0xc8,
+				0x7a,0xe6,0x66,0xb8, 0x86,0x93,0xbe,0xf4,
+				0x6c,0x51,0xc2,0x4c, 0x47,0xbe,0xfe,0x4b,
+				0x35,0x75,0x4d,0xcb, 0xfa,0x1e,0x7d,
+			},
+			[2] = {	/* p. 285 */
+				0x0c,0x75,0x77,0x4d, 0x61,0x02,0x69,0xad,
+				0x5b,0xb4,0xab,0xbb, 0x14,0x83,0x23,0xc9,
+				0x78,0x9f,0x8f,0x76, 0x25,0xcc,0x34,0x33,
+				0x7c,0x03,0x47,0x2d, 0x9a,0x0c,0x4f,0xac,
+				0x30,0xbe,0xd2,0xdd, 0xde,0x64,0xb8,0x7a,
+				0x2c,0x70,0x67,0x52, 0xc2,0x1a,0xc0,0x11,
+				0x27,0x43,0x59,0x2c, 0x4f,0xdf,0x67,
+			},
+		},
+		.rnd_val = {	/* p. 279 */
+			[0] = {
+				0x88,0x97,0x32,0x97, 0x5b,0x36,0xe8,0xe2,
+				0xe7,0xb7,0x40,0x50, 0xae,0xa1,0x71,0x39,
+				0xda,0x2b,0x86,0x34, 0xdc,0xe2,0x13,0x3b,
+				0x06,0x34,0x74,0x3f, 0x47,0x75,0x57,0xab,
+				0x7b,0x84,0x4e,0xd3, 0xf2,0xa4,0x6c,0xc6,
+				0x3e,0xb2,0x32,0x86, 0x46,0x4c,0x51,0xd5,
+				0xd7,0x69,0x71,0xc4, 0x7b,0xc5,0xb5,0x5f,
+				0xed,0x72,0xa8,0x04, 0x3c,0xbf,0x66,0x4f,
+			},
+			[1] = {
+				0xbf,0x49,0xb8,0x89, 0xba,0x98,0x4d,0x34,
+				0x63,0x87,0xe8,0x64, 0x7e,0x98,0xbb,0x99,
+				0xcd,0x41,0xa3,0x2f, 0xbe,0xc1,0xfc,0xb3,
+				0xb6,0xa1,0xb7,0xd9, 0x93,0x2b,0xa7,0xe1,
+				0x1e,0xe6,0xbb,0xd9, 0x24,0x40,0x5a,0x2c,
+				0x7f,0xca,0x89,0x0a, 0x5e,0x9a,0x8d,0xea,
+				0x66,0xac,0x0c,0xac, 0xa0,0xca,0x7b,0xc1,
+				0x8d,0x74,0xfb,0xc0, 0x2a,0x11,0xe4,0x53,
+			},
+		},
+	},
+};
+
+#ifdef NIST_HASH_DRBG_DEBUG
+#define	DPRINTF(fmt, ...)						      \
+	printf("%s:%d: " fmt, __func__, __LINE__, ##__VA_ARGS__)
+#define	DUSE(v)
+#else
+#define	DPRINTF(fmt, ...)
+#define	DUSE(v)			(void)(v)
+#endif
+
+#define	CHECK(i, name, actual, expected, n) do				      \
+{									      \
+	CTASSERT(sizeof(actual) == (n));				      \
+	ok &= check(i, name, actual, expected, (n));			      \
+} while (0)
+
+static bool
+check(unsigned katno, const char *name, const uint8_t *actual,
+    const uint8_t *expected, size_t n)
+{
+	bool ok = true;
+	size_t i;
+
+	DUSE(katno);
+	DUSE(name);
+
+	for (i = 0; i < n; i++) {
+		if (actual[i] != expected[i]) {
+			DPRINTF("KAT %u %s[%zu] = %02x, expected %02x\n",
+			    katno, name, i, actual[i], expected[i]);
+			ok = false;
+		}
+	}
+
+	return ok;
+}
+
+#ifdef NIST_HASH_DRBG_MAIN
+int
+main(void)
+{
+	int ret;
+
+	ret = nist_hash_drbg_initialize();
+
+	fflush(stdout);
+	return ret || ferror(stdout);
+}
+#endif
+
+int
+nist_hash_drbg_initialize(void)
+{
+	const unsigned truncation[] = { 0, 1, 32, 63 };
+	bool ok = true;
+	size_t i, j;
+
+	for (i = 0; i < arraycount(kat); i++) {
+		for (j = 0; j < arraycount(truncation); j++) {
+			const unsigned trunc = truncation[j];
+			struct nist_hash_drbg drbg, *D = &drbg;
+			uint8_t rnd_val[64];
+			unsigned reseed_counter;
+
+			nist_hash_drbg_instantiate(D,
+			    kat_entropy[0], sizeof kat_entropy[0],
+			    kat_nonce, sizeof kat_nonce,
+			    kat[i].personalization->hv_base,
+			    kat[i].personalization->hv_len);
+			reseed_counter = 1;
+			CHECK(i, "C", D->C, kat[i].C, SEEDLEN_BYTES);
+			CHECK(i, "V[0]", D->V, kat[i].V[0], SEEDLEN_BYTES);
+			if (D->reseed_counter != reseed_counter) {
+				DPRINTF("bad reseed counter: %u, expected %u",
+				    D->reseed_counter, reseed_counter);
+				ok = false;
+			}
+
+			if (kat[i].reseed) {
+				nist_hash_drbg_reseed(D,
+				    kat_entropy[1], sizeof kat_entropy[1],
+				    kat[i].additional[0]->hv_base,
+				    kat[i].additional[0]->hv_len);
+			}
+
+			nist_hash_drbg_generate(D, rnd_val,
+			    sizeof(rnd_val) - trunc,
+			    kat[i].reseed ? 0 : kat[i].additional[0]->hv_base,
+			    kat[i].reseed ? 0 : kat[i].additional[0]->hv_len);
+			reseed_counter++;
+			CHECK(i, "V[1]", D->V, kat[i].V[1], SEEDLEN_BYTES);
+			CHECK(i, "rnd_val[0]", rnd_val, kat[i].rnd_val[0],
+			    sizeof(kat[i].rnd_val[0]) - trunc);
+			if (D->reseed_counter != reseed_counter) {
+				DPRINTF("bad reseed counter: %u, expected %u",
+				    D->reseed_counter, reseed_counter);
+				ok = false;
+			}
+
+			if (kat[i].reseed) {
+				nist_hash_drbg_reseed(D,
+				    kat_entropy[2], sizeof kat_entropy[2],
+				    kat[i].additional[1]->hv_base,
+				    kat[i].additional[1]->hv_len);
+				reseed_counter = 1;
+			}
+
+			nist_hash_drbg_generate(D, rnd_val,
+			    sizeof(rnd_val) - trunc,
+			    kat[i].reseed ? 0 : kat[i].additional[1]->hv_base,
+			    kat[i].reseed ? 0 : kat[i].additional[1]->hv_len);
+			reseed_counter++;
+			CHECK(i, "V[2]", D->V, kat[i].V[2], SEEDLEN_BYTES);
+			CHECK(i, "rnd_val[1]", rnd_val, kat[i].rnd_val[1],
+			    sizeof(kat[i].rnd_val[1]) - trunc);
+			if (D->reseed_counter != reseed_counter) {
+				DPRINTF("bad reseed counter: %u, expected %u",
+				    D->reseed_counter, reseed_counter);
+				ok = false;
+			}
+
+			nist_hash_drbg_destroy(D);
+		}
+	}
+
+	if (!ok)
+		return 1;
+	return 0;
+}
Index: src/sys/crypto/nist_hash_drbg/nist_hash_drbg.h
diff -u /dev/null src/sys/crypto/nist_hash_drbg/nist_hash_drbg.h:1.1
--- /dev/null	Mon Sep  2 20:09:30 2019
+++ src/sys/crypto/nist_hash_drbg/nist_hash_drbg.h	Mon Sep  2 20:09:29 2019
@@ -0,0 +1,85 @@
+/*	$NetBSD: nist_hash_drbg.h,v 1.1 2019/09/02 20:09:29 riastradh Exp $	*/
+
+/*-
+ * Copyright (c) 2019 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Taylor R. Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef	NIST_HASH_DRBG_H
+#define	NIST_HASH_DRBG_H
+
+#include <sys/types.h>
+
+/* Instantiation: SHA-256 */
+
+/* 10.1 DRBG Mechanisms Based on Hash Functions, Table 2, SHA-256 column */
+#define	NIST_SHA256_HASH_DRBG_SEEDLEN		440u
+
+#define	NIST_HASH_DRBG_SEEDLEN		NIST_SHA256_HASH_DRBG_SEEDLEN
+#define	nist_hash_drbg			nist_sha256_hash_drbg
+#define	nist_hash_drbg_destroy		nist_sha256_hash_drbg_destroy
+#define	nist_hash_drbg_generate		nist_sha256_hash_drbg_generate
+#define	nist_hash_drbg_initialize	nist_sha256_hash_drbg_initialize
+#define	nist_hash_drbg_instantiate	nist_sha256_hash_drbg_instantiate
+#define	nist_hash_drbg_reseed		nist_sha256_hash_drbg_reseed
+
+/*
+ * By 10.1 DRBG Mechanisms Based on Hash Functions, Table 2, the limit
+ * is <2^48 requests between reseeds.  We truncate this to fit in
+ * 32-bit signed integer instead for hysterical raisins.
+ */
+#define	NIST_HASH_DRBG_RESEED_INTERVAL	0x7fffffff
+
+/* 10.1 DRBG Mechanisms Based on Hash Functions, Table 2 */
+#define	NIST_HASH_DRBG_MAX_REQUEST	0x80000
+#define	NIST_HASH_DRBG_MAX_REQUEST_BYTES (NIST_HASH_DRBG_MAX_REQUEST/8)
+
+#define	NIST_HASH_DRBG_SEEDLEN_BYTES	(NIST_HASH_DRBG_SEEDLEN/8)
+
+#define	NIST_HASH_DRBG_MIN_SEEDLEN_BYTES				      \
+	MIN(32, NIST_HASH_DRBG_SEEDLEN_BYTES)
+
+/* 10.1.1.1 Hash_DRBG Internal State */
+
+struct nist_hash_drbg {
+	uint8_t		V[NIST_HASH_DRBG_SEEDLEN_BYTES];
+	uint8_t		C[NIST_HASH_DRBG_SEEDLEN_BYTES];
+	unsigned	reseed_counter;
+};
+
+typedef struct nist_hash_drbg	NIST_HASH_DRBG;
+
+int	nist_hash_drbg_initialize(void); /* self-test */
+int	nist_hash_drbg_instantiate(struct nist_hash_drbg *,
+	    const void *, size_t, const void *, size_t, const void *, size_t);
+int	nist_hash_drbg_reseed(struct nist_hash_drbg *,
+	    const void *, size_t, const void *, size_t);
+int	nist_hash_drbg_generate(struct nist_hash_drbg *, void *, size_t,
+	    const void *, size_t);
+int	nist_hash_drbg_destroy(struct nist_hash_drbg *);
+
+#endif	/* NIST_HASH_DRBG_H */

Reply via email to