1 1.44 riastrad /* $NetBSD: subr_cprng.c,v 1.44 2023/08/05 11:21:24 riastradh Exp $ */ 2 1.1 tls 3 1.1 tls /*- 4 1.36 riastrad * Copyright (c) 2019 The NetBSD Foundation, Inc. 5 1.1 tls * All rights reserved. 6 1.1 tls * 7 1.1 tls * This code is derived from software contributed to The NetBSD Foundation 8 1.36 riastrad * by Taylor R. Campbell. 9 1.1 tls * 10 1.1 tls * Redistribution and use in source and binary forms, with or without 11 1.1 tls * modification, are permitted provided that the following conditions 12 1.1 tls * are met: 13 1.1 tls * 1. Redistributions of source code must retain the above copyright 14 1.1 tls * notice, this list of conditions and the following disclaimer. 15 1.1 tls * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 tls * notice, this list of conditions and the following disclaimer in the 17 1.1 tls * documentation and/or other materials provided with the distribution. 18 1.1 tls * 19 1.1 tls * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 tls * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 tls * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 tls * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 tls * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 tls * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 tls * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 tls * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 tls * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 tls * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 tls * POSSIBILITY OF SUCH DAMAGE. 30 1.1 tls */ 31 1.1 tls 32 1.36 riastrad /* 33 1.36 riastrad * cprng_strong 34 1.36 riastrad * 35 1.36 riastrad * Per-CPU NIST Hash_DRBG, reseeded automatically from the entropy 36 1.36 riastrad * pool when we transition to full entropy, never blocking. This 37 1.36 riastrad * is slightly different from the old cprng_strong API, but the 38 1.36 riastrad * only users of the old one fell into three categories: 39 1.36 riastrad * 40 1.36 riastrad * 1. never-blocking, oughta-be-per-CPU (kern_cprng, sysctl_prng) 41 1.36 riastrad * 2. never-blocking, used per-CPU anyway (/dev/urandom short reads) 42 1.36 riastrad * 3. /dev/random 43 1.36 riastrad * 44 1.36 riastrad * This code serves the first two categories without having extra 45 1.36 riastrad * logic for /dev/random. 46 1.36 riastrad * 47 1.42 riastrad * kern_cprng - available at IPL_SOFTSERIAL or lower 48 1.36 riastrad * user_cprng - available only at IPL_NONE in thread context 49 1.36 riastrad * 50 1.36 riastrad * The name kern_cprng is for hysterical raisins. The name 51 1.36 riastrad * user_cprng serves only to contrast with kern_cprng. 52 1.36 riastrad */ 53 1.36 riastrad 54 1.18 riastrad #include <sys/cdefs.h> 55 1.44 riastrad __KERNEL_RCSID(0, "$NetBSD: subr_cprng.c,v 1.44 2023/08/05 11:21:24 riastradh Exp $"); 56 1.18 riastrad 57 1.41 skrll #include <sys/param.h> 58 1.1 tls #include <sys/types.h> 59 1.18 riastrad #include <sys/cprng.h> 60 1.36 riastrad #include <sys/cpu.h> 61 1.36 riastrad #include <sys/entropy.h> 62 1.18 riastrad #include <sys/errno.h> 63 1.36 riastrad #include <sys/evcnt.h> 64 1.36 riastrad #include <sys/intr.h> 65 1.18 riastrad #include <sys/kmem.h> 66 1.24 tls #include <sys/percpu.h> 67 1.36 riastrad #include <sys/sysctl.h> 68 1.1 tls #include <sys/systm.h> 69 1.18 riastrad 70 1.31 riastrad #include <crypto/nist_hash_drbg/nist_hash_drbg.h> 71 1.1 tls 72 1.36 riastrad /* 73 1.36 riastrad * struct cprng_strong 74 1.36 riastrad */ 75 1.18 riastrad struct cprng_strong { 76 1.36 riastrad struct percpu *cs_percpu; /* struct cprng_cpu */ 77 1.36 riastrad ipl_cookie_t cs_iplcookie; 78 1.36 riastrad }; 79 1.21 riastrad 80 1.36 riastrad /* 81 1.36 riastrad * struct cprng_cpu 82 1.36 riastrad * 83 1.36 riastrad * Per-CPU state for a cprng_strong. The DRBG and evcnt are 84 1.36 riastrad * allocated separately because percpu(9) sometimes moves per-CPU 85 1.36 riastrad * objects around without zeroing them. 86 1.36 riastrad */ 87 1.36 riastrad struct cprng_cpu { 88 1.36 riastrad struct nist_hash_drbg *cc_drbg; 89 1.36 riastrad struct { 90 1.36 riastrad struct evcnt reseed; 91 1.36 riastrad } *cc_evcnt; 92 1.36 riastrad unsigned cc_epoch; 93 1.18 riastrad }; 94 1.18 riastrad 95 1.36 riastrad static int sysctl_kern_urandom(SYSCTLFN_ARGS); 96 1.36 riastrad static int sysctl_kern_arandom(SYSCTLFN_ARGS); 97 1.36 riastrad static void cprng_init_cpu(void *, void *, struct cpu_info *); 98 1.36 riastrad static void cprng_fini_cpu(void *, void *, struct cpu_info *); 99 1.36 riastrad 100 1.36 riastrad /* Well-known CPRNG instances */ 101 1.42 riastrad struct cprng_strong *kern_cprng __read_mostly; /* IPL_SOFTSERIAL */ 102 1.36 riastrad struct cprng_strong *user_cprng __read_mostly; /* IPL_NONE */ 103 1.18 riastrad 104 1.36 riastrad static struct sysctllog *cprng_sysctllog __read_mostly; 105 1.18 riastrad 106 1.18 riastrad void 107 1.36 riastrad cprng_init(void) 108 1.8 tls { 109 1.8 tls 110 1.36 riastrad if (__predict_false(nist_hash_drbg_initialize() != 0)) 111 1.36 riastrad panic("NIST Hash_DRBG failed self-test"); 112 1.36 riastrad 113 1.18 riastrad /* 114 1.42 riastrad * Create CPRNG instances at two IPLs: IPL_SOFTSERIAL for 115 1.42 riastrad * kernel use that may occur inside soft interrupt handlers, 116 1.36 riastrad * and IPL_NONE for userland use which need not block 117 1.36 riastrad * interrupts. 118 1.18 riastrad */ 119 1.42 riastrad kern_cprng = cprng_strong_create("kern", IPL_SOFTSERIAL, 0); 120 1.36 riastrad user_cprng = cprng_strong_create("user", IPL_NONE, 0); 121 1.8 tls 122 1.36 riastrad /* Create kern.urandom and kern.arandom sysctl nodes. */ 123 1.36 riastrad sysctl_createv(&cprng_sysctllog, 0, NULL, NULL, 124 1.36 riastrad CTLFLAG_PERMANENT|CTLFLAG_READONLY, CTLTYPE_INT, "urandom", 125 1.36 riastrad SYSCTL_DESCR("Independent uniform random 32-bit integer"), 126 1.36 riastrad sysctl_kern_urandom, 0, NULL, 0, CTL_KERN, KERN_URND, CTL_EOL); 127 1.36 riastrad sysctl_createv(&cprng_sysctllog, 0, NULL, NULL, 128 1.36 riastrad CTLFLAG_PERMANENT|CTLFLAG_READONLY, CTLTYPE_INT /*lie*/, "arandom", 129 1.36 riastrad SYSCTL_DESCR("Independent uniform random bytes, up to 256 bytes"), 130 1.36 riastrad sysctl_kern_arandom, 0, NULL, 0, CTL_KERN, KERN_ARND, CTL_EOL); 131 1.8 tls } 132 1.8 tls 133 1.18 riastrad /* 134 1.36 riastrad * sysctl kern.urandom 135 1.36 riastrad * 136 1.36 riastrad * Independent uniform random 32-bit integer. Read-only. 137 1.18 riastrad */ 138 1.18 riastrad static int 139 1.36 riastrad sysctl_kern_urandom(SYSCTLFN_ARGS) 140 1.18 riastrad { 141 1.36 riastrad struct sysctlnode node = *rnode; 142 1.36 riastrad int v; 143 1.36 riastrad int error; 144 1.1 tls 145 1.36 riastrad /* Generate an int's worth of data. */ 146 1.36 riastrad cprng_strong(user_cprng, &v, sizeof v, 0); 147 1.7 tls 148 1.36 riastrad /* Do the sysctl dance. */ 149 1.36 riastrad node.sysctl_data = &v; 150 1.36 riastrad error = sysctl_lookup(SYSCTLFN_CALL(&node)); 151 1.36 riastrad 152 1.36 riastrad /* Clear the buffer before returning the sysctl error. */ 153 1.36 riastrad explicit_memset(&v, 0, sizeof v); 154 1.36 riastrad return error; 155 1.1 tls } 156 1.1 tls 157 1.36 riastrad /* 158 1.36 riastrad * sysctl kern.arandom 159 1.36 riastrad * 160 1.36 riastrad * Independent uniform random bytes, up to 256 bytes. Read-only. 161 1.36 riastrad */ 162 1.29 christos static int 163 1.36 riastrad sysctl_kern_arandom(SYSCTLFN_ARGS) 164 1.29 christos { 165 1.36 riastrad struct sysctlnode node = *rnode; 166 1.36 riastrad uint8_t buf[256]; 167 1.36 riastrad int error; 168 1.29 christos 169 1.36 riastrad /* 170 1.36 riastrad * Clamp to a reasonably small size. 256 bytes is kind of 171 1.36 riastrad * arbitrary; 32 would be more reasonable, but we used 256 in 172 1.36 riastrad * the past, so let's not break compatibility. 173 1.36 riastrad */ 174 1.36 riastrad if (*oldlenp > 256) /* size_t, so never negative */ 175 1.37 nia *oldlenp = 256; 176 1.29 christos 177 1.36 riastrad /* Generate data. */ 178 1.36 riastrad cprng_strong(user_cprng, buf, *oldlenp, 0); 179 1.29 christos 180 1.36 riastrad /* Do the sysctl dance. */ 181 1.36 riastrad node.sysctl_data = buf; 182 1.36 riastrad node.sysctl_size = *oldlenp; 183 1.36 riastrad error = sysctl_lookup(SYSCTLFN_CALL(&node)); 184 1.36 riastrad 185 1.36 riastrad /* Clear the buffer before returning the sysctl error. */ 186 1.36 riastrad explicit_memset(buf, 0, sizeof buf); 187 1.36 riastrad return error; 188 1.29 christos } 189 1.29 christos 190 1.36 riastrad struct cprng_strong * 191 1.36 riastrad cprng_strong_create(const char *name, int ipl, int flags) 192 1.29 christos { 193 1.36 riastrad struct cprng_strong *cprng; 194 1.29 christos 195 1.36 riastrad cprng = kmem_alloc(sizeof(*cprng), KM_SLEEP); 196 1.36 riastrad cprng->cs_iplcookie = makeiplcookie(ipl); 197 1.36 riastrad cprng->cs_percpu = percpu_create(sizeof(struct cprng_cpu), 198 1.36 riastrad cprng_init_cpu, cprng_fini_cpu, __UNCONST(name)); 199 1.29 christos 200 1.36 riastrad return cprng; 201 1.29 christos } 202 1.29 christos 203 1.36 riastrad void 204 1.36 riastrad cprng_strong_destroy(struct cprng_strong *cprng) 205 1.15 tls { 206 1.18 riastrad 207 1.36 riastrad percpu_free(cprng->cs_percpu, sizeof(struct cprng_cpu)); 208 1.36 riastrad kmem_free(cprng, sizeof(*cprng)); 209 1.15 tls } 210 1.15 tls 211 1.18 riastrad static void 212 1.36 riastrad cprng_init_cpu(void *ptr, void *cookie, struct cpu_info *ci) 213 1.18 riastrad { 214 1.36 riastrad struct cprng_cpu *cc = ptr; 215 1.36 riastrad const char *name = cookie; 216 1.39 riastrad const char *cpuname; 217 1.36 riastrad uint8_t zero[NIST_HASH_DRBG_SEEDLEN_BYTES] = {0}; 218 1.36 riastrad char namebuf[64]; /* XXX size? */ 219 1.18 riastrad 220 1.18 riastrad /* 221 1.36 riastrad * Format the name as, e.g., kern/8 if we're on cpu8. This 222 1.36 riastrad * doesn't get displayed anywhere; it just ensures that if 223 1.36 riastrad * there were a bug causing us to use the same otherwise secure 224 1.36 riastrad * seed on multiple CPUs, we would still get independent output 225 1.36 riastrad * from the NIST Hash_DRBG. 226 1.18 riastrad */ 227 1.36 riastrad snprintf(namebuf, sizeof namebuf, "%s/%u", name, cpu_index(ci)); 228 1.1 tls 229 1.18 riastrad /* 230 1.36 riastrad * Allocate the struct nist_hash_drbg and struct evcnt 231 1.36 riastrad * separately, since percpu(9) may move objects around in 232 1.36 riastrad * memory without zeroing. 233 1.18 riastrad */ 234 1.36 riastrad cc->cc_drbg = kmem_zalloc(sizeof(*cc->cc_drbg), KM_SLEEP); 235 1.36 riastrad cc->cc_evcnt = kmem_alloc(sizeof(*cc->cc_evcnt), KM_SLEEP); 236 1.1 tls 237 1.18 riastrad /* 238 1.36 riastrad * Initialize the DRBG with no seed. We do this in order to 239 1.36 riastrad * defer reading from the entropy pool as long as possible. 240 1.18 riastrad */ 241 1.36 riastrad if (__predict_false(nist_hash_drbg_instantiate(cc->cc_drbg, 242 1.36 riastrad zero, sizeof zero, NULL, 0, namebuf, strlen(namebuf)))) 243 1.36 riastrad panic("nist_hash_drbg_instantiate"); 244 1.36 riastrad 245 1.36 riastrad /* Attach the event counters. */ 246 1.39 riastrad /* XXX ci_cpuname may not be initialized early enough. */ 247 1.39 riastrad cpuname = ci->ci_cpuname[0] == '\0' ? "cpu0" : ci->ci_cpuname; 248 1.36 riastrad evcnt_attach_dynamic(&cc->cc_evcnt->reseed, EVCNT_TYPE_MISC, NULL, 249 1.39 riastrad cpuname, "cprng_strong reseed"); 250 1.36 riastrad 251 1.36 riastrad /* Set the epoch uninitialized so we reseed on first use. */ 252 1.36 riastrad cc->cc_epoch = 0; 253 1.18 riastrad } 254 1.1 tls 255 1.18 riastrad static void 256 1.36 riastrad cprng_fini_cpu(void *ptr, void *cookie, struct cpu_info *ci) 257 1.18 riastrad { 258 1.36 riastrad struct cprng_cpu *cc = ptr; 259 1.5 tls 260 1.36 riastrad evcnt_detach(&cc->cc_evcnt->reseed); 261 1.36 riastrad if (__predict_false(nist_hash_drbg_destroy(cc->cc_drbg))) 262 1.36 riastrad panic("nist_hash_drbg_destroy"); 263 1.1 tls 264 1.36 riastrad kmem_free(cc->cc_evcnt, sizeof(*cc->cc_evcnt)); 265 1.36 riastrad kmem_free(cc->cc_drbg, sizeof(*cc->cc_drbg)); 266 1.1 tls } 267 1.1 tls 268 1.44 riastrad static void 269 1.44 riastrad cprng_strong_reseed(struct cprng_strong *cprng, unsigned epoch, 270 1.44 riastrad struct cprng_cpu **ccp, int *sp) 271 1.44 riastrad { 272 1.44 riastrad uint8_t seed[NIST_HASH_DRBG_SEEDLEN_BYTES]; 273 1.44 riastrad 274 1.44 riastrad /* 275 1.44 riastrad * Drop everything to extract a fresh seed from the entropy 276 1.44 riastrad * pool. entropy_extract may sleep on an adaptive lock, which 277 1.44 riastrad * invalidates our percpu(9) reference. 278 1.44 riastrad * 279 1.44 riastrad * This may race with reseeding in another thread, which is no 280 1.44 riastrad * big deal -- worst case, we rewind the entropy epoch here and 281 1.44 riastrad * cause the next caller to reseed again, and in the end we 282 1.44 riastrad * just reseed a couple more times than necessary. 283 1.44 riastrad */ 284 1.44 riastrad splx(*sp); 285 1.44 riastrad percpu_putref(cprng->cs_percpu); 286 1.44 riastrad entropy_extract(seed, sizeof seed, 0); 287 1.44 riastrad *ccp = percpu_getref(cprng->cs_percpu); 288 1.44 riastrad *sp = splraiseipl(cprng->cs_iplcookie); 289 1.44 riastrad 290 1.44 riastrad (*ccp)->cc_evcnt->reseed.ev_count++; 291 1.44 riastrad if (__predict_false(nist_hash_drbg_reseed((*ccp)->cc_drbg, 292 1.44 riastrad seed, sizeof seed, NULL, 0))) 293 1.44 riastrad panic("nist_hash_drbg_reseed"); 294 1.44 riastrad explicit_memset(seed, 0, sizeof seed); 295 1.44 riastrad (*ccp)->cc_epoch = epoch; 296 1.44 riastrad } 297 1.44 riastrad 298 1.36 riastrad size_t 299 1.36 riastrad cprng_strong(struct cprng_strong *cprng, void *buf, size_t len, int flags) 300 1.1 tls { 301 1.36 riastrad struct cprng_cpu *cc; 302 1.36 riastrad unsigned epoch; 303 1.36 riastrad int s; 304 1.1 tls 305 1.42 riastrad /* Not allowed in hard interrupt context. */ 306 1.42 riastrad KASSERT(!cpu_intr_p()); 307 1.42 riastrad 308 1.1 tls /* 309 1.36 riastrad * Verify maximum request length. Caller should really limit 310 1.36 riastrad * their requests to 32 bytes to avoid spending much time with 311 1.36 riastrad * preemption disabled -- use the 32 bytes to seed a private 312 1.36 riastrad * DRBG instance if you need more data. 313 1.1 tls */ 314 1.36 riastrad KASSERT(len <= CPRNG_MAX_LEN); 315 1.18 riastrad 316 1.36 riastrad /* Verify legacy API use. */ 317 1.36 riastrad KASSERT(flags == 0); 318 1.1 tls 319 1.36 riastrad /* Acquire per-CPU state and block interrupts. */ 320 1.36 riastrad cc = percpu_getref(cprng->cs_percpu); 321 1.36 riastrad s = splraiseipl(cprng->cs_iplcookie); 322 1.36 riastrad 323 1.36 riastrad /* If the entropy epoch has changed, (re)seed. */ 324 1.36 riastrad epoch = entropy_epoch(); 325 1.44 riastrad if (__predict_false(epoch != cc->cc_epoch)) 326 1.44 riastrad cprng_strong_reseed(cprng, epoch, &cc, &s); 327 1.1 tls 328 1.36 riastrad /* Generate data. Failure here means it's time to reseed. */ 329 1.36 riastrad if (__predict_false(nist_hash_drbg_generate(cc->cc_drbg, buf, len, 330 1.36 riastrad NULL, 0))) { 331 1.44 riastrad cprng_strong_reseed(cprng, epoch, &cc, &s); 332 1.36 riastrad if (__predict_false(nist_hash_drbg_generate(cc->cc_drbg, 333 1.36 riastrad buf, len, NULL, 0))) 334 1.36 riastrad panic("nist_hash_drbg_generate"); 335 1.36 riastrad } 336 1.23 pooka 337 1.36 riastrad /* Release state and interrupts. */ 338 1.36 riastrad splx(s); 339 1.36 riastrad percpu_putref(cprng->cs_percpu); 340 1.23 pooka 341 1.36 riastrad /* Return the number of bytes generated, for hysterical raisins. */ 342 1.36 riastrad return len; 343 1.23 pooka } 344 1.23 pooka 345 1.36 riastrad uint32_t 346 1.36 riastrad cprng_strong32(void) 347 1.23 pooka { 348 1.36 riastrad uint32_t r; 349 1.36 riastrad cprng_strong(kern_cprng, &r, sizeof(r), 0); 350 1.36 riastrad return r; 351 1.23 pooka } 352 1.23 pooka 353 1.36 riastrad uint64_t 354 1.36 riastrad cprng_strong64(void) 355 1.23 pooka { 356 1.36 riastrad uint64_t r; 357 1.36 riastrad cprng_strong(kern_cprng, &r, sizeof(r), 0); 358 1.36 riastrad return r; 359 1.23 pooka } 360