crypto.cpp

Go to the documentation of this file.
00001 /****************************************************************
00002  *  Vidalia is distributed under the following license:
00003  *
00004  *  Copyright (C) 2007,  Matt Edman, Justin Hipple
00005  *
00006  *  This program is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU General Public License
00008  *  as published by the Free Software Foundation; either version 2
00009  *  of the License, or (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019  *  Boston, MA  02110-1301, USA.
00020  * 
00021  *                     *       *       *
00022  * 
00023  *  Pseudorandom number generation support in this file is derived from
00024  *  Tor's crypto.[ch]. Tor is distributed under this license.
00025  * 
00026  *    Copyright (c) 2001-2004, Roger Dingledine
00027  *    Copyright (c) 2004-2007, Roger Dingledine, Nick Mathewson
00028  *
00029  *   Redistribution and use in source and binary forms, with or without
00030  *   modification, are permitted provided that the following conditions are
00031  *   met:
00032  *
00033  *     * Redistributions of source code must retain the above copyright
00034  *       notice, this list of conditions and the following disclaimer.
00035  *
00036  *     * Redistributions in binary form must reproduce the above
00037  *       copyright notice, this list of conditions and the following disclaimer
00038  *       in the documentation and/or other materials provided with the
00039  *       distribution.
00040  * 
00041  *     * Neither the names of the copyright owners nor the names of its
00042  *       contributors may be used to endorse or promote products derived from
00043  *       this software without specific prior written permission.
00044  *
00045  *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00046  *    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00047  *    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00048  *    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00049  *    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00050  *    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00051  *    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00052  *    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00053  *    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00054  *    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00055  *    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00056  ****************************************************************/
00057 
00058 /**
00059  * \file crypto.cpp
00060  * \version $Id: crypto.cpp 1847 2007-08-21 05:38:31Z edmanm $
00061  * \brief Provides support for pseuodrandom number generation.
00062  */
00063 
00064 #include <QFile>
00065 #include <QStringList>
00066 #include <QtDebug>
00067 #include "crypto.h"
00068 
00069 #if defined(Q_OS_WIN32)
00070 #include <windows.h>
00071 #include <wincrypt.h>
00072 #endif
00073 
00074 
00075 /** Returns <b>len</b> bytes of pseudorandom data on success, or an empty
00076  * QByteArray on failure. This function is based on crypto_seed_rng() from
00077  * Tor's crypto.c. See LICENSE for details on Tor's license. */
00078 QByteArray
00079 crypto_rand_bytes(int len)
00080 {
00081   QByteArray buf(len, 0);
00082 #if defined(Q_OS_WIN32)
00083   static int provider_set = 0;
00084   static HCRYPTPROV provider;
00085 #else
00086   static QStringList filenames =
00087     QStringList() << "/dev/srandom" << "/dev/urandom" << "/dev/random";
00088 #endif
00089   Q_ASSERT(len > 0);
00090 
00091 #if defined(Q_OS_WIN32)
00092   if (!provider_set) {
00093     if (!CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL,
00094                              CRYPT_VERIFYCONTEXT)) {
00095       if ((unsigned long)GetLastError() != (unsigned long)NTE_BAD_KEYSET) {
00096         qWarning("Can't get CryptoAPI provider.");
00097         return QByteArray();
00098       }
00099     }
00100     provider_set = 1;
00101   }
00102   if (!CryptGenRandom(provider, buf.size(), (BYTE *)buf.data())) {
00103     qWarning("Can't get entropy from CryptoAPI.");
00104     return QByteArray();
00105   }
00106   return buf;
00107 #else
00108   foreach (QString fname, filenames) {
00109     QFile file(fname);
00110     if (!file.open(QIODevice::ReadOnly))
00111       continue;
00112 
00113     qint64 bytes_read;
00114     qint64 total = 0;
00115     while (total < buf.size()) {
00116       bytes_read = file.read(buf.data()+total, buf.size()-total);
00117       if (bytes_read < 0)
00118         return QByteArray();
00119       else if (read == 0) {
00120         buf.resize(total);
00121         return buf;
00122       }
00123       total += bytes_read;
00124     }
00125     return buf;
00126   }
00127   qWarning("Can't read from /dev/*random.");
00128   return QByteArray();
00129 #endif
00130 }
00131 
00132 /** Returns a pseudorandom integer, chosen uniformly from the the values in
00133  * the range [0, max). This function is based on crypto_rand_int() from Tor's
00134  * crypto.c. See LICENSE for details on Tor's license. */
00135 quint32
00136 crypto_rand_quint32(quint32 max)
00137 {
00138   QByteArray buf;
00139   quint32 val;
00140   quint32 cutoff;
00141   Q_ASSERT(max > 0);
00142 
00143   cutoff = UINT_MAX - (UINT_MAX % max);
00144   forever {
00145     buf = crypto_rand_bytes(sizeof(quint32));
00146     Q_ASSERT(buf.size() == sizeof(quint32));
00147   
00148     val = *((quint32 *)buf.constData());
00149     if (val < cutoff)
00150       break;
00151   }
00152   return (val % max);
00153 }
00154 
00155 /** Generates a pseudorandom string of length <b>len</b> containing printable
00156  * ASCII characters of length from the range '!' (0x21) to '~' (0x7e). */
00157 QString
00158 crypto_rand_string(int len)
00159 {
00160   QString str;
00161   Q_ASSERT(len >= 0);
00162   
00163   for (int i = 0; i < len; i++)
00164     str += QChar('!' + crypto_rand_quint32('~'-'!'+1));
00165   return str;
00166 }
00167 

Generated on Wed Sep 5 15:49:27 2007 for Vidalia by  doxygen 1.5.3