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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 #include <sys/types.h> 26 #include <sys/sysmacros.h> 27 #include <sys/modctl.h> 28 #include <sys/conf.h> 29 #include <sys/devops.h> 30 #include <sys/cmn_err.h> 31 #include <sys/kmem.h> 32 #include <sys/stat.h> 33 #include <sys/open.h> 34 #include <sys/file.h> 35 #include <sys/cpuvar.h> 36 #include <sys/disp.h> 37 #include <sys/hsvc.h> 38 #include <sys/machsystm.h> 39 #include <sys/ksynch.h> 40 #include <sys/hypervisor_api.h> 41 #include <sys/n2rng.h> 42 #include <sys/sha1.h> 43 #include <sys/ddi.h> /* near end to get min and max macros right */ 44 #include <sys/sunddi.h> 45 #include <rng/fips_random.h> 46 47 /* n must be a power of 2 */ 48 #define ROUNDUP(k, n) (((k) + (n) - 1) & ~((n) - 1)) 49 50 /* 51 * Policy. ENTROPY_STARVATION is the maximum number of calls each 52 * FIPS instance will accept without successfully getting more 53 * entropy. It needs to be large enough to allow RNG operations to 54 * not stall because of health checks, etc. But we don't want it too 55 * large. FIPS 186-2 change 1 (5 October 2001) states that no more 56 * that 2,000,000 DSA signatures (done using this algorithm) should be 57 * done without reseeding. We make sure we add 64 bits of entropy at 58 * most every 10000 operations, hence we will have stirred in 160 bits 59 * of entropy at most once every 30000 operations. Normally, we stir 60 * in 64 bits of entropy for every number generated. 61 */ 62 #define ENTROPY_STARVATION 10000ULL 63 64 65 int 66 fips_random(n2rng_t *n2rng, uint8_t *out, size_t nbytes) 67 { 68 int i; 69 fipsrandomstruct_t *frsp; 70 int rv; 71 union { 72 uint32_t as32[SHA1WORDS]; 73 uint64_t as64[ROUNDUP(SHA1WORDS, 2) >> 1]; 74 } entropy = {0}; 75 uint32_t tempout[SHA1WORDS]; 76 77 78 for (i = 0; i < nbytes; i += SHA1BYTES) { 79 frsp = &n2rng->n_frs.fipsarray[ 80 atomic_inc_32_nv(&n2rng->n_frs.fips_round_robin_j) % 81 N2RNG_FIPS_INSTANCES]; 82 /* 83 * Since in the new scheme of things, the RNG latency 84 * will be high on reads after the first, we get just 85 * one word of entropy per call. 86 */ 87 if ((rv = n2rng_getentropy(n2rng, (void *)&entropy.as64[1], 88 sizeof (uint64_t))) != 0) { 89 90 /* 91 * If all rngs have failed, dispatch task to unregister 92 * from kcf and put the driver in an error state. If 93 * recoverable errors persist, a configuration retry 94 * will be initiated. 95 */ 96 if (rv == EPERM) { 97 n2rng_failure(n2rng); 98 return (EIO); 99 } 100 /* Failure with possible recovery */ 101 entropy.as64[1] = 0; 102 } 103 104 /* 105 * The idea here is that a Niagara2 chip is highly 106 * parallel, with many strands. If we have just one 107 * instance of the FIPS data, then only one FIPS 108 * computation can happen at a time, serializeing all 109 * the RNG stuff. So we make N2RNG_FIPS_INSTANCES, 110 * and use them round-robin, with the counter being 111 * n2rng->n_frs.fips_round_robin_j. We increment the 112 * counter with an atomic op, avoiding having to have 113 * a global muxtex. The atomic ops are also 114 * significantly faster than mutexes. The mutex is 115 * put inside the loop, otherwise one thread reading 116 * many blocks could stall all other strands. 117 */ 118 frsp = &n2rng->n_frs.fipsarray[ 119 atomic_inc_32_nv(&n2rng->n_frs.fips_round_robin_j) % 120 N2RNG_FIPS_INSTANCES]; 121 122 mutex_enter(&frsp->mtx); 123 124 if (entropy.as64[1] == 0) { 125 /* 126 * If we did not get any entropy, entropyword 127 * is zero. We get a false positive with 128 * probablitity 2^-64. It's not worth a few 129 * extra stores and tests eliminate the false 130 * positive. 131 */ 132 if (++frsp->entropyhunger > ENTROPY_STARVATION) { 133 mutex_exit(&frsp->mtx); 134 n2rng_unconfigured(n2rng); 135 return (EIO); 136 } 137 } else { 138 frsp->entropyhunger = 0; 139 } 140 141 /* nbytes - i is bytes to go */ 142 fips_random_inner(frsp->XKEY, tempout, entropy.as32); 143 144 /* 145 * Compare last round with the results of this round, fail 146 * if identical. Save for next round. 147 */ 148 if (n2rng->n_is_fips == B_TRUE) { 149 uint32_t differ = 0; 150 int j; 151 152 for (j = 0; j < 5; j++) { 153 differ |= tempout[j] ^ frsp->x_jminus1[j]; 154 frsp->x_jminus1[j] = tempout[j]; 155 } 156 if (differ == 0) { 157 /* 158 * If differ == 0, the RNG produced the same 159 * answer twice. By FIPS 140-2 Section 4.9 we 160 * must enter an error state. 161 */ 162 mutex_exit(&frsp->mtx); 163 n2rng_failure(n2rng); 164 cmn_err(CE_WARN, 165 "n2rng: Continuous random number generator" 166 " test of FIPS-140 RNG failed."); 167 return (EIO); 168 } 169 } 170 171 bcopy(tempout, &out[i], min(nbytes - i, SHA1BYTES)); 172 173 mutex_exit(&frsp->mtx); 174 } 175 176 /* Zeroize sensitive information */ 177 178 entropy.as64[1] = 0; 179 bzero(tempout, SHA1BYTES); 180 181 return (0); 182 } 183 184 /* 185 * Initializes one FIPS RNG instance. Must be called once for each 186 * instance. 187 */ 188 int 189 n2rng_fips_random_init(n2rng_t *n2rng, fipsrandomstruct_t *frsp) 190 { 191 /* 192 * All FIPS-approved algorithms will operate as cryptograpic 193 * quality PRNGs even if there is no entropy source. (In 194 * fact, this the only one that accepts entropy on the fly.) 195 * One motivation for this is that they system keeps on 196 * delivering cryptographic quality random numbers, even if 197 * the entropy source fails. 198 */ 199 200 int rv; 201 static uint32_t FIPS_RNG_NO_USER_INPUT[] = {0, 0, 0, 0, 0}; 202 203 rv = n2rng_getentropy(n2rng, (void *)frsp->XKEY, ROUNDUP(SHA1BYTES, 8)); 204 if (rv) { 205 return (rv); 206 } 207 frsp->entropyhunger = 0; 208 mutex_init(&frsp->mtx, NULL, MUTEX_DRIVER, NULL); 209 210 /* compute the first (compare only) random value */ 211 fips_random_inner(frsp->XKEY, frsp->x_jminus1, FIPS_RNG_NO_USER_INPUT); 212 213 return (0); 214 } 215 216 void 217 n2rng_fips_random_fini(fipsrandomstruct_t *frsp) 218 { 219 mutex_destroy(&frsp->mtx); 220 /* 221 * Zeroise fips data. Not really necessary, since the 222 * algorithm has backtracking resistance, but do it anyway. 223 */ 224 bzero(frsp, sizeof (fipsrandomstruct_t)); 225 } 226