-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 @@ /*************************************************************************** * 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 |