00001
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
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
00051 const randomGenerator mtprng = { "Mersenne Twister", sizeof(mtprngParam), (randomGeneratorSetup) mtprngSetup, (randomGeneratorSeed) mtprngSeed, (randomGeneratorNext) mtprngNext, (randomGeneratorCleanup) mtprngCleanup };
00052
00053
00056
00057 static void mtprngReload(mtprngParam* mp)
00058
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
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
00091
00092 if (pthread_mutex_init(&mp->lock, (pthread_mutexattr_t *) 0))
00093 return -1;
00094
00095
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
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
00125 if (pthread_mutex_lock(&mp->lock))
00126 return -1;
00127
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
00148 if (pthread_mutex_unlock(&mp->lock))
00149 return -1;
00150
00151 # endif
00152 # endif
00153 #endif
00154 return 0;
00155 }
00156 return -1;
00157 }
00158
00159
00160
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
00177 if (pthread_mutex_lock(&mp->lock))
00178 return -1;
00179
00180 # endif
00181 # endif
00182 #endif
00183
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
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
00208 if (pthread_mutex_unlock(&mp->lock))
00209 return -1;
00210
00211 # endif
00212 # endif
00213 #endif
00214 return 0;
00215 }
00216 return -1;
00217 }
00218
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
00234 if (pthread_mutex_destroy(&mp->lock))
00235 return -1;
00236
00237 # endif
00238 # endif
00239 #endif
00240 return 0;
00241 }
00242 return -1;
00243 }