/** \ingroup PRNG_fips186_m DSA_m * \file fips186.c * * NIST FIPS-186 pseudo-random generator, code. */ /* * Copyright (c) 1998, 1999, 2000 Virtual Unlimited B.V. * * Author: Bob Deblier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "system.h" #include "beecrypt.h" #include "fips186.h" #include "mp32opt.h" #include "mp32.h" #include "debug.h" /** */ /*@observer@*/ /*@unchecked@*/ static uint32 fips186hinit[5] = { 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0, 0x67452301 }; /*@-sizeoftype@*/ const randomGenerator fips186prng = { "FIPS 186", sizeof(fips186Param), (const randomGeneratorSetup) fips186Setup, (const randomGeneratorSeed) fips186Seed, (const randomGeneratorNext) fips186Next, (const randomGeneratorCleanup) fips186Cleanup }; /*@=sizeoftype@*/ /** */ /*@-boundswrite@*/ static int fips186init(register sha1Param* p) /*@modifies p @*/ { mp32copy(5, p->h, fips186hinit); return 0; } /*@=boundswrite@*/ int fips186Setup(fips186Param* fp) { if (fp) { #ifdef _REENTRANT # if WIN32 if (!(fp->lock = CreateMutex(NULL, FALSE, NULL))) return -1; # else # if HAVE_THREAD_H && HAVE_SYNCH_H if (mutex_init(&fp->lock, USYNC_THREAD, (void *) 0)) return -1; # elif HAVE_PTHREAD_H /*@-nullpass@*/ /*@-moduncon@*/ if (pthread_mutex_init(&fp->lock, (pthread_mutexattr_t *) 0)) return -1; /*@=moduncon@*/ /*@=nullpass@*/ # endif # endif #endif fp->digestsize = 0; return entropyGatherNext(fp->state, FIPS186_STATE_SIZE); } return -1; } int fips186Seed(fips186Param* fp, const uint32* data, int size) { if (fp) { #ifdef _REENTRANT # if WIN32 if (WaitForSingleObject(fp->lock, INFINITE) != WAIT_OBJECT_0) return -1; # else # if HAVE_THREAD_H && HAVE_SYNCH_H if (mutex_lock(&fp->lock)) return -1; # elif HAVE_PTHREAD_H /*@-moduncon@*/ if (pthread_mutex_lock(&fp->lock)) return -1; /*@=moduncon@*/ # endif # endif #endif if (data) (void) mp32addx(FIPS186_STATE_SIZE, fp->state, size, data); #ifdef _REENTRANT # if WIN32 if (!ReleaseMutex(fp->lock)) return -1; # else # if HAVE_THREAD_H && HAVE_SYNCH_H if (mutex_unlock(&fp->lock)) return -1; # elif HAVE_PTHREAD_H /*@-moduncon@*/ if (pthread_mutex_unlock(&fp->lock)) return -1; /*@=moduncon@*/ # endif # endif #endif return 0; } return -1; } /*@-boundswrite@*/ int fips186Next(fips186Param* fp, uint32* data, int size) { if (fp) { #ifdef _REENTRANT # if WIN32 if (WaitForSingleObject(fp->lock, INFINITE) != WAIT_OBJECT_0) return -1; # else # if HAVE_THREAD_H && HAVE_SYNCH_H if (mutex_lock(&fp->lock)) return -1; # elif HAVE_PTHREAD_H /*@-moduncon@*/ if (pthread_mutex_lock(&fp->lock)) return -1; /*@=moduncon@*/ # endif # endif #endif while (size > 0) { register uint32 copy; if (fp->digestsize == 0) { (void) fips186init(&fp->param); /* copy the 512 bits of state data into the sha1Param */ mp32copy(FIPS186_STATE_SIZE, fp->param.data, fp->state); /* process the data */ sha1Process(&fp->param); /* set state to state + digest + 1 mod 2^512 */ (void) mp32addx(FIPS186_STATE_SIZE, fp->state, 5, fp->param.h); (void) mp32addw(FIPS186_STATE_SIZE, fp->state, 1); /* we now have 5 words of pseudo-random data */ fp->digestsize = 5; } copy = (size > fp->digestsize) ? fp->digestsize : size; mp32copy(copy, data, fp->param.h + 5 - fp->digestsize); fp->digestsize -= copy; size -= copy; data += copy; } #ifdef _REENTRANT # if WIN32 if (!ReleaseMutex(fp->lock)) return -1; # else # if HAVE_THREAD_H && HAVE_SYNCH_H if (mutex_unlock(&fp->lock)) return -1; # elif HAVE_PTHREAD_H /*@-moduncon@*/ if (pthread_mutex_unlock(&fp->lock)) return -1; /*@=moduncon@*/ # endif # endif #endif return 0; } return -1; } /*@=boundswrite@*/ int fips186Cleanup(fips186Param* fp) { if (fp) { #ifdef _REENTRANT # if WIN32 if (!CloseHandle(fp->lock)) return -1; # else # if HAVE_THREAD_H && HAVE_SYNCH_H if (mutex_destroy(&fp->lock)) return -1; # elif HAVE_PTHREAD_H /*@-moduncon@*/ if (pthread_mutex_destroy(&fp->lock)) return -1; /*@=moduncon@*/ # endif # endif #endif return 0; } return -1; }