Main Page Modules Data Structures File List Data Fields Globals Related Pages

# beecrypt/mtprng.c

Go to the documentation of this file.

    00001
    00018 /* Copyright (c) 1998, 1999, 2000, 2001 Virtual Unlimited B.V.
    00019  *
    00020  * Author: Bob Deblier <bob@virtualunlimited.com>
    00021  *
    00022  * This library is free software; you can redistribute it and/or
    00023  * modify it under the terms of the GNU Lesser General Public
    00024  * License as published by the Free Software Foundation; either
    00025  * version 2.1 of the License, or (at your option) any later version.
    00026  *
    00027  * This library is distributed in the hope that it will be useful,
    00028  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    00029  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00030  * Lesser General Public License for more details.
    00031  *
    00032  * You should have received a copy of the GNU Lesser General Public
    00033  * License along with this library; if not, write to the Free Software
    00034  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    00035  *
    00036  */
    00037
    00038 #include "system.h"
    00039 #include "beecrypt.h"
    00040 #include "mtprng.h"
    00041 #include "mp32opt.h"
    00042 #include "mp32.h"
    00043 #include "debug.h"
    00044
    00045 #define hiBit(a)                ((a) & 0x80000000)
    00046 #define loBit(a)                ((a) & 0x1)
    00047 #define loBits(a)               ((a) & 0x7FFFFFFF)
    00048 #define mixBits(a, b)   (hiBit(a) | loBits(b))
    00049
    00050 /*@-sizeoftype@*/
    00051 const randomGenerator mtprng = { "Mersenne Twister", sizeof(mtprngParam), (randomGeneratorSetup) mtprngSetup, (randomGeneratorSeed) mtprngSeed, (randomGeneratorNext) mtprngNext, (randomGeneratorCleanup) mtprngCleanup };
    00052 /*@=sizeoftype@*/
    00053
    00056 /*@-boundsread@*/
    00057 static void mtprngReload(mtprngParam* mp)
    00058         /*@modifies mp @*/
    00059 {
    00060     register uint32* p0 = mp->state;
    00061     register uint32* p2=p0+2, *pM = p0+M, s0, s1;
    00062     register int j;
    00063
    00064     for (s0=mp->state[0], s1=mp->state[1], j=N-M+1; --j; s0=s1, s1=*(p2++))
    00065         *(p0++) = *(pM++) ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0);
    00066
    00067     for (pM=mp->state, j=M; --j; s0=s1, s1=*(p2++))
    00068         *(p0++) = *(pM++) ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0);
    00069
    00070     s1 = mp->state[0], *p0 = *pM ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0);
    00071
    00072     mp->left = N;
    00073     mp->nextw = mp->state;
    00074 }
    00075 /*@=boundsread@*/
    00076
    00077 int mtprngSetup(mtprngParam* mp)
    00078 {
    00079         if (mp)
    00080         {
    00081                 #ifdef _REENTRANT
    00082                 # if WIN32
    00083                 if (!(mp->lock = CreateMutex(NULL, FALSE, NULL)))
    00084                         return -1;
    00085                 # else
    00086                 #  if HAVE_THREAD_H && HAVE_SYNCH_H
    00087                 if (mutex_init(&mp->lock, USYNC_THREAD, (void *) 0))
    00088                         return -1;
    00089                 #  elif HAVE_PTHREAD_H
    00090                 /*@-nullpass@*/
    00091                 /*@-moduncon@*/
    00092                 if (pthread_mutex_init(&mp->lock, (pthread_mutexattr_t *) 0))
    00093                         return -1;
    00094                 /*@=moduncon@*/
    00095                 /*@=nullpass@*/
    00096                 #  endif
    00097                 # endif
    00098                 #endif
    00099
    00100                 mp->left = 0;
    00101
    00102                 return entropyGatherNext(mp->state, N+1);
    00103         }
    00104         return -1;
    00105 }
    00106
    00107 /*@-boundswrite@*/
    00108 int mtprngSeed(mtprngParam* mp, const uint32* data, int size)
    00109 {
    00110         if (mp)
    00111         {
    00112                 int     needed = N+1;
    00113                 uint32* dest = mp->state;
    00114
    00115                 #ifdef _REENTRANT
    00116                 # if WIN32
    00117                 if (WaitForSingleObject(mp->lock, INFINITE) != WAIT_OBJECT_0)
    00118                         return -1;
    00119                 # else
    00120                 #  if HAVE_THREAD_H && HAVE_SYNCH_H
    00121                 if (mutex_lock(&mp->lock))
    00122                         return -1;
    00123                 #  elif HAVE_PTHREAD_H
    00124                 /*@-moduncon@*/
    00125                 if (pthread_mutex_lock(&mp->lock))
    00126                         return -1;
    00127                 /*@=moduncon@*/
    00128                 #  endif
    00129                 # endif
    00130                 #endif
    00131                 while (size < needed)
    00132                 {
    00133                         mp32copy(size, dest, data);
    00134                         dest += size;
    00135                         needed -= size;
    00136                 }
    00137                 mp32copy(needed, dest, data);
    00138                 #ifdef _REENTRANT
    00139                 # if WIN32
    00140                 if (!ReleaseMutex(mp->lock))
    00141                         return -1;
    00142                 # else
    00143                 #  if HAVE_THREAD_H && HAVE_SYNCH_H
    00144                 if (mutex_unlock(&mp->lock))
    00145                         return -1;
    00146                 #  elif HAVE_PTHREAD_H
    00147                 /*@-moduncon@*/
    00148                 if (pthread_mutex_unlock(&mp->lock))
    00149                         return -1;
    00150                 /*@=moduncon@*/
    00151                 #  endif
    00152                 # endif
    00153                 #endif
    00154                 return 0;
    00155         }
    00156         return -1;
    00157 }
    00158 /*@=boundswrite@*/
    00159
    00160 /*@-boundswrite@*/
    00161 int mtprngNext(mtprngParam* mp, uint32* data, int size)
    00162 {
    00163         if (mp)
    00164         {
    00165                 register uint32 tmp;
    00166
    00167                 #ifdef _REENTRANT
    00168                 # if WIN32
    00169                 if (WaitForSingleObject(mp->lock, INFINITE) != WAIT_OBJECT_0)
    00170                         return -1;
    00171                 # else
    00172                 #  if HAVE_THREAD_H && HAVE_SYNCH_H
    00173                 if (mutex_lock(&mp->lock))
    00174                         return -1;
    00175                 #  elif HAVE_PTHREAD_H
    00176                 /*@-moduncon@*/
    00177                 if (pthread_mutex_lock(&mp->lock))
    00178                         return -1;
    00179                 /*@=moduncon@*/
    00180                 #  endif
    00181                 # endif
    00182                 #endif
    00183                 /*@-branchstate@*/
    00184                 while (size--)
    00185                 {
    00186                         if (mp->left == 0)
    00187                                 mtprngReload(mp);
    00188
    00189                         tmp = *(mp->nextw++);
    00190                         tmp ^= (tmp >> 11);
    00191                         tmp ^= (tmp << 7) & 0x9D2C5680;
    00192                         tmp ^= (tmp << 15) & 0xEFC60000;
    00193                         tmp ^= (tmp >> 18);
    00194                         mp->left--;
    00195                         *(data++) = tmp;
    00196                 }
    00197                 /*@=branchstate@*/
    00198                 #ifdef _REENTRANT
    00199                 # if WIN32
    00200                 if (!ReleaseMutex(mp->lock))
    00201                         return -1;
    00202                 # else
    00203                 #  if HAVE_THREAD_H && HAVE_SYNCH_H
    00204                 if (mutex_unlock(&mp->lock))
    00205                         return -1;
    00206                 #  elif HAVE_PTHREAD_H
    00207                 /*@-moduncon@*/
    00208                 if (pthread_mutex_unlock(&mp->lock))
    00209                         return -1;
    00210                 /*@=moduncon@*/
    00211                 #  endif
    00212                 # endif
    00213                 #endif
    00214                 return 0;
    00215         }
    00216         return -1;
    00217 }
    00218 /*@=boundswrite@*/
    00219
    00220 int mtprngCleanup(mtprngParam* mp)
    00221 {
    00222         if (mp)
    00223         {
    00224                 #ifdef _REENTRANT
    00225                 # if WIN32
    00226                 if (!CloseHandle(mp->lock))
    00227                         return -1;
    00228                 # else
    00229                 #  if HAVE_THREAD_H && HAVE_SYNCH_H
    00230                 if (mutex_destroy(&mp->lock))
    00231                         return -1;
    00232                 #  elif HAVE_PTHREAD_H
    00233                 /*@-moduncon@*/
    00234                 if (pthread_mutex_destroy(&mp->lock))
    00235                         return -1;
    00236                 /*@=moduncon@*/
    00237                 #  endif
    00238                 # endif
    00239                 #endif
    00240                 return 0;
    00241         }
    00242         return -1;
    00243 }