1fe54a78eSHai-May Chao /*
2fe54a78eSHai-May Chao  * CDDL HEADER START
3fe54a78eSHai-May Chao  *
4fe54a78eSHai-May Chao  * The contents of this file are subject to the terms of the
5fe54a78eSHai-May Chao  * Common Development and Distribution License (the "License").
6fe54a78eSHai-May Chao  * You may not use this file except in compliance with the License.
7fe54a78eSHai-May Chao  *
8fe54a78eSHai-May Chao  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fe54a78eSHai-May Chao  * or http://www.opensolaris.org/os/licensing.
10fe54a78eSHai-May Chao  * See the License for the specific language governing permissions
11fe54a78eSHai-May Chao  * and limitations under the License.
12fe54a78eSHai-May Chao  *
13fe54a78eSHai-May Chao  * When distributing Covered Code, include this CDDL HEADER in each
14fe54a78eSHai-May Chao  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fe54a78eSHai-May Chao  * If applicable, add the following below this CDDL HEADER, with the
16fe54a78eSHai-May Chao  * fields enclosed by brackets "[]" replaced with your own identifying
17fe54a78eSHai-May Chao  * information: Portions Copyright [yyyy] [name of copyright owner]
18fe54a78eSHai-May Chao  *
19fe54a78eSHai-May Chao  * CDDL HEADER END
20fe54a78eSHai-May Chao  */
21fe54a78eSHai-May Chao /*
22*b5a2d845SHai-May Chao  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23fe54a78eSHai-May Chao  * Use is subject to license terms.
24fe54a78eSHai-May Chao  */
25fe54a78eSHai-May Chao 
26fe54a78eSHai-May Chao #include <sys/types.h>
27fe54a78eSHai-May Chao #include <rng/fips_random.h>
28fe54a78eSHai-May Chao #include <sys/sha1.h>
29fe54a78eSHai-May Chao 
30fe54a78eSHai-May Chao /*
31fe54a78eSHai-May Chao  * Adds val1 and val2 and stores result into sum.  The various input
32fe54a78eSHai-May Chao  * pointers can be exactly aliased.  (They cannot be offset and
33fe54a78eSHai-May Chao  * overlapping, but no one would ever do that.)  Values are big endian
34fe54a78eSHai-May Chao  * by words and native byte order within words.  The return value's
35fe54a78eSHai-May Chao  * 2-bit is 0 if the result is zero, it's 1 bit is carry out.  (This
36fe54a78eSHai-May Chao  * is reused code.  The return code is not used by n2rng.)  Thus,
37fe54a78eSHai-May Chao  * calling with both carryin and complement_val2 ones does a
38fe54a78eSHai-May Chao  * subtraction.  A null sum pointer parameter is allowed.  The
39fe54a78eSHai-May Chao  * subtraction features were required when this code was orginally
40fe54a78eSHai-May Chao  * written so it could do a mod q operation.
41fe54a78eSHai-May Chao  */
42fe54a78eSHai-May Chao static int
fips_add160(uint32_t * sum,uint32_t const * val1,uint32_t const * val2,const unsigned carryin,const int complement_val2)43fe54a78eSHai-May Chao fips_add160(uint32_t *sum, uint32_t const *val1, uint32_t const *val2,
44fe54a78eSHai-May Chao     const unsigned carryin, const int complement_val2)
45fe54a78eSHai-May Chao {
46fe54a78eSHai-May Chao 	int i;
47fe54a78eSHai-May Chao 	uint32_t partialsum;
48fe54a78eSHai-May Chao 	uint32_t carry = (carryin > 0);
49fe54a78eSHai-May Chao 	uint32_t non_zero = 0;
50fe54a78eSHai-May Chao 
51fe54a78eSHai-May Chao 	for (i = 4; i >= 0; --i) {
52fe54a78eSHai-May Chao 		partialsum = val1[i] + (complement_val2 ? ~val2[i] : val2[i]) +
53fe54a78eSHai-May Chao 		    carry;
54fe54a78eSHai-May Chao 		if (carry) {
55fe54a78eSHai-May Chao 			carry = (partialsum <= val1[i]);
56fe54a78eSHai-May Chao 		} else {
57fe54a78eSHai-May Chao 			carry = (partialsum < val1[i]);
58fe54a78eSHai-May Chao 		}
59fe54a78eSHai-May Chao 		if (sum) {
60fe54a78eSHai-May Chao 			sum[i] = partialsum;
61fe54a78eSHai-May Chao 		}
62fe54a78eSHai-May Chao 		non_zero |= partialsum;
63fe54a78eSHai-May Chao 	}
64fe54a78eSHai-May Chao 
65fe54a78eSHai-May Chao 	return (((non_zero != 0) * 2) | carry);
66fe54a78eSHai-May Chao }
67fe54a78eSHai-May Chao 
68*b5a2d845SHai-May Chao #ifdef _LITTLE_ENDIAN
69*b5a2d845SHai-May Chao #define	SWAP16(value)  \
70*b5a2d845SHai-May Chao 	((((value) & 0xff) << 8) | ((value) >> 8))
71*b5a2d845SHai-May Chao 
72*b5a2d845SHai-May Chao #define	SWAP32(value)	\
73*b5a2d845SHai-May Chao 	(((uint32_t)SWAP16((uint16_t)((value) & 0xffff)) << 16) | \
74*b5a2d845SHai-May Chao 	(uint32_t)SWAP16((uint16_t)((value) >> 16)))
75*b5a2d845SHai-May Chao 
76*b5a2d845SHai-May Chao static void
xvalconv(uint32_t * dest,uint32_t * src,int len)77*b5a2d845SHai-May Chao xvalconv(uint32_t *dest, uint32_t *src, int len)
78*b5a2d845SHai-May Chao {
79*b5a2d845SHai-May Chao 	int i;
80*b5a2d845SHai-May Chao 
81*b5a2d845SHai-May Chao 	for (i = 0; i < len; i++) {
82*b5a2d845SHai-May Chao 		dest [i] = SWAP32(src[i]);
83*b5a2d845SHai-May Chao 	}
84*b5a2d845SHai-May Chao }
85*b5a2d845SHai-May Chao #endif /* _LITTLE_ENDIAN */
86*b5a2d845SHai-May Chao 
87fe54a78eSHai-May Chao /*
88fe54a78eSHai-May Chao  * Computes a new random value, which is stored in x_j; updates
89fe54a78eSHai-May Chao  * XKEY.  XSEED_j is additional input.  In principle, we should
90fe54a78eSHai-May Chao  * protect XKEY, perhaps by putting it on a non-pagable page, but we
91fe54a78eSHai-May Chao  * aways clobber XKEY with fresh entropy just before we use it.  And
92fe54a78eSHai-May Chao  * step 3d irreversibly updates it just after we use it.  The only
93fe54a78eSHai-May Chao  * risk is that if an attacker captured the state while the entropy
94fe54a78eSHai-May Chao  * generator was broken, the attacker could predict future values.
95fe54a78eSHai-May Chao  * There are two cases: 1.  The attack gets root access to a live
96fe54a78eSHai-May Chao  * system.  But there is no defense against that.  2.  The attacker
97fe54a78eSHai-May Chao  * gets access to a crash dump.  But by then no values are being
98fe54a78eSHai-May Chao  * generated.
99fe54a78eSHai-May Chao  *
100fe54a78eSHai-May Chao  * Note that XSEEDj is overwritten with sensitive stuff, and must be
101fe54a78eSHai-May Chao  * zeroed by the caller.  We use two separate symbols (XVAL and
102fe54a78eSHai-May Chao  * XSEEDj) to make each step match the notation in FIPS 186-2.
103fe54a78eSHai-May Chao  */
104fe54a78eSHai-May Chao void
fips_random_inner(uint32_t * key,uint32_t * x_j,uint32_t * XSEED_j)105fe54a78eSHai-May Chao fips_random_inner(uint32_t *key, uint32_t *x_j,
106fe54a78eSHai-May Chao     uint32_t *XSEED_j)
107fe54a78eSHai-May Chao {
108fe54a78eSHai-May Chao 	SHA1_CTX	sha1_context;
109fe54a78eSHai-May Chao 	/* Alias to preserve terminology from FIPS 186-2 */
110fe54a78eSHai-May Chao #define	XVAL XSEED_j
111fe54a78eSHai-May Chao 	/*
112fe54a78eSHai-May Chao 	 * K&R section A8.7: If the array has fixed size, the number
113fe54a78eSHai-May Chao 	 * of initializers may not exceed the number of members in the
114fe54a78eSHai-May Chao 	 * array; if there are fewer, the trailing members are
115fe54a78eSHai-May Chao 	 * initialized with 0.
116fe54a78eSHai-May Chao 	 */
117fe54a78eSHai-May Chao 	static const char	zero[SHA1BLOCKBYTES - SHA1BYTES] = {0};
118fe54a78eSHai-May Chao 
119fe54a78eSHai-May Chao 	/*
120fe54a78eSHai-May Chao 	 * Step 3b: XVAL = (XKEY + XSEED_sub_j) mod 2^b.  The mod is
121fe54a78eSHai-May Chao 	 * implicit in the 160 bit representation.  Note that XVAL and
122fe54a78eSHai-May Chao 	 * XSEED_j are actually the same location.
123fe54a78eSHai-May Chao 	 */
124fe54a78eSHai-May Chao 	(void) fips_add160(XVAL, key, XSEED_j, 0, 0);
125fe54a78eSHai-May Chao 	/*
126fe54a78eSHai-May Chao 	 * Step 3c: x_sub_j = G(t, XVAL).
127fe54a78eSHai-May Chao 	 */
128fe54a78eSHai-May Chao 	SHA1Init(&sha1_context);
129fe54a78eSHai-May Chao 	SHA1Update(&sha1_context, (unsigned char *)XVAL, SHA1BYTES);
130fe54a78eSHai-May Chao 	/*
131fe54a78eSHai-May Chao 	 * Filling to 64 bytes is requried by FIPS 186-2 Appendix 3.3.
132fe54a78eSHai-May Chao 	 * It also triggers SHA1Transform (the steps a-e of the spec).
133fe54a78eSHai-May Chao 	 *
134fe54a78eSHai-May Chao 	 * zero is a const char[], but SHA1update does not declare its
135fe54a78eSHai-May Chao 	 * second parameter const, even though it does not modify it,
136fe54a78eSHai-May Chao 	 * so we cast to suppress a compiler warning.
137fe54a78eSHai-May Chao 	 */
138fe54a78eSHai-May Chao 	SHA1Update(&sha1_context, (unsigned char *)zero,
139fe54a78eSHai-May Chao 	    SHA1BLOCKBYTES - SHA1BYTES);
140fe54a78eSHai-May Chao 	/*
141fe54a78eSHai-May Chao 	 * The code below directly accesses the state field of
142fe54a78eSHai-May Chao 	 * sha1_context, which is of type SHA1_CTX, defined in sha1.h.
143fe54a78eSHai-May Chao 	 */
144fe54a78eSHai-May Chao 	/* copy out to x_j */
145*b5a2d845SHai-May Chao 
146*b5a2d845SHai-May Chao #ifdef _BIG_ENDIAN
147*b5a2d845SHai-May Chao 	{
148*b5a2d845SHai-May Chao 		int i;
149*b5a2d845SHai-May Chao 		for (i = 0; i < 5; i++) {
150*b5a2d845SHai-May Chao 			x_j[i] = sha1_context.state[i];
151*b5a2d845SHai-May Chao 		}
152fe54a78eSHai-May Chao 	}
153*b5a2d845SHai-May Chao #else
154*b5a2d845SHai-May Chao 	xvalconv(x_j, sha1_context.state, SHA1BYTES/4);
155*b5a2d845SHai-May Chao #endif
156*b5a2d845SHai-May Chao 
157fe54a78eSHai-May Chao 	/*
158fe54a78eSHai-May Chao 	 * Step 3d: XKEY = (1 + XKEY + x_sub_j) mod 2^b.  b=160.  The
159fe54a78eSHai-May Chao 	 * mod 2^160 is implicit in the 160 bit representation.  The
160fe54a78eSHai-May Chao 	 * one is added via the carry-in flag.
161fe54a78eSHai-May Chao 	 */
162fe54a78eSHai-May Chao 	(void) fips_add160(key, key, x_j, 1, 0);
163fe54a78eSHai-May Chao #undef XVAL
164fe54a78eSHai-May Chao }
165