-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge PR #2882: CryptographicRandom: new class for acquiring random d…
…ata for cryptographic purposes.
- Loading branch information
Showing
11 changed files
with
319 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
Copyright (c) 2008, Damien Miller <djm@openbsd.org> | ||
|
||
Permission to use, copy, modify, and distribute this software for any | ||
purpose with or without fee is hereby granted, provided that the above | ||
copyright notice and this permission notice appear in all copies. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
/* $OpenBSD: arc4random_uniform.c,v 1.2 2015/09/13 08:31:47 guenther Exp $ */ | ||
|
||
/* | ||
* Copyright (c) 2008, Damien Miller <djm@openbsd.org> | ||
* | ||
* Permission to use, copy, modify, and distribute this software for any | ||
* purpose with or without fee is hereby granted, provided that the above | ||
* copyright notice and this permission notice appear in all copies. | ||
* | ||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
*/ | ||
|
||
// This is arc4random_uniform.c from OpenBSD's source tree at | ||
// $OPENBSD_ROOT/lib/libc/crypt/arc4random_uniform.c. | ||
// | ||
// Mumble-specific changes: | ||
// | ||
// - Change file extension to .cpp and rename to mumble_arc4random_uniform.cpp. | ||
// - Add CryptographicRandom.h include. | ||
// - Remove <sys/types.h> and <stdlib.h> includes, include <stdint.h> for uint32_t. | ||
// - Added an implementation of arc4random called mumble_arc4random. | ||
// - Rename arc4random_uniform to mumble_arc4random_uniform. | ||
// - Change call to arc4random in mumble_arc4random_uniform to call | ||
// mumble_arc4random instead of arc4random. | ||
// - Remove DEF_WEAK for arc4random_uniform. | ||
// - Disable MSVC warning 4146. | ||
|
||
#include <stdint.h> | ||
#include "CryptographicRandom.h" | ||
|
||
#if defined(_MSC_VER) | ||
// Disable "unary minus operator applied to unsigned type, result still unsigned" | ||
// warning. The unary minus operator used in arc4random_uniform is perfectly valid. | ||
# pragma warning(disable: 4146) | ||
#endif | ||
|
||
// Call through to CryptographicRandom::uint32() | ||
uint32_t | ||
mumble_arc4random(void) | ||
{ | ||
return CryptographicRandom::uint32(); | ||
} | ||
|
||
/* | ||
* Calculate a uniformly distributed random number less than upper_bound | ||
* avoiding "modulo bias". | ||
* | ||
* Uniformity is achieved by generating new random numbers until the one | ||
* returned is outside the range [0, 2**32 % upper_bound). This | ||
* guarantees the selected random number will be inside | ||
* [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound) | ||
* after reduction modulo upper_bound. | ||
*/ | ||
uint32_t | ||
mumble_arc4random_uniform(uint32_t upper_bound) | ||
{ | ||
uint32_t r, min; | ||
|
||
if (upper_bound < 2) | ||
return 0; | ||
|
||
/* 2**32 % x == (2**32 - x) % x */ | ||
min = -upper_bound % upper_bound; | ||
|
||
/* | ||
* This could theoretically loop forever but each retry has | ||
* p > 0.5 (worst case, usually far better) of selecting a | ||
* number inside the range we need, so it should rarely need | ||
* to re-roll. | ||
*/ | ||
for (;;) { | ||
r = mumble_arc4random(); | ||
if (r >= min) | ||
break; | ||
} | ||
|
||
return r % upper_bound; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
// Copyright 2005-2017 The Mumble Developers. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license | ||
// that can be found in the LICENSE file at the root of the | ||
// Mumble source tree or at <https://www.mumble.info/LICENSE>. | ||
|
||
#ifndef MUMBLE_3RDPARTY_ARC4RANDOM_UNIFORM_H_ | ||
#define MUMBLE_3RDPARTY_ARC4RANDOM_UNIFORM_H_ | ||
|
||
#include <stdint.h> | ||
|
||
uint32_t mumble_arc4random(void); | ||
uint32_t mumble_arc4random_uniform(uint32_t upper_bound); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// Copyright 2005-2017 The Mumble Developers. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license | ||
// that can be found in the LICENSE file at the root of the | ||
// Mumble source tree or at <https://www.mumble.info/LICENSE>. | ||
|
||
#include "murmur_pch.h" | ||
|
||
#include "CryptographicRandom.h" | ||
|
||
#include "arc4random_uniform.h" | ||
|
||
void CryptographicRandom::fillBuffer(void *buf, int numBytes) { | ||
// We treat negative and zero values of numBytes to be | ||
// fatal errors in the program. Abort the program if such | ||
// a value is passed to fillBuffer(). | ||
if (numBytes <= 0) { | ||
qFatal("CryptographicRandom::fillBuffer(): numBytes is <= 0"); | ||
} | ||
|
||
// RAND_bytes only returns an error if the entropy pool has not yet been sufficiently filled, | ||
// or in the case of a catastrophic, unrecoverable error in the RAND_bytes implementation happens. | ||
// OpenSSL needs at least 32-bytes of high-entropy random data to seed its CSPRNG. | ||
// If OpenSSL cannot acquire enough random data to seed its CSPRNG at the time Mumble and Murmur | ||
// are running, there is not much we can do about it other than aborting the program. | ||
if (RAND_bytes(reinterpret_cast<unsigned char *>(buf), static_cast<int>(numBytes)) != 1) { | ||
qFatal("CryptographicRandom::fillBuffer(): internal error in OpenSSL's RAND_bytes or entropy pool not yet filled."); | ||
} | ||
} | ||
|
||
uint32_t CryptographicRandom::uint32() { | ||
uint32_t ret = 0; | ||
|
||
unsigned char buf[4]; | ||
CryptographicRandom::fillBuffer(buf, sizeof(buf)); | ||
|
||
ret = (buf[0]) | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); | ||
return ret; | ||
} | ||
|
||
uint32_t CryptographicRandom::uniform(uint32_t upperBound) { | ||
// Implemented in 3rdparty/arc4random/arc4random_uniform.c | ||
return mumble_arc4random_uniform(upperBound); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
// Copyright 2005-2017 The Mumble Developers. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license | ||
// that can be found in the LICENSE file at the root of the | ||
// Mumble source tree or at <https://www.mumble.info/LICENSE>. | ||
|
||
#ifndef MUMBLE_CRYPTOGRAPHICRANDOM_H_ | ||
#define MUMBLE_CRYPTOGRAPHICRANDOM_H_ | ||
|
||
#include <stdint.h> | ||
|
||
/// CryptographicRandom provides useful utilities for acquiring | ||
/// pseudo-random data for use in cryptography. | ||
class CryptographicRandom { | ||
public: | ||
/// Fill the buffer at |buf| with |numBytes| bytes of pseudo-random data. | ||
/// The value of |numBytes| must be >= 0. Otherwise, program execution is aborted. | ||
/// | ||
/// This function is equivalent to the arc4random_buf() function from OpenBSD. | ||
/// | ||
/// This function should not ever fail. It is considered a catastrophic failure if | ||
/// it does. The program is aborted if the function fails, because it is generally | ||
/// impossible to recover from such a scenario. | ||
static void fillBuffer(void *buf, int numBytes); | ||
|
||
/// Return a pseudo-random number in the range of 0 to (2**32)-1. | ||
/// | ||
/// This function is equivalent to the arc4random() function from OpenBSD. | ||
/// | ||
/// This function should not ever fail. It is considered a catastrophic failure if | ||
/// it does. The program is aborted if the function fails, because it is generally | ||
/// impossible to recover from such a scenario. | ||
static uint32_t uint32(); | ||
|
||
/// Calculate a uniformly distributed random number less than |upperBound| | ||
/// avoiding "modulo bias". | ||
/// | ||
/// This function is equivalent to the arc4random_uniform() function from OpenBSD. | ||
/// | ||
/// This function should not ever fail. It is considered a catastrophic failure if | ||
/// it does. The program is aborted if the function fails, because it is generally | ||
/// impossible to recover from such a scenario. | ||
static uint32_t uniform(uint32_t upperBound); | ||
}; | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
74 changes: 74 additions & 0 deletions
74
src/tests/TestCryptographicRandom/TestCryptographicRandom.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
// Copyright 2005-2017 The Mumble Developers. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license | ||
// that can be found in the LICENSE file at the root of the | ||
// Mumble source tree or at <https://www.mumble.info/LICENSE>. | ||
|
||
#include <QtCore> | ||
#include <QtTest> | ||
|
||
#include "CryptographicRandom.h" | ||
|
||
#include <stdint.h> | ||
#include <stdlib.h> | ||
#include <limits> | ||
|
||
class TestCryptographicRandom : public QObject { | ||
Q_OBJECT | ||
private slots: | ||
void fillBuffer(); | ||
void uint32(); | ||
void uniform(); | ||
}; | ||
|
||
// Verify the entropy of the data returned by the random source | ||
// by zlib compressing it and ensuring the compressed size is at | ||
// least 99% of the size of the input data. | ||
// | ||
// The inspiration for this check is from the rand_test.go file | ||
// for Go standard library's crypt/rand package: | ||
// https://golang.org/src/crypto/rand/rand_test.go | ||
bool verifyEntropy(unsigned char *buf, int len) { | ||
QByteArray flated = qCompress(buf, len); | ||
return (flated.size() >= ((len * 99) / 100)); | ||
} | ||
|
||
void TestCryptographicRandom::fillBuffer() { | ||
const int buflen = 1000000; | ||
|
||
for (int i = 0; i < 10; i++) { | ||
unsigned char *buf = reinterpret_cast<unsigned char *>(calloc(buflen, 1)); | ||
CryptographicRandom::fillBuffer(buf, buflen); | ||
QVERIFY(verifyEntropy(buf, buflen)); | ||
free(buf); | ||
} | ||
} | ||
|
||
void TestCryptographicRandom::uint32() { | ||
const int buflen = 1000000; | ||
|
||
for (int i = 0; i < 10; i++) { | ||
unsigned char *buf = reinterpret_cast<unsigned char *>(calloc(buflen, 1)); | ||
int niter = buflen / sizeof(uint32_t); | ||
for (int j = 0; j < niter; j++) { | ||
int off = j * sizeof(uint32_t); | ||
uint32_t val = CryptographicRandom::uint32(); | ||
buf[off] = val & 0xff; | ||
buf[off+1] = (val >> 8) & 0xff; | ||
buf[off+2] = (val >> 16) & 0xff; | ||
buf[off+3] = (val >> 24) & 0xff; | ||
} | ||
QVERIFY(verifyEntropy(buf, buflen)); | ||
free(buf); | ||
} | ||
} | ||
|
||
void TestCryptographicRandom::uniform() { | ||
for (uint32_t upperBound = 0; upperBound < 10000; upperBound++) { | ||
uint32_t val = CryptographicRandom::uniform(upperBound); | ||
QVERIFY(val <= upperBound); | ||
} | ||
} | ||
|
||
|
||
QTEST_MAIN(TestCryptographicRandom) | ||
#include "TestCryptographicRandom.moc" |
20 changes: 20 additions & 0 deletions
20
src/tests/TestCryptographicRandom/TestCryptographicRandom.pro
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# Copyright 2005-2017 The Mumble Developers. All rights reserved. | ||
# Use of this source code is governed by a BSD-style license | ||
# that can be found in the LICENSE file at the root of the | ||
# Mumble source tree or at <https://www.mumble.info/LICENSE>. | ||
|
||
include(../../../compiler.pri) | ||
include(../../../qmake/openssl.pri) | ||
|
||
TEMPLATE = app | ||
QT = core testlib | ||
CONFIG += testcase | ||
CONFIG += qt warn_on | ||
CONFIG -= app_bundle | ||
LANGUAGE = C++ | ||
TARGET = TestCryptographicRandom | ||
SOURCES = TestCryptographicRandom.cpp CryptographicRandom.cpp arc4random_uniform.cpp | ||
HEADERS = CryptographicHash.h | ||
VPATH += ../.. | ||
VPATH += ../../../3rdparty/arc4random-src | ||
INCLUDEPATH += ../.. ../../murmur ../../mumble ../../../3rdparty/arc4random-src |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters