fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao/*
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * CDDL HEADER START
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao *
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * The contents of this file are subject to the terms of the
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * Common Development and Distribution License (the "License").
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * You may not use this file except in compliance with the License.
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao *
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * or http://www.opensolaris.org/os/licensing.
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * See the License for the specific language governing permissions
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * and limitations under the License.
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao *
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * When distributing Covered Code, include this CDDL HEADER in each
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * If applicable, add the following below this CDDL HEADER, with the
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * fields enclosed by brackets "[]" replaced with your own identifying
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * information: Portions Copyright [yyyy] [name of copyright owner]
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao *
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * CDDL HEADER END
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao */
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao/*
b5a2d8455dfa3190fc977c4bec53e91c99012767Hai-May Chao * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * Use is subject to license terms.
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao */
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao#include <sys/types.h>
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao#include <rng/fips_random.h>
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao#include <sys/sha1.h>
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao/*
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * Adds val1 and val2 and stores result into sum. The various input
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * pointers can be exactly aliased. (They cannot be offset and
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * overlapping, but no one would ever do that.) Values are big endian
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * by words and native byte order within words. The return value's
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * 2-bit is 0 if the result is zero, it's 1 bit is carry out. (This
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * is reused code. The return code is not used by n2rng.) Thus,
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * calling with both carryin and complement_val2 ones does a
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * subtraction. A null sum pointer parameter is allowed. The
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * subtraction features were required when this code was orginally
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * written so it could do a mod q operation.
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao */
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chaostatic int
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chaofips_add160(uint32_t *sum, uint32_t const *val1, uint32_t const *val2,
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao const unsigned carryin, const int complement_val2)
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao{
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao int i;
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao uint32_t partialsum;
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao uint32_t carry = (carryin > 0);
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao uint32_t non_zero = 0;
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao for (i = 4; i >= 0; --i) {
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao partialsum = val1[i] + (complement_val2 ? ~val2[i] : val2[i]) +
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao carry;
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao if (carry) {
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao carry = (partialsum <= val1[i]);
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao } else {
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao carry = (partialsum < val1[i]);
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao }
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao if (sum) {
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao sum[i] = partialsum;
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao }
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao non_zero |= partialsum;
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao }
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao return (((non_zero != 0) * 2) | carry);
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao}
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao
b5a2d8455dfa3190fc977c4bec53e91c99012767Hai-May Chao#ifdef _LITTLE_ENDIAN
b5a2d8455dfa3190fc977c4bec53e91c99012767Hai-May Chao#define SWAP16(value) \
b5a2d8455dfa3190fc977c4bec53e91c99012767Hai-May Chao ((((value) & 0xff) << 8) | ((value) >> 8))
b5a2d8455dfa3190fc977c4bec53e91c99012767Hai-May Chao
b5a2d8455dfa3190fc977c4bec53e91c99012767Hai-May Chao#define SWAP32(value) \
b5a2d8455dfa3190fc977c4bec53e91c99012767Hai-May Chao (((uint32_t)SWAP16((uint16_t)((value) & 0xffff)) << 16) | \
b5a2d8455dfa3190fc977c4bec53e91c99012767Hai-May Chao (uint32_t)SWAP16((uint16_t)((value) >> 16)))
b5a2d8455dfa3190fc977c4bec53e91c99012767Hai-May Chao
b5a2d8455dfa3190fc977c4bec53e91c99012767Hai-May Chaostatic void
b5a2d8455dfa3190fc977c4bec53e91c99012767Hai-May Chaoxvalconv(uint32_t *dest, uint32_t *src, int len)
b5a2d8455dfa3190fc977c4bec53e91c99012767Hai-May Chao{
b5a2d8455dfa3190fc977c4bec53e91c99012767Hai-May Chao int i;
b5a2d8455dfa3190fc977c4bec53e91c99012767Hai-May Chao
b5a2d8455dfa3190fc977c4bec53e91c99012767Hai-May Chao for (i = 0; i < len; i++) {
b5a2d8455dfa3190fc977c4bec53e91c99012767Hai-May Chao dest [i] = SWAP32(src[i]);
b5a2d8455dfa3190fc977c4bec53e91c99012767Hai-May Chao }
b5a2d8455dfa3190fc977c4bec53e91c99012767Hai-May Chao}
b5a2d8455dfa3190fc977c4bec53e91c99012767Hai-May Chao#endif /* _LITTLE_ENDIAN */
b5a2d8455dfa3190fc977c4bec53e91c99012767Hai-May Chao
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao/*
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * Computes a new random value, which is stored in x_j; updates
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * XKEY. XSEED_j is additional input. In principle, we should
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * protect XKEY, perhaps by putting it on a non-pagable page, but we
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * aways clobber XKEY with fresh entropy just before we use it. And
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * step 3d irreversibly updates it just after we use it. The only
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * risk is that if an attacker captured the state while the entropy
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * generator was broken, the attacker could predict future values.
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * There are two cases: 1. The attack gets root access to a live
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * system. But there is no defense against that. 2. The attacker
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * gets access to a crash dump. But by then no values are being
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * generated.
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao *
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * Note that XSEEDj is overwritten with sensitive stuff, and must be
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * zeroed by the caller. We use two separate symbols (XVAL and
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * XSEEDj) to make each step match the notation in FIPS 186-2.
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao */
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chaovoid
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chaofips_random_inner(uint32_t *key, uint32_t *x_j,
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao uint32_t *XSEED_j)
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao{
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao SHA1_CTX sha1_context;
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao /* Alias to preserve terminology from FIPS 186-2 */
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao#define XVAL XSEED_j
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao /*
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * K&R section A8.7: If the array has fixed size, the number
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * of initializers may not exceed the number of members in the
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * array; if there are fewer, the trailing members are
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * initialized with 0.
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao */
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao static const char zero[SHA1BLOCKBYTES - SHA1BYTES] = {0};
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao /*
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * Step 3b: XVAL = (XKEY + XSEED_sub_j) mod 2^b. The mod is
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * implicit in the 160 bit representation. Note that XVAL and
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * XSEED_j are actually the same location.
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao */
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao (void) fips_add160(XVAL, key, XSEED_j, 0, 0);
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao /*
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * Step 3c: x_sub_j = G(t, XVAL).
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao */
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao SHA1Init(&sha1_context);
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao SHA1Update(&sha1_context, (unsigned char *)XVAL, SHA1BYTES);
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao /*
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * Filling to 64 bytes is requried by FIPS 186-2 Appendix 3.3.
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * It also triggers SHA1Transform (the steps a-e of the spec).
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao *
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * zero is a const char[], but SHA1update does not declare its
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * second parameter const, even though it does not modify it,
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * so we cast to suppress a compiler warning.
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao */
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao SHA1Update(&sha1_context, (unsigned char *)zero,
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao SHA1BLOCKBYTES - SHA1BYTES);
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao /*
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * The code below directly accesses the state field of
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * sha1_context, which is of type SHA1_CTX, defined in sha1.h.
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao */
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao /* copy out to x_j */
b5a2d8455dfa3190fc977c4bec53e91c99012767Hai-May Chao
b5a2d8455dfa3190fc977c4bec53e91c99012767Hai-May Chao#ifdef _BIG_ENDIAN
b5a2d8455dfa3190fc977c4bec53e91c99012767Hai-May Chao {
b5a2d8455dfa3190fc977c4bec53e91c99012767Hai-May Chao int i;
b5a2d8455dfa3190fc977c4bec53e91c99012767Hai-May Chao for (i = 0; i < 5; i++) {
b5a2d8455dfa3190fc977c4bec53e91c99012767Hai-May Chao x_j[i] = sha1_context.state[i];
b5a2d8455dfa3190fc977c4bec53e91c99012767Hai-May Chao }
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao }
b5a2d8455dfa3190fc977c4bec53e91c99012767Hai-May Chao#else
b5a2d8455dfa3190fc977c4bec53e91c99012767Hai-May Chao xvalconv(x_j, sha1_context.state, SHA1BYTES/4);
b5a2d8455dfa3190fc977c4bec53e91c99012767Hai-May Chao#endif
b5a2d8455dfa3190fc977c4bec53e91c99012767Hai-May Chao
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao /*
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * Step 3d: XKEY = (1 + XKEY + x_sub_j) mod 2^b. b=160. The
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * mod 2^160 is implicit in the 160 bit representation. The
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao * one is added via the carry-in flag.
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao */
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao (void) fips_add160(key, key, x_j, 1, 0);
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao#undef XVAL
fe54a78e1aacf39261ad56e9903bce02e3fb6d21Hai-May Chao}