summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorFrancis Dupont <fdupont@isc.org>2018-08-23 18:10:10 +0200
committerFrancis Dupont <fdupont@isc.org>2018-11-04 07:05:08 +0100
commit9e742d3034280a840481b7ad6f321f8e95e6029b (patch)
tree92eba61e1eb3cba1922c37216232ac44ff3cd2b0 /src
parent[master] Added ChangeLog for #194. (diff)
downloadkea-9e742d3034280a840481b7ad6f321f8e95e6029b.tar.xz
kea-9e742d3034280a840481b7ad6f321f8e95e6029b.zip
[29-cryptolink-random-generator] Added RNG support
Diffstat (limited to 'src')
-rw-r--r--src/lib/cryptolink/Makefile.am1
-rw-r--r--src/lib/cryptolink/botan1_link.cc40
-rw-r--r--src/lib/cryptolink/botan_link.cc41
-rw-r--r--src/lib/cryptolink/crypto_rng.cc33
-rw-r--r--src/lib/cryptolink/crypto_rng.h64
-rw-r--r--src/lib/cryptolink/cryptolink.cc5
-rw-r--r--src/lib/cryptolink/cryptolink.h19
-rw-r--r--src/lib/cryptolink/openssl_link.cc42
-rw-r--r--src/lib/cryptolink/tests/crypto_unittests.cc28
9 files changed, 265 insertions, 8 deletions
diff --git a/src/lib/cryptolink/Makefile.am b/src/lib/cryptolink/Makefile.am
index b7e14ca55d..9b3c9fde01 100644
--- a/src/lib/cryptolink/Makefile.am
+++ b/src/lib/cryptolink/Makefile.am
@@ -11,6 +11,7 @@ lib_LTLIBRARIES = libkea-cryptolink.la
libkea_cryptolink_la_SOURCES = cryptolink.h cryptolink.cc
libkea_cryptolink_la_SOURCES += crypto_hash.h crypto_hash.cc
libkea_cryptolink_la_SOURCES += crypto_hmac.h crypto_hmac.cc
+libkea_cryptolink_la_SOURCES += crypto_rng.h crypto_rng.cc
if HAVE_BOTAN1
libkea_cryptolink_la_SOURCES += botan1_link.cc
libkea_cryptolink_la_SOURCES += botan_common.h
diff --git a/src/lib/cryptolink/botan1_link.cc b/src/lib/cryptolink/botan1_link.cc
index a367c4ea6e..ce6bd8d6fa 100644
--- a/src/lib/cryptolink/botan1_link.cc
+++ b/src/lib/cryptolink/botan1_link.cc
@@ -9,9 +9,11 @@
#include <cryptolink/cryptolink.h>
#include <cryptolink/crypto_hash.h>
#include <cryptolink/crypto_hmac.h>
+#include <cryptolink/crypto_rng.h>
#include <botan/botan.h>
#include <botan/init.h>
+#include <botan/auto_rng.h>
namespace isc {
namespace cryptolink {
@@ -23,19 +25,55 @@ private:
};
CryptoLink::~CryptoLink() {
+ rng_.reset();
delete impl_;
}
+/// \brief Botan implementation of RNG.
+class RNGImpl : public RNG {
+public:
+ RNGImpl() {
+ rng.reset(new Botan::AutoSeeded_RNG());
+ }
+
+ ~RNGImpl() {
+ }
+
+private:
+ std::vector<uint8_t> random(size_t len) {
+ std::vector<uint8_t> data;
+ if (len > 0) {
+ data.resize(len);
+ try {
+ rng->randomize(&data[0], len);
+ } catch (const Botan::Exception& ex) {
+ isc_throw(isc::cryptolink::LibraryError,
+ "Botan error: " << ex.what());
+ }
+ }
+ return (data);
+ }
+
+ boost::shared_ptr<Botan::RandomNumberGenerator> rng;
+};
+
void
CryptoLink::initialize() {
CryptoLink& c = getCryptoLinkInternal();
- if (c.impl_ == NULL) {
+ if (!c.impl_) {
try {
c.impl_ = new CryptoLinkImpl();
} catch (const Botan::Exception& ex) {
isc_throw(InitializationError, "Botan error: " << ex.what());
}
}
+ if (!c.rng_) {
+ try {
+ c.rng_.reset(new RNGImpl());
+ } catch (const Botan::Exception& ex) {
+ isc_throw(InitializationError, "Botan error: " << ex.what());
+ }
+ }
}
std::string
diff --git a/src/lib/cryptolink/botan_link.cc b/src/lib/cryptolink/botan_link.cc
index c7f40cb182..714663d507 100644
--- a/src/lib/cryptolink/botan_link.cc
+++ b/src/lib/cryptolink/botan_link.cc
@@ -9,9 +9,11 @@
#include <cryptolink/cryptolink.h>
#include <cryptolink/crypto_hash.h>
#include <cryptolink/crypto_hmac.h>
+#include <cryptolink/crypto_rng.h>
#include <botan/exceptn.h>
#include <botan/version.h>
+#include <botan/auto_rng.h>
namespace isc {
namespace cryptolink {
@@ -25,16 +27,53 @@ CryptoLink::~CryptoLink() {
delete impl_;
}
+/// \brief Botan implementation of RNG.
+class RNGImpl : public RNG {
+public:
+ RNGImpl() {
+ rng.reset(new Botan::AutoSeeded_RNG());
+ }
+
+ ~RNGImpl() {
+ }
+
+private:
+ std::vector<uint8_t> random(size_t len) {
+ std::vector<uint8_t> data;
+ if (len > 0) {
+ data.resize(len);
+ try {
+ rng->randomize(&data[0], len);
+ } catch (const Botan::Exception& ex) {
+ isc_throw(isc::cryptolink::LibraryError,
+ "Botan error: " << ex.what());
+ }
+ }
+ return (data);
+ }
+
+ boost::shared_ptr<Botan::RandomNumberGenerator> rng;
+};
+
void
CryptoLink::initialize() {
CryptoLink& c = getCryptoLinkInternal();
- if (c.impl_ == NULL) {
+ if (!c.impl_) {
try {
c.impl_ = new CryptoLinkImpl();
} catch (const Botan::Exception& ex) {
isc_throw(InitializationError, "Botan error: " << ex.what());
}
}
+ if (!c.rng_) {
+ try {
+ c.rng_.reset(new RNGImpl());
+ } catch (const Botan::Exception& ex) {
+ isc_throw(InitializationError, "Botan error: " << ex.what());
+ }
+ }
+ // A not yet fixed bug makes RNG to be destroyed after memory pool...
+ atexit([]{ getCryptoLink().getRNG().reset(); });
}
std::string
diff --git a/src/lib/cryptolink/crypto_rng.cc b/src/lib/cryptolink/crypto_rng.cc
new file mode 100644
index 0000000000..54dacce408
--- /dev/null
+++ b/src/lib/cryptolink/crypto_rng.cc
@@ -0,0 +1,33 @@
+// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <cryptolink.h>
+#include <cryptolink/crypto_rng.h>
+
+#include <boost/scoped_ptr.hpp>
+
+#include <cstring>
+
+namespace isc {
+namespace cryptolink {
+
+RNG::RNG() {
+}
+
+RNG::~RNG() {
+}
+
+std::vector<uint8_t>
+random(size_t len)
+{
+ RNGPtr rng(CryptoLink::getCryptoLink().getRNG());
+ return (rng->random(len));
+}
+
+} // namespace cryptolink
+} // namespace isc
diff --git a/src/lib/cryptolink/crypto_rng.h b/src/lib/cryptolink/crypto_rng.h
new file mode 100644
index 0000000000..916321e7ca
--- /dev/null
+++ b/src/lib/cryptolink/crypto_rng.h
@@ -0,0 +1,64 @@
+// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <boost/noncopyable.hpp>
+
+#include <cryptolink/cryptolink.h>
+
+#ifndef ISC_CRYPTO_RNG_H
+#define ISC_CRYPTO_RNG_H
+
+namespace isc {
+namespace cryptolink {
+
+/// \brief RNG support
+///
+/// This class is used to get the RNG.
+/// The global instance can be get with CryptoLink::getRNG()
+///
+class RNG : private boost::noncopyable {
+public:
+ /// \brief Constructor from a Random Number Generator
+ ///
+ /// \exception LibraryError if there was any unexpected exception
+ /// in the underlying library
+ RNG();
+
+ /// \brief Destructor
+ virtual ~RNG();
+
+ /// \brief Generate random value.
+ ///
+ /// The result will be returned as a std::vector<uint8_t>
+ ///
+ /// \exception LibraryError if there was any unexpected exception
+ /// in the underlying library
+ ///
+ /// \param len The number of bytes from the result to generate.
+ /// \return a vector containing random value.
+ virtual std::vector<uint8_t> random(size_t len) = 0;
+
+private:
+ friend RNGPtr& CryptoLink::getRNG();
+};
+
+/// \brief Generate random value.
+///
+/// This is a convenience function that generate random data
+/// given a fixed amount of data. Internally it does the same as
+/// creating an RNG object and generating the resulting value.
+///
+/// \exception LibraryError if there was any unexpected exception
+/// in the underlying library
+///
+/// \param len The length of the data
+std::vector<uint8_t> random(size_t len);
+
+} // namespace cryptolink
+} // namespace isc
+
+#endif // ISC_CRYPTO_RNG_H
+
diff --git a/src/lib/cryptolink/cryptolink.cc b/src/lib/cryptolink/cryptolink.cc
index 3bae155ce5..a768ee206b 100644
--- a/src/lib/cryptolink/cryptolink.cc
+++ b/src/lib/cryptolink/cryptolink.cc
@@ -41,6 +41,11 @@ CryptoLink::createHMAC(const void* secret, size_t secret_len,
return (new HMAC(secret, secret_len, hash_algorithm));
}
+RNGPtr&
+CryptoLink::getRNG() {
+ return (rng_);
+}
+
} // namespace cryptolink
} // namespace isc
diff --git a/src/lib/cryptolink/cryptolink.h b/src/lib/cryptolink/cryptolink.h
index 1856b34137..b3e357835d 100644
--- a/src/lib/cryptolink/cryptolink.h
+++ b/src/lib/cryptolink/cryptolink.h
@@ -12,7 +12,7 @@
#include <exceptions/exceptions.h>
#include <boost/noncopyable.hpp>
-#include <boost/scoped_ptr.hpp>
+#include <boost/shared_ptr.hpp>
#include <memory>
@@ -42,6 +42,10 @@ class Hash;
// Forward declaration for createHMAC()
class HMAC;
+// Forward declaration for getRNG()
+class RNG;
+typedef boost::shared_ptr<RNG> RNGPtr;
+
/// General exception class that is the base for all crypto-related
/// exceptions
class CryptoLinkError : public Exception {
@@ -84,8 +88,9 @@ public:
CryptoLinkError(file, line, what) {}
};
-/// Forward declaration for pimpl
+/// Forward declarations for pimpl
class CryptoLinkImpl;
+class RNGImpl;
/// \brief Singleton entry point and factory class
///
@@ -209,6 +214,14 @@ public:
HMAC* createHMAC(const void* secret, size_t secret_len,
const HashAlgorithm hash_algorithm);
+ /// \brief Get the global RNG
+ ///
+ /// \exception NotImplemented if the method was not implemented
+ /// in a derived class
+ /// \exception LibraryError if there was any unexpected exception
+ /// in the underlying library
+ virtual RNGPtr& getRNG();
+
private:
// To enable us to use an optional explicit initialization call,
// the 'real' instance getter is private
@@ -220,6 +233,8 @@ private:
~CryptoLink();
CryptoLinkImpl* impl_;
+
+ RNGPtr rng_;
};
} // namespace cryptolink
diff --git a/src/lib/cryptolink/openssl_link.cc b/src/lib/cryptolink/openssl_link.cc
index dac6ee4fd1..1a573f7c41 100644
--- a/src/lib/cryptolink/openssl_link.cc
+++ b/src/lib/cryptolink/openssl_link.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014-2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -7,27 +7,49 @@
#include <config.h>
#include <cryptolink/cryptolink.h>
+#include <cryptolink/crypto_rng.h>
#include <cryptolink/crypto_hash.h>
#include <cryptolink/crypto_hmac.h>
#include <openssl/crypto.h>
+#include <openssl/rand.h>
namespace isc {
namespace cryptolink {
// For OpenSSL, we use the CryptoLink class object in RAII style
class CryptoLinkImpl {
- // empty class
};
CryptoLink::~CryptoLink() {
delete impl_;
}
+/// \brief OpenSSL implementation of RNG.
+class RNGImpl : public RNG {
+public:
+ RNGImpl() { }
+
+ ~RNGImpl() { }
+
+private:
+ std::vector<uint8_t> random(size_t len) {
+ std::vector<uint8_t> data;
+ if (len > 0) {
+ data.resize(len);
+ if (RAND_bytes(&data[0], len) != 1) {
+ isc_throw(isc::cryptolink::LibraryError,
+ "OpenSSL RAND_bytes() failed");
+ }
+ }
+ return (data);
+ }
+};
+
void
CryptoLink::initialize() {
CryptoLink& c = getCryptoLinkInternal();
- if (c.impl_ == NULL) {
+ if (!c.impl_) {
try {
c.impl_ = new CryptoLinkImpl();
} catch (const std::exception &ex) {
@@ -40,6 +62,19 @@ CryptoLink::initialize() {
"Error during OpenSSL initialization");
}
}
+ if (!c.rng_) {
+ try {
+ c.rng_.reset(new RNGImpl());
+ } catch (const std::exception &ex) {
+ // Should never happen
+ isc_throw(InitializationError,
+ "Error during OpenSSL RNG initialization:" << ex.what());
+ } catch (...) {
+ // Should never happen
+ isc_throw(InitializationError,
+ "Error during OpenSSL RNG initialization");
+ }
+ }
}
std::string
@@ -49,4 +84,3 @@ CryptoLink::getVersion() {
} // namespace cryptolink
} // namespace isc
-
diff --git a/src/lib/cryptolink/tests/crypto_unittests.cc b/src/lib/cryptolink/tests/crypto_unittests.cc
index d512ecaa5a..39dc207400 100644
--- a/src/lib/cryptolink/tests/crypto_unittests.cc
+++ b/src/lib/cryptolink/tests/crypto_unittests.cc
@@ -11,7 +11,9 @@
#include <util/encode/hex.h>
#include <cryptolink/cryptolink.h>
+#include <cryptolink/crypto_rng.h>
+using namespace std;
using namespace isc::cryptolink;
// Test get version
@@ -25,3 +27,29 @@ TEST(CryptoLinkTest, Singleton) {
const CryptoLink& c2 = CryptoLink::getCryptoLink();
ASSERT_EQ(&c1, &c2);
}
+
+// Tests whether getRNG() returns a global value
+TEST(CryptoLinkTest, GlobalRNG) {
+ CryptoLink& c = CryptoLink::getCryptoLink();
+ RNGPtr rng1 = c.getRNG();
+ RNGPtr rng2 = c.getRNG();
+ ASSERT_EQ(rng1, rng2);
+}
+
+// Tests whether RNG works
+TEST(CryptoLinkTest, RNG) {
+ RNGPtr rng = CryptoLink::getCryptoLink().getRNG();
+ vector<uint8_t> data;
+ ASSERT_NO_THROW(data = rng->random(16));
+ ASSERT_EQ(16, data.size());
+ vector<uint8_t> zero;
+ zero.resize(16);
+ EXPECT_NE(0, memcmp(&zero[0], &data[0], zero.size()));
+
+ // Retry with the function (vs method)
+ vector<uint8_t> dataf;
+ ASSERT_NO_THROW(dataf = random(16));
+ ASSERT_EQ(16, dataf.size());
+ EXPECT_NE(0, memcmp(&zero[0], &dataf[0], zero.size()));
+ EXPECT_NE(0, memcmp(&data[0], &dataf[0], zero.size()));
+}