+857. [func] fdupont
+ Improve the cryptolink code, for instance use a constant
+ time comparison.
+ (Trac #3602, git ...)
+
856. [build] marcinw
callout_manager.h and server_hooks.h headers are now exported,
so statically linked libraries can be tested.
namespace isc {
namespace cryptolink {
+namespace btn {
/// @brief Decode the HashAlgorithm enum into a name usable by Botan
///
/// @param algorithm algorithm to be converted
/// @return static text representation of the algorithm name
const char*
-getBotanHashAlgorithmName(isc::cryptolink::HashAlgorithm algorithm);
+getHashAlgorithmName(isc::cryptolink::HashAlgorithm algorithm);
+} // namespace btn
} // namespace cryptolink
} // namespace isc
/// @param algorithm algorithm to be converted
/// @return text representation of the algorithm name
const char*
-getBotanHashAlgorithmName(isc::cryptolink::HashAlgorithm algorithm) {
+btn::getHashAlgorithmName(HashAlgorithm algorithm) {
switch (algorithm) {
case isc::cryptolink::MD5:
return ("MD5");
explicit HashImpl(const HashAlgorithm hash_algorithm) {
Botan::HashFunction* hash;
try {
- hash = Botan::get_hash(
- getBotanHashAlgorithmName(hash_algorithm));
+ hash = Botan::get_hash(btn::getHashAlgorithmName(hash_algorithm));
} catch (const Botan::Algorithm_Not_Found&) {
isc_throw(isc::cryptolink::UnsupportedAlgorithm,
"Unknown hash algorithm: " <<
const HashAlgorithm hash_algorithm) {
Botan::HashFunction* hash;
try {
- hash = Botan::get_hash(
- getBotanHashAlgorithmName(hash_algorithm));
+ hash = Botan::get_hash(btn::getHashAlgorithmName(hash_algorithm));
} catch (const Botan::Algorithm_Not_Found&) {
isc_throw(isc::cryptolink::UnsupportedAlgorithm,
"Unknown hash algorithm: " <<
-// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011, 2014 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
/// and smaller than the output length of the algorithm,
/// only len bytes will be checked
/// \return true if the signature is correct, false otherwise
+ ///
+ /// \note verify() does not destroy its context so it can be
+ /// called multiple times with different signatures.
bool verify(const void* sig, size_t len);
private:
namespace isc {
namespace cryptolink {
+namespace ossl {
/// @brief Decode the HashAlgorithm enum into an EVP_MD pointer (or 0)
///
/// @param algorithm algorithm to be converted
/// @return pointer to a static EVP_MD which identifies the algorithm
const EVP_MD*
-getOpenSSLHashAlgorithm(isc::cryptolink::HashAlgorithm algorithm);
+getHashAlgorithm(isc::cryptolink::HashAlgorithm algorithm);
+/// Secure Buffers which are wiped out when released.
+/// Subset of the std::vector interface but not derived from
+/// to avoid unwanted inheritance.
+template<typename T>
+class SecBuf {
+public:
+ typedef typename std::vector<T>::iterator iterator;
+
+ typedef typename std::vector<T>::const_iterator const_iterator;
+
+ explicit SecBuf() : vec_(std::vector<T>()) {}
+
+ explicit SecBuf(size_t n, const T& value = T()) :
+ vec_(std::vector<T>(n, value))
+ {}
+
+ SecBuf(iterator first, iterator last) :
+ vec_(std::vector<T>(first, last))
+ {}
+
+ SecBuf(const_iterator first, const_iterator last) :
+ vec_(std::vector<T>(first, last))
+ {}
+
+ SecBuf(const std::vector<T>& x) : vec_(x) {}
+
+ ~SecBuf() {
+ std::memset(&vec_[0], 0, vec_.capacity() * sizeof(T));
+ };
+
+ iterator begin() {
+ return (vec_.begin());
+ };
+
+ const_iterator begin() const {
+ return (vec_.begin());
+ };
+
+ iterator end() {
+ return (vec_.end());
+ };
+
+ const_iterator end() const {
+ return (vec_.end());
+ };
+
+ size_t size() const {
+ return (vec_.size());
+ };
+
+ void resize(size_t sz) {
+ vec_.resize(sz);
+ };
+
+ SecBuf& operator=(const SecBuf& x) {
+ if (&x != *this) {
+ vec_ = x.vec_;
+ }
+ return (*this);
+ };
+
+ T& operator[](size_t n) {
+ return (vec_[n]);
+ };
+
+ const T& operator[](size_t n) const {
+ return (vec_[n]);
+ };
+
+ // constant time comparison against timing attacks
+ // (same type than XXX::verify() so const void* (vs. const T*) x)
+ bool same(const void* x, size_t len) const {
+ bool ret = true;
+ const T* p = static_cast<const T*>(x);
+ for (size_t i = 0; i < len; ++i)
+ ret = ret && (vec_[i] == p[i]);
+ return ret;
+ };
+
+private:
+ std::vector<T> vec_;
+};
+
+} // namespace ossl
} // namespace cryptolink
} // namespace isc
/// @param algorithm algorithm to be converted
/// @return pointer to EVP_MD which identifies the algorithm
const EVP_MD*
-getOpenSSLHashAlgorithm(isc::cryptolink::HashAlgorithm algorithm) {
+ossl::getHashAlgorithm(HashAlgorithm algorithm) {
switch (algorithm) {
case isc::cryptolink::MD5:
return (EVP_md5());
///
/// @param hash_algorithm The hash algorithm
explicit HashImpl(const HashAlgorithm hash_algorithm) {
- const EVP_MD* algo = getOpenSSLHashAlgorithm(hash_algorithm);
+ const EVP_MD* algo = ossl::getHashAlgorithm(hash_algorithm);
if (algo == 0) {
isc_throw(isc::cryptolink::UnsupportedAlgorithm,
"Unknown hash algorithm: " <<
#include <cstring>
-namespace {
-
-/// Secure Buffers which are wiped out when released.
-template<typename T>
-struct SecBuf {
-public:
- typedef typename std::vector<T>::iterator iterator;
-
- typedef typename std::vector<T>::const_iterator const_iterator;
-
- explicit SecBuf() : vec_(std::vector<T>()) {}
-
- explicit SecBuf(size_t n, const T& value = T()) :
- vec_(std::vector<T>(n, value))
- {}
-
- SecBuf(iterator first, iterator last) :
- vec_(std::vector<T>(first, last))
- {}
-
- SecBuf(const_iterator first, const_iterator last) :
- vec_(std::vector<T>(first, last))
- {}
-
- SecBuf(const std::vector<T>& x) : vec_(x) {}
-
- ~SecBuf() {
- std::memset(&vec_[0], 0, vec_.capacity() * sizeof(T));
- };
-
- iterator begin() {
- return (vec_.begin());
- };
-
- const_iterator begin() const {
- return (vec_.begin());
- };
-
- iterator end() {
- return (vec_.end());
- };
-
- const_iterator end() const {
- return (vec_.end());
- };
-
- size_t size() const {
- return (vec_.size());
- };
-
- void resize(size_t sz) {
- vec_.resize(sz);
- };
-
- SecBuf& operator=(const SecBuf& x) {
- if (&x != *this) {
- vec_ = x.vec_;
- }
- return (*this);
- };
-
- T& operator[](size_t n) {
- return (vec_[n]);
- };
-
- const T& operator[](size_t n) const {
- return (vec_[n]);
- };
-
-private:
- std::vector<T> vec_;
-};
-
-} // local namespace
-
namespace isc {
namespace cryptolink {
/// @param hash_algorithm The hash algorithm
explicit HMACImpl(const void* secret, size_t secret_len,
const HashAlgorithm hash_algorithm) {
- const EVP_MD* algo = getOpenSSLHashAlgorithm(hash_algorithm);
+ const EVP_MD* algo = ossl::getHashAlgorithm(hash_algorithm);
if (algo == 0) {
isc_throw(UnsupportedAlgorithm,
"Unknown hash algorithm: " <<
/// See @ref isc::cryptolink::HMAC::sign() for details.
void sign(isc::util::OutputBuffer& result, size_t len) {
size_t size = getOutputLength();
- SecBuf<unsigned char> digest(size);
+ ossl::SecBuf<unsigned char> digest(size);
HMAC_Final(md_.get(), &digest[0], NULL);
if (len == 0 || len > size) {
len = size;
/// See @ref isc::cryptolink::HMAC::sign() for details.
void sign(void* result, size_t len) {
size_t size = getOutputLength();
- SecBuf<unsigned char> digest(size);
+ ossl::SecBuf<unsigned char> digest(size);
HMAC_Final(md_.get(), &digest[0], NULL);
if (len > size) {
len = size;
/// See @ref isc::cryptolink::HMAC::sign() for details.
std::vector<uint8_t> sign(size_t len) {
size_t size = getOutputLength();
- SecBuf<unsigned char> digest(size);
+ ossl::SecBuf<unsigned char> digest(size);
HMAC_Final(md_.get(), &digest[0], NULL);
if (len != 0 && len < size) {
digest.resize(len);
if (len != 0 && (len < 10 || len < size / 2)) {
return (false);
}
- SecBuf<unsigned char> digest(size);
+ ossl::SecBuf<unsigned char> digest(size);
HMAC_Final(md_.get(), &digest[0], NULL);
if (len == 0 || len > size) {
len = size;
}
- return (std::memcmp(&digest[0], sig, len) == 0);
+ return (digest.same(sig, len));
}
private: