summaryrefslogtreecommitdiffabout
Side-by-side diff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--pwmanager/pwmanager/randomizer.cpp207
-rw-r--r--pwmanager/pwmanager/randomizer.h39
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 @@
/***************************************************************************
* copyright (C) 2004 by Ulf Schenk
- * This file is originaly based on version 1.0.1 of pwmanager
+ * This file is originaly based on version 2.0 of pwmanager
* and was modified to run on embedded devices that run microkde
*
* $Id$
@@ -20,105 +20,202 @@
#include "randomizer.h"
#include "pwmexception.h"
+#include <qfile.h>
+
+#include <kapplication.h>
+
#include <stdlib.h>
#include <time.h>
+#ifdef PWM_EMBEDDED
+
+#ifndef Q_LONG
+#define Q_LONG long
+#endif
+
+#endif //PWM_EMBEDDED
+
+
Randomizer * Randomizer::rndObj (0);
Randomizer::Randomizer()
{
- // probe for random devices
- rndDev = fopen("/dev/urandom", "r");
- if (rndDev)
+ rndDev = new QFile;
+ seed = time(0);
+
+#if 1 // set to 0 to test rand_r() fallback
+
+ // probe for /dev/urandom
+ rndDev->setName("/dev/urandom");
+ if (rndDev->exists() &&
+ rndDev->open(IO_ReadOnly)) {
+ printDebug("Randomizer: using /dev/urandom");
return;
- rndDev = fopen("/dev/random", "r");
- if (rndDev)
+ }
+
+ // probe for /dev/random
+ rndDev->setName("/dev/random");
+ if (rndDev->exists() &&
+ rndDev->open(IO_ReadOnly)) {
+ printDebug("Randomizer: using /dev/random");
return;
- // fall back to rand_r()
- seed = time(0);
+ }
+
+ // probe for EGD
+ char *fn = getenv("RANDFILE");
+ if (fn) {
+ rndDev->setName(fn);
+ if (rndDev->exists() &&
+ rndDev->open(IO_ReadOnly)) {
+ printDebug(string("Randomizer: using $RANDFILE \"")
+ + fn
+ + "\" (aka EGD)");
+ return;
+ }
+ }
+#endif
+
+ /* no secure randomizer found.
+ * Fall back to stdlib randomizer.
+ */
+ delete_and_null(rndDev);
+ printWarn("neither /dev/*random nor EGD found! "
+ "Falling back to insecure rand_r()!");
}
Randomizer::~Randomizer()
{
+#ifndef PWM_EMBEDDED
+ while (mutex.locked()) {
+ /* wait for the mutex to unlock.
+ * Don't block the GUI here, so processEvents()
+ */
+ kapp->processEvents();
+ }
+#endif
if (rndDev) {
- if (fclose(rndDev)) {
- printWarn("failed closing the random-device!");
- }
+ rndDev->close();
+ delete rndDev;
}
}
char Randomizer::genRndChar()
{
+ char ret;
+#ifndef PWM_EMBEDDED
+ mutex.lock();
+#endif
if (rndDev) {
- /* we have a rand-device-node */
- return (getc(rndDev));
- } else {
- /* we don't have a random-device-node.
- * so fall back to rand_r()
+ /* we have a file which provides random data.
+ * Simply read it.
*/
- return (rand_r(&seed) % 0xFF);
+ ret = rndDev->getch();
+ } else {
+ /* fall back to rand_r() */
+ ret = rand_r(&seed) % 0xFF;
}
+#ifndef PWM_EMBEDDED
+ mutex->unlock();
+#endif
+ return ret;
}
int Randomizer::genRndInt()
{
- if(rndDev) {
- int ret;
+ int ret;
+#ifndef PWM_EMBEDDED
+ mutex->lock();
+#endif
+ if (rndDev) {
if (sizeof(int) == 4) {
- (reinterpret_cast<char *>(&ret))[0] = getc(rndDev);
- (reinterpret_cast<char *>(&ret))[1] = getc(rndDev);
- (reinterpret_cast<char *>(&ret))[2] = getc(rndDev);
- (reinterpret_cast<char *>(&ret))[3] = getc(rndDev);
+ (reinterpret_cast<char *>(&ret))[0] = rndDev->getch();
+ (reinterpret_cast<char *>(&ret))[1] = rndDev->getch();
+ (reinterpret_cast<char *>(&ret))[2] = rndDev->getch();
+ (reinterpret_cast<char *>(&ret))[3] = rndDev->getch();
} else if (sizeof(int) == 8) {
- (reinterpret_cast<char *>(&ret))[0] = getc(rndDev);
- (reinterpret_cast<char *>(&ret))[1] = getc(rndDev);
- (reinterpret_cast<char *>(&ret))[2] = getc(rndDev);
- (reinterpret_cast<char *>(&ret))[3] = getc(rndDev);
- (reinterpret_cast<char *>(&ret))[4] = getc(rndDev);
- (reinterpret_cast<char *>(&ret))[5] = getc(rndDev);
- (reinterpret_cast<char *>(&ret))[6] = getc(rndDev);
- (reinterpret_cast<char *>(&ret))[7] = getc(rndDev);
+ (reinterpret_cast<char *>(&ret))[0] = rndDev->getch();
+ (reinterpret_cast<char *>(&ret))[1] = rndDev->getch();
+ (reinterpret_cast<char *>(&ret))[2] = rndDev->getch();
+ (reinterpret_cast<char *>(&ret))[3] = rndDev->getch();
+ (reinterpret_cast<char *>(&ret))[4] = rndDev->getch();
+ (reinterpret_cast<char *>(&ret))[5] = rndDev->getch();
+ (reinterpret_cast<char *>(&ret))[6] = rndDev->getch();
+ (reinterpret_cast<char *>(&ret))[7] = rndDev->getch();
} else {
printWarn(string(__FILE__) + ":" + tostr(__LINE__)
+ ": sizeof(int) != 4 && sizeof(int) != 8");
- rndDev = 0;
- seed = time(0);
- return genRndInt();
+ ret = rand_r(&seed);
}
- return ret;
} else {
- return rand_r(&seed);
+ ret = rand_r(&seed);
}
+#ifndef PWM_EMBEDDED
+ mutex->unlock();
+#endif
+ return ret;
}
unsigned int Randomizer::genRndUInt()
{
- if(rndDev) {
- unsigned int ret;
+ unsigned int ret;
+#ifndef PWM_EMBEDDED
+ mutex->lock();
+#endif
+ if (rndDev) {
if (sizeof(unsigned int) == 4) {
- (reinterpret_cast<char *>(&ret))[0] = getc(rndDev);
- (reinterpret_cast<char *>(&ret))[1] = getc(rndDev);
- (reinterpret_cast<char *>(&ret))[2] = getc(rndDev);
- (reinterpret_cast<char *>(&ret))[3] = getc(rndDev);
+ (reinterpret_cast<char *>(&ret))[0] = rndDev->getch();
+ (reinterpret_cast<char *>(&ret))[1] = rndDev->getch();
+ (reinterpret_cast<char *>(&ret))[2] = rndDev->getch();
+ (reinterpret_cast<char *>(&ret))[3] = rndDev->getch();
} else if (sizeof(unsigned int) == 8) {
- (reinterpret_cast<char *>(&ret))[0] = getc(rndDev);
- (reinterpret_cast<char *>(&ret))[1] = getc(rndDev);
- (reinterpret_cast<char *>(&ret))[2] = getc(rndDev);
- (reinterpret_cast<char *>(&ret))[3] = getc(rndDev);
- (reinterpret_cast<char *>(&ret))[4] = getc(rndDev);
- (reinterpret_cast<char *>(&ret))[5] = getc(rndDev);
- (reinterpret_cast<char *>(&ret))[6] = getc(rndDev);
- (reinterpret_cast<char *>(&ret))[7] = getc(rndDev);
+ (reinterpret_cast<char *>(&ret))[0] = rndDev->getch();
+ (reinterpret_cast<char *>(&ret))[1] = rndDev->getch();
+ (reinterpret_cast<char *>(&ret))[2] = rndDev->getch();
+ (reinterpret_cast<char *>(&ret))[3] = rndDev->getch();
+ (reinterpret_cast<char *>(&ret))[4] = rndDev->getch();
+ (reinterpret_cast<char *>(&ret))[5] = rndDev->getch();
+ (reinterpret_cast<char *>(&ret))[6] = rndDev->getch();
+ (reinterpret_cast<char *>(&ret))[7] = rndDev->getch();
} else {
printWarn(string(__FILE__) + ":" + tostr(__LINE__)
+ ": sizeof(unsigned int) != 4 && sizeof(unsigned int) != 8");
- rndDev = 0;
- seed = time(0);
- return genRndUInt();
+ ret = rand_r(&seed);
}
- return ret;
} else {
- return static_cast<unsigned int>(rand_r(&seed));
+ ret = rand_r(&seed);
+ }
+#ifndef PWM_EMBEDDED
+ mutex->unlock();
+#endif
+ return ret;
+}
+
+void Randomizer::genRndBuf(unsigned char *buf, size_t len)
+{
+#ifndef PWM_EMBEDDED
+ mutex->lock();
+#endif
+ if (rndDev) {
+ Q_LONG n;
+ n = rndDev->readBlock(reinterpret_cast<char *>(buf), len);
+ WARN_ON(n != static_cast<Q_LONG>(len));
+ } else {
+ size_t i;
+ for (i = 0; i < len; ++i)
+ buf[i] = rand_r(&seed) % 0xFF;
}
+#ifndef PWM_EMBEDDED
+ mutex->unlock();
+#endif
+}
+
+string Randomizer::genRndBuf(size_t len)
+{
+ string ret;
+ unsigned char *buf;
+ buf = new unsigned char[len];
+ genRndBuf(buf, len);
+ ret.assign(reinterpret_cast<const char *>(buf), len);
+ return ret;
}
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 @@
/***************************************************************************
* copyright (C) 2004 by Ulf Schenk
- * This file is originaly based on version 1.0.1 of pwmanager
+ * This file is originaly based on version 2.0 of pwmanager
* and was modified to run on embedded devices that run microkde
*
* $Id$
**************************************************************************/
-#ifndef RANDOMIZER_H
-#define RANDOMIZER_H
+#ifndef __RANDOMIZER_H
+#define __RANDOMIZER_H
#include "pwmexception.h"
-#include <stdio.h>
+#ifndef PWM_EMBEDDED
+#include <qmutex.h>
+#endif
+
+#include <string>
+
+using std::string;
+
+class QFile;
-/** simple randomizer
- * This class is *NOT* reentrant save!
+/** Randomizer to get random values.
+ * This class is thread-safe.
+ * You should always use the instance returned by
+ * obj() to use it.
*/
class Randomizer
{
@@ -52,16 +62,25 @@ public:
char genRndChar();
/** generate random int */
int genRndInt();
- /** generate random unsigned int */
+ /** generate a random unsigned int */
unsigned int genRndUInt();
+ /** returns a buffer with random data */
+ string genRndBuf(size_t len);
+ /** returns a buffer with random data */
+ void genRndBuf(unsigned char *buf, size_t len);
+
protected:
/** random-device-node (if available. Otherwise NULL) */
- FILE *rndDev;
+ QFile *rndDev;
+#ifndef PWM_EMBEDDED
+ /** mutex for accessing the public functions thread-save */
+ QMutex mutex;
+#endif
/** seed value for fallback - rand_r() */
unsigned int seed;
- /** static Randomier object returned by obj() */
+ /** static Randomizer object returned by obj() */
static Randomizer *rndObj;
};
-#endif
+#endif // __RANDOMIZER_H