diff --git a/Makefile.in b/Makefile.in
index 779b8922f060f7d246ffea22c2d9a2d74e04574b..905ebd6b1ad18efc8dbb2dd822815c6247ac8b6a 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -164,7 +164,8 @@ nettle_SOURCES = aes-decrypt-internal.c aes-decrypt.c aes-decrypt-table.c \
 		 version.c \
 		 write-be32.c write-le32.c write-le64.c \
 		 yarrow256.c yarrow_key_event.c \
-		 xts.c xts-aes128.c xts-aes256.c
+		 xts.c xts-aes128.c xts-aes256.c \
+		 drbg-ctr-aes256.c
 
 hogweed_SOURCES = sexp.c sexp-format.c \
 		  sexp-transport.c sexp-transport-format.c \
@@ -243,7 +244,8 @@ HEADERS = aes.h arcfour.h arctwo.h asn1.h blowfish.h balloon.h \
 	  pgp.h pkcs1.h pss.h pss-mgf1.h realloc.h ripemd160.h rsa.h \
 	  salsa20.h sexp.h serpent.h \
 	  sha.h sha1.h sha2.h sha3.h sm3.h sm4.h streebog.h twofish.h \
-	  umac.h yarrow.h xts.h poly1305.h nist-keywrap.h
+	  umac.h yarrow.h xts.h poly1305.h nist-keywrap.h \
+	  drbg-ctr.h
 
 INSTALL_HEADERS = $(HEADERS) version.h @IF_MINI_GMP@ mini-gmp.h
 
diff --git a/NEWS b/NEWS
index 413538c6190fc65d86ddeb92c3b5c6ca6618a2d4..cf51326b3fb3da5e60bf6654125500aab09a1a05 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,9 @@
+NEWS for the Nettle 3.10 release
+
+	New features:
+
+	* Added DRBG-CTR with AES256, contributed by Simon Josefsson.
+
 NEWS for the Nettle 3.9.1 release
 
 	This is a bugfix release, fixing a few bugs reported for
