-rw-r--r-- | pwmanager/pwmanager/randomizer.cpp | 207 | ||||
-rw-r--r-- | pwmanager/pwmanager/randomizer.h | 39 |
2 files changed, 181 insertions, 65 deletions
diff --git a/pwmanager/pwmanager/randomizer.cpp b/pwmanager/pwmanager/randomizer.cpp index e623f51..1269c53 100644 --- a/pwmanager/pwmanager/randomizer.cpp +++ b/pwmanager/pwmanager/randomizer.cpp | |||
@@ -11,7 +11,7 @@ | |||
11 | 11 | ||
12 | /*************************************************************************** | 12 | /*************************************************************************** |
13 | * copyright (C) 2004 by Ulf Schenk | 13 | * copyright (C) 2004 by Ulf Schenk |
14 | * This file is originaly based on version 1.0.1 of pwmanager | 14 | * This file is originaly based on version 2.0 of pwmanager |
15 | * and was modified to run on embedded devices that run microkde | 15 | * and was modified to run on embedded devices that run microkde |
16 | * | 16 | * |
17 | * $Id$ | 17 | * $Id$ |
@@ -20,105 +20,202 @@ | |||
20 | #include "randomizer.h" | 20 | #include "randomizer.h" |
21 | #include "pwmexception.h" | 21 | #include "pwmexception.h" |
22 | 22 | ||
23 | #include <qfile.h> | ||
24 | |||
25 | #include <kapplication.h> | ||
26 | |||
23 | #include <stdlib.h> | 27 | #include <stdlib.h> |
24 | #include <time.h> | 28 | #include <time.h> |
25 | 29 | ||
26 | 30 | ||
31 | #ifdef PWM_EMBEDDED | ||
32 | |||
33 | #ifndef Q_LONG | ||
34 | #define Q_LONG long | ||
35 | #endif | ||
36 | |||
37 | #endif //PWM_EMBEDDED | ||
38 | |||
39 | |||
27 | Randomizer * Randomizer::rndObj (0); | 40 | Randomizer * Randomizer::rndObj (0); |
28 | 41 | ||
29 | Randomizer::Randomizer() | 42 | Randomizer::Randomizer() |
30 | { | 43 | { |
31 | // probe for random devices | 44 | rndDev = new QFile; |
32 | rndDev = fopen("/dev/urandom", "r"); | 45 | seed = time(0); |
33 | if (rndDev) | 46 | |
47 | #if 1 // set to 0 to test rand_r() fallback | ||
48 | |||
49 | // probe for /dev/urandom | ||
50 | rndDev->setName("/dev/urandom"); | ||
51 | if (rndDev->exists() && | ||
52 | rndDev->open(IO_ReadOnly)) { | ||
53 | printDebug("Randomizer: using /dev/urandom"); | ||
34 | return; | 54 | return; |
35 | rndDev = fopen("/dev/random", "r"); | 55 | } |
36 | if (rndDev) | 56 | |
57 | // probe for /dev/random | ||
58 | rndDev->setName("/dev/random"); | ||
59 | if (rndDev->exists() && | ||
60 | rndDev->open(IO_ReadOnly)) { | ||
61 | printDebug("Randomizer: using /dev/random"); | ||
37 | return; | 62 | return; |
38 | // fall back to rand_r() | 63 | } |
39 | seed = time(0); | 64 | |
65 | // probe for EGD | ||
66 | char *fn = getenv("RANDFILE"); | ||
67 | if (fn) { | ||
68 | rndDev->setName(fn); | ||
69 | if (rndDev->exists() && | ||
70 | rndDev->open(IO_ReadOnly)) { | ||
71 | printDebug(string("Randomizer: using $RANDFILE \"") | ||
72 | + fn | ||
73 | + "\" (aka EGD)"); | ||
74 | return; | ||
75 | } | ||
76 | } | ||
77 | #endif | ||
78 | |||
79 | /* no secure randomizer found. | ||
80 | * Fall back to stdlib randomizer. | ||
81 | */ | ||
82 | delete_and_null(rndDev); | ||
83 | printWarn("neither /dev/*random nor EGD found! " | ||
84 | "Falling back to insecure rand_r()!"); | ||
40 | } | 85 | } |
41 | 86 | ||
42 | Randomizer::~Randomizer() | 87 | Randomizer::~Randomizer() |
43 | { | 88 | { |
89 | #ifndef PWM_EMBEDDED | ||
90 | while (mutex.locked()) { | ||
91 | /* wait for the mutex to unlock. | ||
92 | * Don't block the GUI here, so processEvents() | ||
93 | */ | ||
94 | kapp->processEvents(); | ||
95 | } | ||
96 | #endif | ||
44 | if (rndDev) { | 97 | if (rndDev) { |
45 | if (fclose(rndDev)) { | 98 | rndDev->close(); |
46 | printWarn("failed closing the random-device!"); | 99 | delete rndDev; |
47 | } | ||
48 | } | 100 | } |
49 | } | 101 | } |
50 | 102 | ||
51 | char Randomizer::genRndChar() | 103 | char Randomizer::genRndChar() |
52 | { | 104 | { |
105 | char ret; | ||
106 | #ifndef PWM_EMBEDDED | ||
107 | mutex.lock(); | ||
108 | #endif | ||
53 | if (rndDev) { | 109 | if (rndDev) { |
54 | /* we have a rand-device-node */ | 110 | /* we have a file which provides random data. |
55 | return (getc(rndDev)); | 111 | * Simply read it. |
56 | } else { | ||
57 | /* we don't have a random-device-node. | ||
58 | * so fall back to rand_r() | ||
59 | */ | 112 | */ |
60 | return (rand_r(&seed) % 0xFF); | 113 | ret = rndDev->getch(); |
114 | } else { | ||
115 | /* fall back to rand_r() */ | ||
116 | ret = rand_r(&seed) % 0xFF; | ||
61 | } | 117 | } |
118 | #ifndef PWM_EMBEDDED | ||
119 | mutex->unlock(); | ||
120 | #endif | ||
121 | return ret; | ||
62 | } | 122 | } |
63 | 123 | ||
64 | int Randomizer::genRndInt() | 124 | int Randomizer::genRndInt() |
65 | { | 125 | { |
66 | if(rndDev) { | 126 | int ret; |
67 | int ret; | 127 | #ifndef PWM_EMBEDDED |
128 | mutex->lock(); | ||
129 | #endif | ||
130 | if (rndDev) { | ||
68 | if (sizeof(int) == 4) { | 131 | if (sizeof(int) == 4) { |
69 | (reinterpret_cast<char *>(&ret))[0] = getc(rndDev); | 132 | (reinterpret_cast<char *>(&ret))[0] = rndDev->getch(); |
70 | (reinterpret_cast<char *>(&ret))[1] = getc(rndDev); | 133 | (reinterpret_cast<char *>(&ret))[1] = rndDev->getch(); |
71 | (reinterpret_cast<char *>(&ret))[2] = getc(rndDev); | 134 | (reinterpret_cast<char *>(&ret))[2] = rndDev->getch(); |
72 | (reinterpret_cast<char *>(&ret))[3] = getc(rndDev); | 135 | (reinterpret_cast<char *>(&ret))[3] = rndDev->getch(); |
73 | } else if (sizeof(int) == 8) { | 136 | } else if (sizeof(int) == 8) { |
74 | (reinterpret_cast<char *>(&ret))[0] = getc(rndDev); | 137 | (reinterpret_cast<char *>(&ret))[0] = rndDev->getch(); |
75 | (reinterpret_cast<char *>(&ret))[1] = getc(rndDev); | 138 | (reinterpret_cast<char *>(&ret))[1] = rndDev->getch(); |
76 | (reinterpret_cast<char *>(&ret))[2] = getc(rndDev); | 139 | (reinterpret_cast<char *>(&ret))[2] = rndDev->getch(); |
77 | (reinterpret_cast<char *>(&ret))[3] = getc(rndDev); | 140 | (reinterpret_cast<char *>(&ret))[3] = rndDev->getch(); |
78 | (reinterpret_cast<char *>(&ret))[4] = getc(rndDev); | 141 | (reinterpret_cast<char *>(&ret))[4] = rndDev->getch(); |
79 | (reinterpret_cast<char *>(&ret))[5] = getc(rndDev); | 142 | (reinterpret_cast<char *>(&ret))[5] = rndDev->getch(); |
80 | (reinterpret_cast<char *>(&ret))[6] = getc(rndDev); | 143 | (reinterpret_cast<char *>(&ret))[6] = rndDev->getch(); |
81 | (reinterpret_cast<char *>(&ret))[7] = getc(rndDev); | 144 | (reinterpret_cast<char *>(&ret))[7] = rndDev->getch(); |
82 | } else { | 145 | } else { |
83 | printWarn(string(__FILE__) + ":" + tostr(__LINE__) | 146 | printWarn(string(__FILE__) + ":" + tostr(__LINE__) |
84 | + ": sizeof(int) != 4 && sizeof(int) != 8"); | 147 | + ": sizeof(int) != 4 && sizeof(int) != 8"); |
85 | rndDev = 0; | 148 | ret = rand_r(&seed); |
86 | seed = time(0); | ||
87 | return genRndInt(); | ||
88 | } | 149 | } |
89 | return ret; | ||
90 | } else { | 150 | } else { |
91 | return rand_r(&seed); | 151 | ret = rand_r(&seed); |
92 | } | 152 | } |
153 | #ifndef PWM_EMBEDDED | ||
154 | mutex->unlock(); | ||
155 | #endif | ||
156 | return ret; | ||
93 | } | 157 | } |
94 | 158 | ||
95 | unsigned int Randomizer::genRndUInt() | 159 | unsigned int Randomizer::genRndUInt() |
96 | { | 160 | { |
97 | if(rndDev) { | 161 | unsigned int ret; |
98 | unsigned int ret; | 162 | #ifndef PWM_EMBEDDED |
163 | mutex->lock(); | ||
164 | #endif | ||
165 | if (rndDev) { | ||
99 | if (sizeof(unsigned int) == 4) { | 166 | if (sizeof(unsigned int) == 4) { |
100 | (reinterpret_cast<char *>(&ret))[0] = getc(rndDev); | 167 | (reinterpret_cast<char *>(&ret))[0] = rndDev->getch(); |
101 | (reinterpret_cast<char *>(&ret))[1] = getc(rndDev); | 168 | (reinterpret_cast<char *>(&ret))[1] = rndDev->getch(); |
102 | (reinterpret_cast<char *>(&ret))[2] = getc(rndDev); | 169 | (reinterpret_cast<char *>(&ret))[2] = rndDev->getch(); |
103 | (reinterpret_cast<char *>(&ret))[3] = getc(rndDev); | 170 | (reinterpret_cast<char *>(&ret))[3] = rndDev->getch(); |
104 | } else if (sizeof(unsigned int) == 8) { | 171 | } else if (sizeof(unsigned int) == 8) { |
105 | (reinterpret_cast<char *>(&ret))[0] = getc(rndDev); | 172 | (reinterpret_cast<char *>(&ret))[0] = rndDev->getch(); |
106 | (reinterpret_cast<char *>(&ret))[1] = getc(rndDev); | 173 | (reinterpret_cast<char *>(&ret))[1] = rndDev->getch(); |
107 | (reinterpret_cast<char *>(&ret))[2] = getc(rndDev); | 174 | (reinterpret_cast<char *>(&ret))[2] = rndDev->getch(); |
108 | (reinterpret_cast<char *>(&ret))[3] = getc(rndDev); | 175 | (reinterpret_cast<char *>(&ret))[3] = rndDev->getch(); |
109 | (reinterpret_cast<char *>(&ret))[4] = getc(rndDev); | 176 | (reinterpret_cast<char *>(&ret))[4] = rndDev->getch(); |
110 | (reinterpret_cast<char *>(&ret))[5] = getc(rndDev); | 177 | (reinterpret_cast<char *>(&ret))[5] = rndDev->getch(); |
111 | (reinterpret_cast<char *>(&ret))[6] = getc(rndDev); | 178 | (reinterpret_cast<char *>(&ret))[6] = rndDev->getch(); |
112 | (reinterpret_cast<char *>(&ret))[7] = getc(rndDev); | 179 | (reinterpret_cast<char *>(&ret))[7] = rndDev->getch(); |
113 | } else { | 180 | } else { |
114 | printWarn(string(__FILE__) + ":" + tostr(__LINE__) | 181 | printWarn(string(__FILE__) + ":" + tostr(__LINE__) |
115 | + ": sizeof(unsigned int) != 4 && sizeof(unsigned int) != 8"); | 182 | + ": sizeof(unsigned int) != 4 && sizeof(unsigned int) != 8"); |
116 | rndDev = 0; | 183 | ret = rand_r(&seed); |
117 | seed = time(0); | ||
118 | return genRndUInt(); | ||
119 | } | 184 | } |
120 | return ret; | ||
121 | } else { | 185 | } else { |
122 | return static_cast<unsigned int>(rand_r(&seed)); | 186 | ret = rand_r(&seed); |
187 | } | ||
188 | #ifndef PWM_EMBEDDED | ||
189 | mutex->unlock(); | ||
190 | #endif | ||
191 | return ret; | ||
192 | } | ||
193 | |||
194 | void Randomizer::genRndBuf(unsigned char *buf, size_t len) | ||
195 | { | ||
196 | #ifndef PWM_EMBEDDED | ||
197 | mutex->lock(); | ||
198 | #endif | ||
199 | if (rndDev) { | ||
200 | Q_LONG n; | ||
201 | n = rndDev->readBlock(reinterpret_cast<char *>(buf), len); | ||
202 | WARN_ON(n != static_cast<Q_LONG>(len)); | ||
203 | } else { | ||
204 | size_t i; | ||
205 | for (i = 0; i < len; ++i) | ||
206 | buf[i] = rand_r(&seed) % 0xFF; | ||
123 | } | 207 | } |
208 | #ifndef PWM_EMBEDDED | ||
209 | mutex->unlock(); | ||
210 | #endif | ||
211 | } | ||
212 | |||
213 | string Randomizer::genRndBuf(size_t len) | ||
214 | { | ||
215 | string ret; | ||
216 | unsigned char *buf; | ||
217 | buf = new unsigned char[len]; | ||
218 | genRndBuf(buf, len); | ||
219 | ret.assign(reinterpret_cast<const char *>(buf), len); | ||
220 | return ret; | ||
124 | } | 221 | } |
diff --git a/pwmanager/pwmanager/randomizer.h b/pwmanager/pwmanager/randomizer.h index db17334..5eb02f1 100644 --- a/pwmanager/pwmanager/randomizer.h +++ b/pwmanager/pwmanager/randomizer.h | |||
@@ -11,21 +11,31 @@ | |||
11 | 11 | ||
12 | /*************************************************************************** | 12 | /*************************************************************************** |
13 | * copyright (C) 2004 by Ulf Schenk | 13 | * copyright (C) 2004 by Ulf Schenk |
14 | * This file is originaly based on version 1.0.1 of pwmanager | 14 | * This file is originaly based on version 2.0 of pwmanager |
15 | * and was modified to run on embedded devices that run microkde | 15 | * and was modified to run on embedded devices that run microkde |
16 | * | 16 | * |
17 | * $Id$ | 17 | * $Id$ |
18 | **************************************************************************/ | 18 | **************************************************************************/ |
19 | 19 | ||
20 | #ifndef RANDOMIZER_H | 20 | #ifndef __RANDOMIZER_H |
21 | #define RANDOMIZER_H | 21 | #define __RANDOMIZER_H |
22 | 22 | ||
23 | #include "pwmexception.h" | 23 | #include "pwmexception.h" |
24 | 24 | ||
25 | #include <stdio.h> | 25 | #ifndef PWM_EMBEDDED |
26 | #include <qmutex.h> | ||
27 | #endif | ||
28 | |||
29 | #include <string> | ||
30 | |||
31 | using std::string; | ||
32 | |||
33 | class QFile; | ||
26 | 34 | ||
27 | /** simple randomizer | 35 | /** Randomizer to get random values. |
28 | * This class is *NOT* reentrant save! | 36 | * This class is thread-safe. |
37 | * You should always use the instance returned by | ||
38 | * obj() to use it. | ||
29 | */ | 39 | */ |
30 | class Randomizer | 40 | class Randomizer |
31 | { | 41 | { |
@@ -52,16 +62,25 @@ public: | |||
52 | char genRndChar(); | 62 | char genRndChar(); |
53 | /** generate random int */ | 63 | /** generate random int */ |
54 | int genRndInt(); | 64 | int genRndInt(); |
55 | /** generate random unsigned int */ | 65 | /** generate a random unsigned int */ |
56 | unsigned int genRndUInt(); | 66 | unsigned int genRndUInt(); |
57 | 67 | ||
68 | /** returns a buffer with random data */ | ||
69 | string genRndBuf(size_t len); | ||
70 | /** returns a buffer with random data */ | ||
71 | void genRndBuf(unsigned char *buf, size_t len); | ||
72 | |||
58 | protected: | 73 | protected: |
59 | /** random-device-node (if available. Otherwise NULL) */ | 74 | /** random-device-node (if available. Otherwise NULL) */ |
60 | FILE *rndDev; | 75 | QFile *rndDev; |
76 | #ifndef PWM_EMBEDDED | ||
77 | /** mutex for accessing the public functions thread-save */ | ||
78 | QMutex mutex; | ||
79 | #endif | ||
61 | /** seed value for fallback - rand_r() */ | 80 | /** seed value for fallback - rand_r() */ |
62 | unsigned int seed; | 81 | unsigned int seed; |
63 | /** static Randomier object returned by obj() */ | 82 | /** static Randomizer object returned by obj() */ |
64 | static Randomizer *rndObj; | 83 | static Randomizer *rndObj; |
65 | }; | 84 | }; |
66 | 85 | ||
67 | #endif | 86 | #endif // __RANDOMIZER_H |