xref: /onnv-gate/usr/src/common/crypto/rng/fips_random.c (revision 10500:a10fbcfc2f21)
18029SHai-May.Chao@Sun.COM /*
28029SHai-May.Chao@Sun.COM  * CDDL HEADER START
38029SHai-May.Chao@Sun.COM  *
48029SHai-May.Chao@Sun.COM  * The contents of this file are subject to the terms of the
58029SHai-May.Chao@Sun.COM  * Common Development and Distribution License (the "License").
68029SHai-May.Chao@Sun.COM  * You may not use this file except in compliance with the License.
78029SHai-May.Chao@Sun.COM  *
88029SHai-May.Chao@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
98029SHai-May.Chao@Sun.COM  * or http://www.opensolaris.org/os/licensing.
108029SHai-May.Chao@Sun.COM  * See the License for the specific language governing permissions
118029SHai-May.Chao@Sun.COM  * and limitations under the License.
128029SHai-May.Chao@Sun.COM  *
138029SHai-May.Chao@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
148029SHai-May.Chao@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
158029SHai-May.Chao@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
168029SHai-May.Chao@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
178029SHai-May.Chao@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
188029SHai-May.Chao@Sun.COM  *
198029SHai-May.Chao@Sun.COM  * CDDL HEADER END
208029SHai-May.Chao@Sun.COM  */
218029SHai-May.Chao@Sun.COM /*
22*10500SHai-May.Chao@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
238029SHai-May.Chao@Sun.COM  * Use is subject to license terms.
248029SHai-May.Chao@Sun.COM  */
258029SHai-May.Chao@Sun.COM 
268029SHai-May.Chao@Sun.COM #include <sys/types.h>
278029SHai-May.Chao@Sun.COM #include <rng/fips_random.h>
288029SHai-May.Chao@Sun.COM #include <sys/sha1.h>
298029SHai-May.Chao@Sun.COM 
308029SHai-May.Chao@Sun.COM /*
318029SHai-May.Chao@Sun.COM  * Adds val1 and val2 and stores result into sum.  The various input
328029SHai-May.Chao@Sun.COM  * pointers can be exactly aliased.  (They cannot be offset and
338029SHai-May.Chao@Sun.COM  * overlapping, but no one would ever do that.)  Values are big endian
348029SHai-May.Chao@Sun.COM  * by words and native byte order within words.  The return value's
358029SHai-May.Chao@Sun.COM  * 2-bit is 0 if the result is zero, it's 1 bit is carry out.  (This
368029SHai-May.Chao@Sun.COM  * is reused code.  The return code is not used by n2rng.)  Thus,
378029SHai-May.Chao@Sun.COM  * calling with both carryin and complement_val2 ones does a
388029SHai-May.Chao@Sun.COM  * subtraction.  A null sum pointer parameter is allowed.  The
398029SHai-May.Chao@Sun.COM  * subtraction features were required when this code was orginally
408029SHai-May.Chao@Sun.COM  * written so it could do a mod q operation.
418029SHai-May.Chao@Sun.COM  */
428029SHai-May.Chao@Sun.COM static int
fips_add160(uint32_t * sum,uint32_t const * val1,uint32_t const * val2,const unsigned carryin,const int complement_val2)438029SHai-May.Chao@Sun.COM fips_add160(uint32_t *sum, uint32_t const *val1, uint32_t const *val2,
448029SHai-May.Chao@Sun.COM     const unsigned carryin, const int complement_val2)
458029SHai-May.Chao@Sun.COM {
468029SHai-May.Chao@Sun.COM 	int i;
478029SHai-May.Chao@Sun.COM 	uint32_t partialsum;
488029SHai-May.Chao@Sun.COM 	uint32_t carry = (carryin > 0);
498029SHai-May.Chao@Sun.COM 	uint32_t non_zero = 0;
508029SHai-May.Chao@Sun.COM 
518029SHai-May.Chao@Sun.COM 	for (i = 4; i >= 0; --i) {
528029SHai-May.Chao@Sun.COM 		partialsum = val1[i] + (complement_val2 ? ~val2[i] : val2[i]) +
538029SHai-May.Chao@Sun.COM 		    carry;
548029SHai-May.Chao@Sun.COM 		if (carry) {
558029SHai-May.Chao@Sun.COM 			carry = (partialsum <= val1[i]);
568029SHai-May.Chao@Sun.COM 		} else {
578029SHai-May.Chao@Sun.COM 			carry = (partialsum < val1[i]);
588029SHai-May.Chao@Sun.COM 		}
598029SHai-May.Chao@Sun.COM 		if (sum) {
608029SHai-May.Chao@Sun.COM 			sum[i] = partialsum;
618029SHai-May.Chao@Sun.COM 		}
628029SHai-May.Chao@Sun.COM 		non_zero |= partialsum;
638029SHai-May.Chao@Sun.COM 	}
648029SHai-May.Chao@Sun.COM 
658029SHai-May.Chao@Sun.COM 	return (((non_zero != 0) * 2) | carry);
668029SHai-May.Chao@Sun.COM }
678029SHai-May.Chao@Sun.COM 
68*10500SHai-May.Chao@Sun.COM #ifdef _LITTLE_ENDIAN
69*10500SHai-May.Chao@Sun.COM #define	SWAP16(value)  \
70*10500SHai-May.Chao@Sun.COM 	((((value) & 0xff) << 8) | ((value) >> 8))
71*10500SHai-May.Chao@Sun.COM 
72*10500SHai-May.Chao@Sun.COM #define	SWAP32(value)	\
73*10500SHai-May.Chao@Sun.COM 	(((uint32_t)SWAP16((uint16_t)((value) & 0xffff)) << 16) | \
74*10500SHai-May.Chao@Sun.COM 	(uint32_t)SWAP16((uint16_t)((value) >> 16)))
75*10500SHai-May.Chao@Sun.COM 
76*10500SHai-May.Chao@Sun.COM static void
xvalconv(uint32_t * dest,uint32_t * src,int len)77*10500SHai-May.Chao@Sun.COM xvalconv(uint32_t *dest, uint32_t *src, int len)
78*10500SHai-May.Chao@Sun.COM {
79*10500SHai-May.Chao@Sun.COM 	int i;
80*10500SHai-May.Chao@Sun.COM 
81*10500SHai-May.Chao@Sun.COM 	for (i = 0; i < len; i++) {
82*10500SHai-May.Chao@Sun.COM 		dest [i] = SWAP32(src[i]);
83*10500SHai-May.Chao@Sun.COM 	}
84*10500SHai-May.Chao@Sun.COM }
85*10500SHai-May.Chao@Sun.COM #endif /* _LITTLE_ENDIAN */
86*10500SHai-May.Chao@Sun.COM 
878029SHai-May.Chao@Sun.COM /*
888029SHai-May.Chao@Sun.COM  * Computes a new random value, which is stored in x_j; updates
898029SHai-May.Chao@Sun.COM  * XKEY.  XSEED_j is additional input.  In principle, we should
908029SHai-May.Chao@Sun.COM  * protect XKEY, perhaps by putting it on a non-pagable page, but we
918029SHai-May.Chao@Sun.COM  * aways clobber XKEY with fresh entropy just before we use it.  And
928029SHai-May.Chao@Sun.COM  * step 3d irreversibly updates it just after we use it.  The only
938029SHai-May.Chao@Sun.COM  * risk is that if an attacker captured the state while the entropy
948029SHai-May.Chao@Sun.COM  * generator was broken, the attacker could predict future values.
958029SHai-May.Chao@Sun.COM  * There are two cases: 1.  The attack gets root access to a live
968029SHai-May.Chao@Sun.COM  * system.  But there is no defense against that.  2.  The attacker
978029SHai-May.Chao@Sun.COM  * gets access to a crash dump.  But by then no values are being
988029SHai-May.Chao@Sun.COM  * generated.
998029SHai-May.Chao@Sun.COM  *
1008029SHai-May.Chao@Sun.COM  * Note that XSEEDj is overwritten with sensitive stuff, and must be
1018029SHai-May.Chao@Sun.COM  * zeroed by the caller.  We use two separate symbols (XVAL and
1028029SHai-May.Chao@Sun.COM  * XSEEDj) to make each step match the notation in FIPS 186-2.
1038029SHai-May.Chao@Sun.COM  */
1048029SHai-May.Chao@Sun.COM void
fips_random_inner(uint32_t * key,uint32_t * x_j,uint32_t * XSEED_j)1058029SHai-May.Chao@Sun.COM fips_random_inner(uint32_t *key, uint32_t *x_j,
1068029SHai-May.Chao@Sun.COM     uint32_t *XSEED_j)
1078029SHai-May.Chao@Sun.COM {
1088029SHai-May.Chao@Sun.COM 	SHA1_CTX	sha1_context;
1098029SHai-May.Chao@Sun.COM 	/* Alias to preserve terminology from FIPS 186-2 */
1108029SHai-May.Chao@Sun.COM #define	XVAL XSEED_j
1118029SHai-May.Chao@Sun.COM 	/*
1128029SHai-May.Chao@Sun.COM 	 * K&R section A8.7: If the array has fixed size, the number
1138029SHai-May.Chao@Sun.COM 	 * of initializers may not exceed the number of members in the
1148029SHai-May.Chao@Sun.COM 	 * array; if there are fewer, the trailing members are
1158029SHai-May.Chao@Sun.COM 	 * initialized with 0.
1168029SHai-May.Chao@Sun.COM 	 */
1178029SHai-May.Chao@Sun.COM 	static const char	zero[SHA1BLOCKBYTES - SHA1BYTES] = {0};
1188029SHai-May.Chao@Sun.COM 
1198029SHai-May.Chao@Sun.COM 	/*
1208029SHai-May.Chao@Sun.COM 	 * Step 3b: XVAL = (XKEY + XSEED_sub_j) mod 2^b.  The mod is
1218029SHai-May.Chao@Sun.COM 	 * implicit in the 160 bit representation.  Note that XVAL and
1228029SHai-May.Chao@Sun.COM 	 * XSEED_j are actually the same location.
1238029SHai-May.Chao@Sun.COM 	 */
1248029SHai-May.Chao@Sun.COM 	(void) fips_add160(XVAL, key, XSEED_j, 0, 0);
1258029SHai-May.Chao@Sun.COM 	/*
1268029SHai-May.Chao@Sun.COM 	 * Step 3c: x_sub_j = G(t, XVAL).
1278029SHai-May.Chao@Sun.COM 	 */
1288029SHai-May.Chao@Sun.COM 	SHA1Init(&sha1_context);
1298029SHai-May.Chao@Sun.COM 	SHA1Update(&sha1_context, (unsigned char *)XVAL, SHA1BYTES);
1308029SHai-May.Chao@Sun.COM 	/*
1318029SHai-May.Chao@Sun.COM 	 * Filling to 64 bytes is requried by FIPS 186-2 Appendix 3.3.
1328029SHai-May.Chao@Sun.COM 	 * It also triggers SHA1Transform (the steps a-e of the spec).
1338029SHai-May.Chao@Sun.COM 	 *
1348029SHai-May.Chao@Sun.COM 	 * zero is a const char[], but SHA1update does not declare its
1358029SHai-May.Chao@Sun.COM 	 * second parameter const, even though it does not modify it,
1368029SHai-May.Chao@Sun.COM 	 * so we cast to suppress a compiler warning.
1378029SHai-May.Chao@Sun.COM 	 */
1388029SHai-May.Chao@Sun.COM 	SHA1Update(&sha1_context, (unsigned char *)zero,
1398029SHai-May.Chao@Sun.COM 	    SHA1BLOCKBYTES - SHA1BYTES);
1408029SHai-May.Chao@Sun.COM 	/*
1418029SHai-May.Chao@Sun.COM 	 * The code below directly accesses the state field of
1428029SHai-May.Chao@Sun.COM 	 * sha1_context, which is of type SHA1_CTX, defined in sha1.h.
1438029SHai-May.Chao@Sun.COM 	 */
1448029SHai-May.Chao@Sun.COM 	/* copy out to x_j */
145*10500SHai-May.Chao@Sun.COM 
146*10500SHai-May.Chao@Sun.COM #ifdef _BIG_ENDIAN
147*10500SHai-May.Chao@Sun.COM 	{
148*10500SHai-May.Chao@Sun.COM 		int i;
149*10500SHai-May.Chao@Sun.COM 		for (i = 0; i < 5; i++) {
150*10500SHai-May.Chao@Sun.COM 			x_j[i] = sha1_context.state[i];
151*10500SHai-May.Chao@Sun.COM 		}
1528029SHai-May.Chao@Sun.COM 	}
153*10500SHai-May.Chao@Sun.COM #else
154*10500SHai-May.Chao@Sun.COM 	xvalconv(x_j, sha1_context.state, SHA1BYTES/4);
155*10500SHai-May.Chao@Sun.COM #endif
156*10500SHai-May.Chao@Sun.COM 
1578029SHai-May.Chao@Sun.COM 	/*
1588029SHai-May.Chao@Sun.COM 	 * Step 3d: XKEY = (1 + XKEY + x_sub_j) mod 2^b.  b=160.  The
1598029SHai-May.Chao@Sun.COM 	 * mod 2^160 is implicit in the 160 bit representation.  The
1608029SHai-May.Chao@Sun.COM 	 * one is added via the carry-in flag.
1618029SHai-May.Chao@Sun.COM 	 */
1628029SHai-May.Chao@Sun.COM 	(void) fips_add160(key, key, x_j, 1, 0);
1638029SHai-May.Chao@Sun.COM #undef XVAL
1648029SHai-May.Chao@Sun.COM }
165