diff --git a/drbg-ctr-aes256.c b/drbg-ctr-aes256.c
new file mode 100644
index 0000000000000000000000000000000000000000..b3e8e194779eccaac685c59ba350783ab07917d0
--- /dev/null
+++ b/drbg-ctr-aes256.c
@@ -0,0 +1,100 @@
+/* drbg-ctr-aes256.c
+
+   Copyright (C) 2023 Simon Josefsson
+
+   This file is part of GNU Nettle.
+
+   GNU Nettle is free software: you can redistribute it and/or
+   modify it under the terms of either:
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at your
+       option) any later version.
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at your
+       option) any later version.
+
+   or both in parallel, as here.
+
+   GNU Nettle is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see http://www.gnu.org/licenses/.
+*/
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "drbg-ctr.h"
+
+#include <string.h>
+#include "macros.h"
+#include "memxor.h"
+
+static void
+drbg_ctr_aes256_update (struct aes256_ctx *Key,
+			uint8_t *V, uint8_t *provided_data)
+{
+  uint8_t tmp[DRBG_CTR_AES256_SEED_SIZE];
+
+  INCREMENT (AES_BLOCK_SIZE, V);
+  aes256_encrypt (Key, AES_BLOCK_SIZE, tmp, V);
+
+  INCREMENT (AES_BLOCK_SIZE, V);
+  aes256_encrypt (Key, AES_BLOCK_SIZE, tmp + AES_BLOCK_SIZE, V);
+
+  INCREMENT (AES_BLOCK_SIZE, V);
+  aes256_encrypt (Key, AES_BLOCK_SIZE, tmp + 2 * AES_BLOCK_SIZE, V);
+
+  if (provided_data)
+    memxor (tmp, provided_data, 48);
+
+  aes256_set_encrypt_key (Key, tmp);
+
+  memcpy (V, tmp + AES256_KEY_SIZE, AES_BLOCK_SIZE);
+}
+
+void
+drbg_ctr_aes256_init (struct drbg_ctr_aes256_ctx *ctx, uint8_t *seed_material)
+{
+  uint8_t Key[AES256_KEY_SIZE];
+
+  memset (Key, 0, AES256_KEY_SIZE);
+  aes256_set_encrypt_key (&ctx->Key, Key);
+
+  memset (ctx->V, 0, AES_BLOCK_SIZE);
+
+  drbg_ctr_aes256_update (&ctx->Key, ctx->V, seed_material);
+}
+
+void
+drbg_ctr_aes256_random (struct drbg_ctr_aes256_ctx *ctx,
+			size_t n, uint8_t *dst)
+{
+  while (n >= AES_BLOCK_SIZE)
+    {
+      INCREMENT (AES_BLOCK_SIZE, ctx->V);
+      aes256_encrypt (&ctx->Key, AES_BLOCK_SIZE, dst, ctx->V);
+      dst += AES_BLOCK_SIZE;
+      n -= AES_BLOCK_SIZE;
+    }
+
+  if (n > 0)
+    {
+      uint8_t block[AES_BLOCK_SIZE];
+
+      INCREMENT (AES_BLOCK_SIZE, ctx->V);
+      aes256_encrypt (&ctx->Key, AES_BLOCK_SIZE, block, ctx->V);
+      memcpy (dst, block, n);
+    }
+
+  drbg_ctr_aes256_update (&ctx->Key, ctx->V, NULL);
+}
diff --git a/drbg-ctr.h b/drbg-ctr.h
new file mode 100644
index 0000000000000000000000000000000000000000..63ac36806638945544691a6f6698d54ca4f9adec
--- /dev/null
+++ b/drbg-ctr.h
@@ -0,0 +1,69 @@
+/* drbg-ctr.h
+
+   This file is part of GNU Nettle.
+
+   GNU Nettle is free software: you can redistribute it and/or
+   modify it under the terms of either:
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at your
+       option) any later version.
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at your
+       option) any later version.
+
+   or both in parallel, as here.
+
+   GNU Nettle is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see http://www.gnu.org/licenses/.
+*/
+
+#ifndef NETTLE_DRBG_CTR_H_INCLUDED
+#define NETTLE_DRBG_CTR_H_INCLUDED
+
+#include "nettle-types.h"
+
+#include "aes.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* Namespace mangling */
+#define drbg_ctr_aes256_init nettle_drbg_ctr_aes256_init
+#define drbg_ctr_aes256_random nettle_drbg_ctr_aes256_random
+
+#define DRBG_CTR_AES256_SEED_SIZE (AES_BLOCK_SIZE + AES256_KEY_SIZE)
+
+struct drbg_ctr_aes256_ctx
+{
+  struct aes256_ctx Key;
+  uint8_t V[AES_BLOCK_SIZE];
+};
+
+/* Initialize using DRBG_CTR_AES256_SEED_SIZE bytes of
+   SEED_MATERIAL.  */
+void
+drbg_ctr_aes256_init (struct drbg_ctr_aes256_ctx *ctx,
+		      uint8_t *seed_material);
+
+/* Output N bytes of random data into DST.  */
+void
+drbg_ctr_aes256_random (struct drbg_ctr_aes256_ctx *ctx,
+			size_t n, uint8_t *dst);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NETTLE_DRBG_CTR_H_INCLUDED */
diff --git a/nettle.texinfo b/nettle.texinfo
index 736150d955ca5e1cd5482379c00006369c6fd878..2da634531909da320bf5e84449580905247d2881 100644
--- a/nettle.texinfo
+++ b/nettle.texinfo
@@ -6298,6 +6298,45 @@ Returns an entropy estimate, in bits, suitable for calling
 @code{yarrow256_update}. Usually, 0, 1 or 2 bits.
 @end deftypefun
 
