1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/types.h> 27 #include <sys/sysmacros.h> 28 #include <sys/modctl.h> 29 #include <sys/conf.h> 30 #include <sys/devops.h> 31 #include <sys/cmn_err.h> 32 #include <sys/kmem.h> 33 #include <sys/stat.h> 34 #include <sys/open.h> 35 #include <sys/file.h> 36 #include <sys/cpuvar.h> 37 #include <sys/disp.h> 38 #include <sys/hsvc.h> 39 #include <sys/machsystm.h> 40 #include <sys/ksynch.h> 41 #include <sys/hypervisor_api.h> 42 #include <sys/n2rng.h> 43 #include <sys/sha1.h> 44 #include <sys/ddi.h> /* near end to get min and max macros right */ 45 #include <sys/sunddi.h> 46 #include <rng/fips_random.h> 47 48 /* n must be a power of 2 */ 49 #define ROUNDUP(k, n) (((k) + (n) - 1) & ~((n) - 1)) 50 51 /* 52 * Policy. ENTROPY_STARVATION is the maximum number of calls each 53 * FIPS instance will accept without successfully getting more 54 * entropy. It needs to be large enough to allow RNG operations to 55 * not stall because of health checks, etc. But we don't want it too 56 * large. FIPS 186-2 change 1 (5 October 2001) states that no more 57 * that 2,000,000 DSA signatures (done using this algorithm) should be 58 * done without reseeding. We make sure we add 64 bits of entropy at 59 * most every 10000 operations, hence we will have stirred in 160 bits 60 * of entropy at most once every 30000 operations. Normally, we stir 61 * in 64 bits of entropy for every number generated. 62 */ 63 #define ENTROPY_STARVATION 10000ULL 64 65 66 int 67 fips_random(n2rng_t *n2rng, uint8_t *out, size_t nbytes) 68 { 69 int i; 70 fipsrandomstruct_t *frsp; 71 int rv; 72 union { 73 uint32_t as32[SHA1WORDS]; 74 uint64_t as64[ROUNDUP(SHA1WORDS, 2) >> 1]; 75 } entropy = {0}; 76 uint32_t tempout[SHA1WORDS]; 77 78 79 for (i = 0; i < nbytes; i += SHA1BYTES) { 80 frsp = &n2rng->n_frs.fipsarray[ 81 atomic_inc_32_nv(&n2rng->n_frs.fips_round_robin_j) % 82 N2RNG_FIPS_INSTANCES]; 83 /* 84 * Since in the new scheme of things, the RNG latency 85 * will be high on reads after the first, we get just 86 * one word of entropy per call. 87 */ 88 if ((rv = n2rng_getentropy(n2rng, (void *)&entropy.as64[1], 89 sizeof (uint64_t))) != 0) { 90 91 /* 92 * If all rngs have failed, dispatch task to unregister 93 * from kcf and put the driver in an error state. If 94 * recoverable errors persist, a configuration retry 95 * will be initiated. 96 */ 97 if (rv == EPERM) { 98 n2rng_failure(n2rng); 99 return (EIO); 100 } 101 /* Failure with possible recovery */ 102 entropy.as64[1] = 0; 103 } 104 105 /* 106 * The idea here is that a Niagara2 chip is highly 107 * parallel, with many strands. If we have just one 108 * instance of the FIPS data, then only one FIPS 109 * computation can happen at a time, serializeing all 110 * the RNG stuff. So we make N2RNG_FIPS_INSTANCES, 111 * and use them round-robin, with the counter being 112 * n2rng->n_frs.fips_round_robin_j. We increment the 113 * counter with an atomic op, avoiding having to have 114 * a global muxtex. The atomic ops are also 115 * significantly faster than mutexes. The mutex is 116 * put inside the loop, otherwise one thread reading 117 * many blocks could stall all other strands. 118 */ 119 frsp = &n2rng->n_frs.fipsarray[ 120 atomic_inc_32_nv(&n2rng->n_frs.fips_round_robin_j) % 121 N2RNG_FIPS_INSTANCES]; 122 123 mutex_enter(&frsp->mtx); 124 125 if (entropy.as64[1] == 0) { 126 /* 127 * If we did not get any entropy, entropyword 128 * is zero. We get a false positive with 129 * probablitity 2^-64. It's not worth a few 130 * extra stores and tests eliminate the false 131 * positive. 132 */ 133 if (++frsp->entropyhunger > ENTROPY_STARVATION) { 134 mutex_exit(&frsp->mtx); 135 n2rng_unconfigured(n2rng); 136 return (EIO); 137 } 138 } else { 139 frsp->entropyhunger = 0; 140 } 141 142 /* nbytes - i is bytes to go */ 143 fips_random_inner(frsp->XKEY, tempout, entropy.as32); 144 bcopy(tempout, &out[i], min(nbytes - i, SHA1BYTES)); 145 146 mutex_exit(&frsp->mtx); 147 } 148 149 /* Zeroize sensitive information */ 150 151 entropy.as64[1] = 0; 152 bzero(tempout, SHA1BYTES); 153 154 return (0); 155 } 156 157 /* 158 * Initializes one FIPS RNG instance. Must be called once for each 159 * instance. 160 */ 161 int 162 n2rng_fips_random_init(n2rng_t *n2rng, fipsrandomstruct_t *frsp) 163 { 164 /* 165 * All FIPS-approved algorithms will operate as cryptograpic 166 * quality PRNGs even if there is no entropy source. (In 167 * fact, this the only one that accepts entropy on the fly.) 168 * One motivation for this is that they system keeps on 169 * delivering cryptographic quality random numbers, even if 170 * the entropy source fails. 171 */ 172 173 int rv; 174 175 rv = n2rng_getentropy(n2rng, (void *)frsp->XKEY, ROUNDUP(SHA1BYTES, 8)); 176 if (rv) { 177 return (rv); 178 } 179 frsp->entropyhunger = 0; 180 mutex_init(&frsp->mtx, NULL, MUTEX_DRIVER, NULL); 181 182 return (0); 183 } 184 185 void 186 n2rng_fips_random_fini(fipsrandomstruct_t *frsp) 187 { 188 mutex_destroy(&frsp->mtx); 189 /* 190 * Zeroise fips data. Not really necessary, since the 191 * algorithm has backtracking resistance, but do it anyway. 192 */ 193 bzero(frsp, sizeof (fipsrandomstruct_t)); 194 } 195