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