+@subsection DRBG-CTR
+
+The Deterministic Random Bit Generator (DRBG) family is a complex family
+of deterministic randomness generators published by NIST in SP 800-90A.
+
+We support what we believe is the reasonable parts of the CTR_DRBG
+algorithm for AES256.  Re-seeding, personalization strings, derivation
+functions and support for non-AES256 is not implemented.
+Personalization strings can be implemented by the caller, if desired,
+with xor.  If you need re-seeding or entropy derivation, we suggest that
+you use Yarrow instead.
+
+The security bounds of DRBG-CTR are not intuitive, see ``Security Bounds
+for the NIST Codebook-based Deterministic Random Bit Generator'' by
+Matthew J. Campagna, from @url{https://eprint.iacr.org/2006/379.pdf}.
+
+Our suggested use-case for DRBG-CTR is to deterministically generate
+known values from a seed when comparing against expected values for some
+other algorithm.
+
+Nettle defines DRBG-CTR in @file{<nettle/drbg-ctr.h>}.
+
+@deftp {Context struct} {struct drbg_ctr_aes256_ctx}
+@end deftp
+
+@defvr Constant DRBG_CTR_AES256_SEED_SIZE
+The size of the seeding material.
+@end defvr
+
+@deftypefun void drbg_ctr_aes256_init (struct drbg_ctr_aes256_ctx *@var{ctx}, uint8_t *@var{seed_material})
+Initialize the DRBG-CTR-AES256 context using
+@code{DRBG_CTR_AES256_SEED_SIZE} bytes of @var{seed_material}.
+@end deftypefun
+
+@deftypefun void drbg_ctr_aes256_random (struct drbg_ctr_aes256_ctx *@var{ctx}, size_t n, uint8_t *@var{dst});
+Generates @var{n} octets of output into @var{dst}.  The generator must
+be initialized before you call this function.
+@end deftypefun
+
 @node ASCII encoding
 @section ASCII encoding
 
diff --git a/testsuite/.gitignore b/testsuite/.gitignore
index 8c91d1af33517d6fc5f9f9c249fa967e1c0992fd..f237815237f0bf8cdbdff13088b54127f0e251cd 100644
--- a/testsuite/.gitignore
+++ b/testsuite/.gitignore
@@ -113,6 +113,7 @@
 /ed448-test
 /shake256-test
 /x86-ibt-test
+/drbg-ctr-aes256-test
 
 /test.in
 /test1.out
diff --git a/testsuite/Makefile.in b/testsuite/Makefile.in
index c11023a3e5e2b77c44f08e9506e395c6877930a0..eb68fe892e6366749744d56ea8ebf8066aaee502 100644
--- a/testsuite/Makefile.in
+++ b/testsuite/Makefile.in
@@ -34,7 +34,7 @@ TS_NETTLE_SOURCES = aes-test.c aes-keywrap-test.c arcfour-test.c arctwo-test.c \
 		    meta-hash-test.c meta-cipher-test.c\
 		    meta-aead-test.c meta-armor-test.c meta-mac-test.c \
 		    buffer-test.c yarrow-test.c xts-test.c pbkdf2-test.c \
-		    x86-ibt-test.c
+		    x86-ibt-test.c drbg-ctr-aes256.c
 
 TS_HOGWEED_SOURCES = sexp-test.c sexp-format-test.c \
 		     rsa2sexp-test.c sexp2rsa-test.c \
diff --git a/testsuite/drbg-ctr-aes256-test.c b/testsuite/drbg-ctr-aes256-test.c
new file mode 100644
index 0000000000000000000000000000000000000000..4f09d805d6771bf471195b0cd083fb216d8a1a93
--- /dev/null
+++ b/testsuite/drbg-ctr-aes256-test.c
@@ -0,0 +1,74 @@
+/* drbg-ctr-aes256-test.c
+
+   Copyright (C) 2023 Simon Josefsson
+
+   This file is part of GNU Nettle.
+
+   GNU Nettle is free software: you can redistribute it and/or
+   modify it under the terms of either:
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at your
+       option) any later version.
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at your
+       option) any later version.
+
+   or both in parallel, as here.
+
+   GNU Nettle is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see http://www.gnu.org/licenses/.
+*/
+
+#include "testutils.h"
+
+#include "drbg-ctr.h"
+
+void
+test_main (void)
+{
+  struct drbg_ctr_aes256_ctx rng;
+  uint8_t seed_material[DRBG_CTR_AES256_SEED_SIZE];
+  uint8_t tmp[DRBG_CTR_AES256_SEED_SIZE];
+  size_t i;
+
+  /* https://ntruprime.cr.yp.to/nist/ntruprime-20201007/Reference_Implementation/kem/sntrup761/nist/kat_kem.c.html
+     https://ntruprime.cr.yp.to/nist/ntruprime-20201007/KAT/kem/sntrup761/kat_kem.req.html
+   */
+
+  for (i = 0; i < DRBG_CTR_AES256_SEED_SIZE; i++)
+    seed_material[i] = i;
+
+  drbg_ctr_aes256_init (&rng, seed_material);
+
+  drbg_ctr_aes256_random (&rng, DRBG_CTR_AES256_SEED_SIZE, tmp);
+  if (!MEMEQ (DRBG_CTR_AES256_SEED_SIZE,
+	      tmp,
+	      H ("061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479"
+		 "D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA1")))
+    {
+      printf ("drbg_ctr_aes256 = ");
+      print_hex (DRBG_CTR_AES256_SEED_SIZE, tmp);
+      abort ();
+    }
+
+  drbg_ctr_aes256_random (&rng, DRBG_CTR_AES256_SEED_SIZE, tmp);
+  if (!MEMEQ (DRBG_CTR_AES256_SEED_SIZE,
+	      tmp,
+	      H ("D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835AD55"
+		 "B22E75BF57BB556AC81ADDE6AEEB4A5A875C3BFCADFA958F")))
+    {
+      printf ("drbg_ctr_aes256 = ");
+      print_hex (DRBG_CTR_AES256_SEED_SIZE, tmp);
+      abort ();
+    }
+}