One MessageDigestImpl.h to rule them all.

pull/128/merge
Nils Maier 2013-09-20 07:54:30 +02:00
parent a4e29303ef
commit fa30fe4b15
12 changed files with 329 additions and 687 deletions

View File

@ -32,15 +32,13 @@
* files in the program, then also delete it here. * files in the program, then also delete it here.
*/ */
/* copyright --> */ /* copyright --> */
#include "AppleMessageDigestImpl.h"
#include "MessageDigestImpl.h"
#include <CommonCrypto/CommonDigest.h> #include <CommonCrypto/CommonDigest.h>
#include "array_fun.h"
#include "a2functional.h"
#include "HashFuncEntry.h"
namespace aria2 { namespace aria2 {
namespace {
template<size_t dlen, template<size_t dlen,
typename ctx_t, typename ctx_t,
@ -52,6 +50,9 @@ public:
MessageDigestBase() { reset(); } MessageDigestBase() { reset(); }
virtual ~MessageDigestBase() {} virtual ~MessageDigestBase() {}
static size_t length() {
return dlen;
}
virtual size_t getDigestLength() const CXX11_OVERRIDE { virtual size_t getDigestLength() const CXX11_OVERRIDE {
return dlen; return dlen;
} }
@ -111,49 +112,20 @@ typedef MessageDigestBase<CC_SHA512_DIGEST_LENGTH,
CC_SHA512_Final> CC_SHA512_Final>
MessageDigestSHA512; MessageDigestSHA512;
} // namespace
std::unique_ptr<MessageDigestImpl> MessageDigestImpl::sha1() std::unique_ptr<MessageDigestImpl> MessageDigestImpl::sha1()
{ {
return std::unique_ptr<MessageDigestImpl>(new MessageDigestSHA1()); return std::unique_ptr<MessageDigestImpl>(new MessageDigestSHA1());
} }
std::unique_ptr<MessageDigestImpl> MessageDigestImpl::create MessageDigestImpl::hashes_t MessageDigestImpl::hashes = {
(const std::string& hashType) { "sha-1", make_hi<MessageDigestSHA1>() },
{ { "sha-224", make_hi<MessageDigestSHA224>() },
if (hashType == "sha-1") { { "sha-256", make_hi<MessageDigestSHA256>() },
return make_unique<MessageDigestSHA1>(); { "sha-384", make_hi<MessageDigestSHA384>() },
} { "sha-512", make_hi<MessageDigestSHA512>() },
if (hashType == "sha-224") { { "md5", make_hi<MessageDigestMD5>() },
return make_unique<MessageDigestSHA224>(); };
}
if (hashType == "sha-256") {
return make_unique<MessageDigestSHA256>();
}
if (hashType == "sha-384") {
return make_unique<MessageDigestSHA384>();
}
if (hashType == "sha-512") {
return make_unique<MessageDigestSHA512>();
}
if (hashType == "md5") {
return make_unique<MessageDigestMD5>();
}
return nullptr;
}
bool MessageDigestImpl::supports(const std::string& hashType)
{
return hashType == "sha-1" || hashType == "sha-224" ||
hashType == "sha-256" || hashType == "sha-384" ||
hashType == "sha-512" || hashType == "md5";
}
size_t MessageDigestImpl::getDigestLength(const std::string& hashType)
{
std::unique_ptr<MessageDigestImpl> impl = create(hashType);
if (!impl) {
return 0;
}
return impl->getDigestLength();
}
} // namespace aria2 } // namespace aria2

View File

@ -1,71 +0,0 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2013 Nils Maier
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#ifndef D_APPLE_MESSAGE_DIGEST_IMPL_H
#define D_APPLE_MESSAGE_DIGEST_IMPL_H
#include "common.h"
#include <string>
#include <memory>
namespace aria2 {
class MessageDigestImpl {
public:
virtual ~MessageDigestImpl() {}
static std::unique_ptr<MessageDigestImpl> sha1();
static std::unique_ptr<MessageDigestImpl> create(const std::string& hashType);
static bool supports(const std::string& hashType);
static size_t getDigestLength(const std::string& hashType);
public:
virtual size_t getDigestLength() const = 0;
virtual void reset() = 0;
virtual void update(const void* data, size_t length) = 0;
virtual void digest(unsigned char* md) = 0;
protected:
MessageDigestImpl() {}
private:
MessageDigestImpl(const MessageDigestImpl&);
MessageDigestImpl& operator=(const MessageDigestImpl&);
};
} // namespace aria2
#endif // D_APPLE_MESSAGE_DIGEST_IMPL_H

View File

@ -2,7 +2,7 @@
/* /*
* aria2 - The high speed download utility * aria2 - The high speed download utility
* *
* Copyright (C) 2010 Tatsuhiro Tsujikawa * Copyright (C) 2013 Nils Maier
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -32,84 +32,81 @@
* files in the program, then also delete it here. * files in the program, then also delete it here.
*/ */
/* copyright --> */ /* copyright --> */
#include "LibgcryptMessageDigestImpl.h"
#include <algorithm> #include "MessageDigestImpl.h"
#include "array_fun.h" #include <gcrypt.h>
#include "HashFuncEntry.h"
#include "a2functional.h"
namespace aria2 { namespace aria2 {
MessageDigestImpl::MessageDigestImpl(int hashFunc) : hashFunc_{hashFunc} namespace {
{ template<int hash>
gcry_md_open(&ctx_, hashFunc_, 0); class MessageDigestBase : public MessageDigestImpl {
} private:
struct Deleter {
void operator()(gcry_md_hd_t ctx) {
if (ctx) {
gcry_md_close(ctx);
}
}
};
MessageDigestImpl::~MessageDigestImpl() public:
{ MessageDigestBase() {
gcry_md_close(ctx_); gcry_md_hd_t ctx = nullptr;
} gcry_md_open(&ctx, hash, 0);
ctx_.reset(ctx);
reset();
}
virtual ~MessageDigestBase() {}
static size_t length() {
return ::gcry_md_get_algo_dlen(hash);
}
virtual size_t getDigestLength() const CXX11_OVERRIDE {
return ::gcry_md_get_algo_dlen(hash);
}
virtual void reset() CXX11_OVERRIDE {
::gcry_md_reset(ctx_.get());
}
virtual void update(const void* data, size_t length) CXX11_OVERRIDE {
auto bytes = reinterpret_cast<const uint8_t*>(data);
while (length) {
size_t l = std::min(length, (size_t)std::numeric_limits<uint32_t>::max());
gcry_md_write(ctx_.get(), bytes, length);
length -= l;
bytes += l;
}
}
virtual void digest(unsigned char* md) CXX11_OVERRIDE {
::memcpy(md, gcry_md_read(ctx_.get(), 0), getDigestLength());
}
private:
std::unique_ptr<std::remove_pointer<gcry_md_hd_t>::type, Deleter> ctx_;
size_t len_;
};
typedef MessageDigestBase<GCRY_MD_MD5> MessageDigestMD5;
typedef MessageDigestBase<GCRY_MD_SHA1> MessageDigestSHA1;
typedef MessageDigestBase<GCRY_MD_SHA224> MessageDigestSHA224;
typedef MessageDigestBase<GCRY_MD_SHA256> MessageDigestSHA256;
typedef MessageDigestBase<GCRY_MD_SHA384> MessageDigestSHA384;
typedef MessageDigestBase<GCRY_MD_SHA512> MessageDigestSHA512;
} // namespace
std::unique_ptr<MessageDigestImpl> MessageDigestImpl::sha1() std::unique_ptr<MessageDigestImpl> MessageDigestImpl::sha1()
{ {
return make_unique<MessageDigestImpl>(GCRY_MD_SHA1); return std::unique_ptr<MessageDigestImpl>(new MessageDigestSHA1());
} }
typedef HashFuncEntry<int> CHashFuncEntry; MessageDigestImpl::hashes_t MessageDigestImpl::hashes = {
typedef FindHashFunc<int> CFindHashFunc; { "sha-1", make_hi<MessageDigestSHA1>() },
{ "sha-224", make_hi<MessageDigestSHA224>() },
namespace { { "sha-256", make_hi<MessageDigestSHA256>() },
CHashFuncEntry hashFuncs[] = { { "sha-384", make_hi<MessageDigestSHA384>() },
CHashFuncEntry("sha-1", GCRY_MD_SHA1), { "sha-512", make_hi<MessageDigestSHA512>() },
CHashFuncEntry("sha-224", GCRY_MD_SHA224), { "md5", make_hi<MessageDigestMD5>() },
CHashFuncEntry("sha-256", GCRY_MD_SHA256),
CHashFuncEntry("sha-384", GCRY_MD_SHA384),
CHashFuncEntry("sha-512", GCRY_MD_SHA512),
CHashFuncEntry("md5", GCRY_MD_MD5)
}; };
} // namespace
std::unique_ptr<MessageDigestImpl> MessageDigestImpl::create
(const std::string& hashType)
{
int hashFunc = getHashFunc(std::begin(hashFuncs), std::end(hashFuncs),
hashType);
return make_unique<MessageDigestImpl>(hashFunc);
}
bool MessageDigestImpl::supports(const std::string& hashType)
{
return std::end(hashFuncs) != std::find_if(std::begin(hashFuncs),
std::end(hashFuncs),
CFindHashFunc(hashType));
}
size_t MessageDigestImpl::getDigestLength(const std::string& hashType)
{
int hashFunc = getHashFunc(std::begin(hashFuncs), std::end(hashFuncs),
hashType);
return gcry_md_get_algo_dlen(hashFunc);
}
size_t MessageDigestImpl::getDigestLength() const
{
return gcry_md_get_algo_dlen(hashFunc_);
}
void MessageDigestImpl::reset()
{
gcry_md_reset(ctx_);
}
void MessageDigestImpl::update(const void* data, size_t length)
{
gcry_md_write(ctx_, data, length);
}
void MessageDigestImpl::digest(unsigned char* md)
{
memcpy(md, gcry_md_read(ctx_, 0), gcry_md_get_algo_dlen(hashFunc_));
}
} // namespace aria2 } // namespace aria2

View File

@ -1,75 +0,0 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2010 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#ifndef D_LIBGCRYPT_MESSAGE_DIGEST_IMPL_H
#define D_LIBGCRYPT_MESSAGE_DIGEST_IMPL_H
#include "common.h"
#include <string>
#include <memory>
#include <gcrypt.h>
namespace aria2 {
class MessageDigestImpl {
public:
MessageDigestImpl(int hashFunc);
// We don't implement copy ctor.
MessageDigestImpl(const MessageDigestImpl&) = delete;
// We don't implement assignment operator.
MessageDigestImpl& operator==(const MessageDigestImpl&) = delete;
~MessageDigestImpl();
static std::unique_ptr<MessageDigestImpl> sha1();
static std::unique_ptr<MessageDigestImpl> create
(const std::string& hashType);
static bool supports(const std::string& hashType);
static size_t getDigestLength(const std::string& hashType);
size_t getDigestLength() const;
void reset();
void update(const void* data, size_t length);
void digest(unsigned char* md);
private:
int hashFunc_;
gcry_md_hd_t ctx_;
};
} // namespace aria2
#endif // D_LIBGCRYPT_MESSAGE_DIGEST_IMPL_H

View File

@ -2,7 +2,7 @@
/* /*
* aria2 - The high speed download utility * aria2 - The high speed download utility
* *
* Copyright (C) 2011 Tatsuhiro Tsujikawa * Copyright (C) 2013 Nils Maier
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -32,86 +32,69 @@
* files in the program, then also delete it here. * files in the program, then also delete it here.
*/ */
/* copyright --> */ /* copyright --> */
#include "LibnettleMessageDigestImpl.h"
#include <algorithm> #include "MessageDigestImpl.h"
#include "array_fun.h" #include <nettle/nettle-meta.h>
#include "HashFuncEntry.h"
#include "a2functional.h"
namespace aria2 { namespace aria2 {
MessageDigestImpl::MessageDigestImpl(const nettle_hash* hashInfo) namespace {
: hashInfo_{hashInfo}, template<const nettle_hash* hash>
ctx_{new char[hashInfo->context_size]} class MessageDigestBase : public MessageDigestImpl {
{ public:
reset(); MessageDigestBase() : ctx_(new char[hash->context_size]) {
} reset();
}
virtual ~MessageDigestBase() {}
MessageDigestImpl::~MessageDigestImpl() static size_t length() {
{ return hash->digest_size;
delete [] ctx_; }
} virtual size_t getDigestLength() const CXX11_OVERRIDE {
return hash->digest_size;
}
virtual void reset() CXX11_OVERRIDE {
hash->init(ctx_.get());
}
virtual void update(const void* data, size_t length) CXX11_OVERRIDE {
auto bytes = reinterpret_cast<const uint8_t*>(data);
while (length) {
size_t l = std::min(length, (size_t)std::numeric_limits<uint32_t>::max());
hash->update(ctx_.get(), l, bytes);
length -= l;
bytes += l;
}
}
virtual void digest(unsigned char* md) CXX11_OVERRIDE {
hash->digest(ctx_.get(), getDigestLength(), md);
}
private:
std::unique_ptr<char[]> ctx_;
size_t len_;
};
typedef MessageDigestBase<&nettle_md5> MessageDigestMD5;
typedef MessageDigestBase<&nettle_sha1> MessageDigestSHA1;
typedef MessageDigestBase<&nettle_sha224> MessageDigestSHA224;
typedef MessageDigestBase<&nettle_sha256> MessageDigestSHA256;
typedef MessageDigestBase<&nettle_sha384> MessageDigestSHA384;
typedef MessageDigestBase<&nettle_sha512> MessageDigestSHA512;
} // namespace
std::unique_ptr<MessageDigestImpl> MessageDigestImpl::sha1() std::unique_ptr<MessageDigestImpl> MessageDigestImpl::sha1()
{ {
return make_unique<MessageDigestImpl>(&nettle_sha1); return std::unique_ptr<MessageDigestImpl>(new MessageDigestSHA1());
} }
typedef HashFuncEntry<const nettle_hash*> CHashFuncEntry; MessageDigestImpl::hashes_t MessageDigestImpl::hashes = {
typedef FindHashFunc<const nettle_hash*> CFindHashFunc; { "sha-1", make_hi<MessageDigestSHA1>() },
{ "sha-224", make_hi<MessageDigestSHA224>() },
namespace { { "sha-256", make_hi<MessageDigestSHA256>() },
CHashFuncEntry hashFuncs[] = { { "sha-384", make_hi<MessageDigestSHA384>() },
CHashFuncEntry("sha-1", &nettle_sha1), { "sha-512", make_hi<MessageDigestSHA512>() },
CHashFuncEntry("sha-224", &nettle_sha224), { "md5", make_hi<MessageDigestMD5>() },
CHashFuncEntry("sha-256", &nettle_sha256),
CHashFuncEntry("sha-384", &nettle_sha384),
CHashFuncEntry("sha-512", &nettle_sha512),
CHashFuncEntry("md5", &nettle_md5)
}; };
} // namespace
std::unique_ptr<MessageDigestImpl> MessageDigestImpl::create
(const std::string& hashType)
{
auto hashInfo =
getHashFunc(std::begin(hashFuncs), std::end(hashFuncs), hashType);
return make_unique<MessageDigestImpl>(hashInfo);
}
bool MessageDigestImpl::supports(const std::string& hashType)
{
return std::end(hashFuncs) != std::find_if(std::begin(hashFuncs),
std::end(hashFuncs),
CFindHashFunc(hashType));
}
size_t MessageDigestImpl::getDigestLength(const std::string& hashType)
{
auto hashInfo =
getHashFunc(std::begin(hashFuncs), std::end(hashFuncs), hashType);
return hashInfo->digest_size;
}
size_t MessageDigestImpl::getDigestLength() const
{
return hashInfo_->digest_size;
}
void MessageDigestImpl::reset()
{
hashInfo_->init(ctx_);
}
void MessageDigestImpl::update(const void* data, size_t length)
{
hashInfo_->update(ctx_, length, static_cast<const uint8_t*>(data));
}
void MessageDigestImpl::digest(unsigned char* md)
{
hashInfo_->digest(ctx_, getDigestLength(), md);
}
} // namespace aria2 } // namespace aria2

View File

@ -1,75 +0,0 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2011 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#ifndef D_LIBNETTLE_MESSAGE_DIGEST_IMPL_H
#define D_LIBNETTLE_MESSAGE_DIGEST_IMPL_H
#include "common.h"
#include <string>
#include <memory>
#include <nettle/nettle-meta.h>
namespace aria2 {
class MessageDigestImpl {
public:
MessageDigestImpl(const nettle_hash* hashInfo);
// We don't implement copy ctor.
MessageDigestImpl(const MessageDigestImpl&) = delete;
// We don't implement assignment operator.
MessageDigestImpl& operator==(const MessageDigestImpl&) = delete;
~MessageDigestImpl();
static std::unique_ptr<MessageDigestImpl> sha1();
static std::unique_ptr<MessageDigestImpl> create
(const std::string& hashType);
static bool supports(const std::string& hashType);
static size_t getDigestLength(const std::string& hashType);
size_t getDigestLength() const;
void reset();
void update(const void* data, size_t length);
void digest(unsigned char* md);
private:
const nettle_hash* hashInfo_;
char* ctx_;
};
} // namespace aria2
#endif // D_LIBNETTLE_MESSAGE_DIGEST_IMPL_H

View File

@ -2,7 +2,7 @@
/* /*
* aria2 - The high speed download utility * aria2 - The high speed download utility
* *
* Copyright (C) 2010 Tatsuhiro Tsujikawa * Copyright (C) 2013 Nils Maier
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -32,95 +32,76 @@
* files in the program, then also delete it here. * files in the program, then also delete it here.
*/ */
/* copyright --> */ /* copyright --> */
#include "LibsslMessageDigestImpl.h"
#include <algorithm> #include "MessageDigestImpl.h"
#include "array_fun.h" #include <openssl/evp.h>
#include "HashFuncEntry.h"
#include "a2functional.h"
namespace aria2 { namespace aria2 {
MessageDigestImpl::MessageDigestImpl(const EVP_MD* hashFunc) template<const EVP_MD* (*init_fn)()>
: hashFunc_{hashFunc} class MessageDigestBase : public MessageDigestImpl {
{ public:
EVP_MD_CTX_init(&ctx_); MessageDigestBase() : md_(init_fn()), len_(EVP_MD_size(md_)) {
reset(); EVP_MD_CTX_init(&ctx_);
} reset();
}
virtual ~MessageDigestBase() {
EVP_MD_CTX_cleanup(&ctx_);
}
MessageDigestImpl::~MessageDigestImpl() static size_t length() {
{ return EVP_MD_size(init_fn());
EVP_MD_CTX_cleanup(&ctx_); }
} virtual size_t getDigestLength() const CXX11_OVERRIDE {
return len_;
}
virtual void reset() CXX11_OVERRIDE {
EVP_DigestInit_ex(&ctx_, md_, 0);
}
virtual void update(const void* data, size_t length) CXX11_OVERRIDE {
auto bytes = reinterpret_cast<const char*>(data);
while (length) {
size_t l = std::min(length, (size_t)std::numeric_limits<uint32_t>::max());
EVP_DigestUpdate(&ctx_, bytes, l);
length -= l;
bytes += l;
}
}
virtual void digest(unsigned char* md) CXX11_OVERRIDE {
unsigned int len;
EVP_DigestFinal_ex(&ctx_, md, &len);
}
private:
EVP_MD_CTX ctx_;
const EVP_MD* md_;
const size_t len_;
};
typedef MessageDigestBase<EVP_md5> MessageDigestMD5;
typedef MessageDigestBase<EVP_sha1> MessageDigestSHA1;
std::unique_ptr<MessageDigestImpl> MessageDigestImpl::sha1() std::unique_ptr<MessageDigestImpl> MessageDigestImpl::sha1()
{ {
return make_unique<MessageDigestImpl>(EVP_sha1()); return std::unique_ptr<MessageDigestImpl>(new MessageDigestSHA1());
} }
typedef HashFuncEntry<const EVP_MD*> CHashFuncEntry; MessageDigestImpl::hashes_t MessageDigestImpl::hashes = {
typedef FindHashFunc<const EVP_MD*> CFindHashFunc; { "sha-1", make_hi<MessageDigestSHA1>() },
namespace {
CHashFuncEntry hashFuncs[] = {
CHashFuncEntry("sha-1", EVP_sha1()),
#ifdef HAVE_EVP_SHA224 #ifdef HAVE_EVP_SHA224
CHashFuncEntry("sha-224", EVP_sha224()), { "sha-224", make_hi<MessageDigestBase<EVP_sha224> >() },
#endif // HAVE_EVP_SHA224 #endif
#ifdef HAVE_EVP_SHA256 #ifdef HAVE_EVP_SHA224
CHashFuncEntry("sha-256", EVP_sha256()), { "sha-256", make_hi<MessageDigestBase<EVP_sha256> >() },
#endif // HAVE_EVP_SHA256 #endif
#ifdef HAVE_EVP_SHA384 #ifdef HAVE_EVP_SHA224
CHashFuncEntry("sha-384", EVP_sha384()), { "sha-384", make_hi<MessageDigestBase<EVP_sha384> >() },
#endif // HAVE_EVP_SHA384 #endif
#ifdef HAVE_EVP_SHA512 #ifdef HAVE_EVP_SHA224
CHashFuncEntry("sha-512", EVP_sha512()), { "sha-512", make_hi<MessageDigestBase<EVP_sha512> >() },
#endif // HAVE_EVP_SHA512 #endif
CHashFuncEntry("md5", EVP_md5()) { "md5", make_hi<MessageDigestMD5>() },
}; };
} // namespace
std::unique_ptr<MessageDigestImpl> MessageDigestImpl::create
(const std::string& hashType)
{
auto hashFunc = getHashFunc(std::begin(hashFuncs), std::end(hashFuncs),
hashType);
return make_unique<MessageDigestImpl>(hashFunc);
}
bool MessageDigestImpl::supports(const std::string& hashType)
{
return std::end(hashFuncs) != std::find_if(std::begin(hashFuncs),
std::end(hashFuncs),
CFindHashFunc(hashType));
}
size_t MessageDigestImpl::getDigestLength(const std::string& hashType)
{
auto hashFunc = getHashFunc(std::begin(hashFuncs), std::end(hashFuncs),
hashType);
return EVP_MD_size(hashFunc);
}
size_t MessageDigestImpl::getDigestLength() const
{
return EVP_MD_size(hashFunc_);
}
void MessageDigestImpl::reset()
{
EVP_DigestInit_ex(&ctx_, hashFunc_, 0);
}
void MessageDigestImpl::update(const void* data, size_t length)
{
EVP_DigestUpdate(&ctx_, data, length);
}
void MessageDigestImpl::digest(unsigned char* md)
{
unsigned int len;
EVP_DigestFinal_ex(&ctx_, md, &len);
}
} // namespace aria2 } // namespace aria2

View File

@ -1,75 +0,0 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2010 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#ifndef D_LIBSSL_MESSAGE_DIGEST_IMPL_H
#define D_LIBSSL_MESSAGE_DIGEST_IMPL_H
#include "common.h"
#include <string>
#include <memory>
#include <openssl/evp.h>
namespace aria2 {
class MessageDigestImpl {
public:
MessageDigestImpl(const EVP_MD* hashFunc);
// We don't implement copy ctor.
MessageDigestImpl(const MessageDigestImpl&) = delete;
// We don't implement assignment operator.
MessageDigestImpl& operator==(const MessageDigestImpl&) = delete;
~MessageDigestImpl();
static std::unique_ptr<MessageDigestImpl> sha1();
static std::unique_ptr<MessageDigestImpl> create
(const std::string& hashType);
static bool supports(const std::string& hashType);
static size_t getDigestLength(const std::string& hashType);
size_t getDigestLength() const;
void reset();
void update(const void* data, size_t length);
void digest(unsigned char* md);
private:
const EVP_MD* hashFunc_;
EVP_MD_CTX ctx_;
};
} // namespace aria2
#endif // D_LIBSSL_MESSAGE_DIGEST_IMPL_H

View File

@ -321,7 +321,7 @@ SRCS += TLSContext.h TLSSession.h
endif # ENABLE_SSL endif # ENABLE_SSL
if USE_APPLE_MD if USE_APPLE_MD
SRCS += AppleMessageDigestImpl.cc AppleMessageDigestImpl.h SRCS += AppleMessageDigestImpl.cc
endif # USE_APPLE_MD endif # USE_APPLE_MD
if HAVE_APPLETLS if HAVE_APPLETLS
@ -330,7 +330,7 @@ SRCS += AppleTLSContext.cc AppleTLSContext.h \
endif # HAVE_APPLETLS endif # HAVE_APPLETLS
if USE_WINDOWS_MD if USE_WINDOWS_MD
SRCS += WinMessageDigestImpl.cc WinMessageDigestImpl.h SRCS += WinMessageDigestImpl.cc
endif # USE_WINDOWS_MD endif # USE_WINDOWS_MD
if HAVE_LIBGNUTLS if HAVE_LIBGNUTLS
@ -342,14 +342,14 @@ if HAVE_LIBGCRYPT
SRCS += LibgcryptARC4Encryptor.cc LibgcryptARC4Encryptor.h \ SRCS += LibgcryptARC4Encryptor.cc LibgcryptARC4Encryptor.h \
LibgcryptDHKeyExchange.cc LibgcryptDHKeyExchange.h LibgcryptDHKeyExchange.cc LibgcryptDHKeyExchange.h
if USE_LIBGCRYPT_MD if USE_LIBGCRYPT_MD
SRCS += LibgcryptMessageDigestImpl.cc LibgcryptMessageDigestImpl.h SRCS += LibgcryptMessageDigestImpl.cc
endif # USE_LIBGCRYPT_MD endif # USE_LIBGCRYPT_MD
endif # HAVE_LIBGCRYPT endif # HAVE_LIBGCRYPT
if HAVE_LIBNETTLE if HAVE_LIBNETTLE
SRCS += LibnettleARC4Encryptor.cc LibnettleARC4Encryptor.h SRCS += LibnettleARC4Encryptor.cc LibnettleARC4Encryptor.h
if USE_LIBNETTLE_MD if USE_LIBNETTLE_MD
SRCS += LibnettleMessageDigestImpl.cc LibnettleMessageDigestImpl.h SRCS += LibnettleMessageDigestImpl.cc
endif # USE_LIBNETTLE_MD endif # USE_LIBNETTLE_MD
endif # HAVE_LIBNETTLE endif # HAVE_LIBNETTLE
@ -366,7 +366,7 @@ SRCS += LibsslTLSContext.cc LibsslTLSContext.h \
LibsslTLSSession.cc LibsslTLSSession.h LibsslTLSSession.cc LibsslTLSSession.h
endif # !HAVE_APPLETLS endif # !HAVE_APPLETLS
if USE_OPENSSL_MD if USE_OPENSSL_MD
SRCS += LibsslMessageDigestImpl.cc LibsslMessageDigestImpl.h SRCS += LibsslMessageDigestImpl.cc
endif endif
endif # HAVE_OPENSSL endif # HAVE_OPENSSL

View File

@ -2,7 +2,7 @@
/* /*
* aria2 - The high speed download utility * aria2 - The high speed download utility
* *
* Copyright (C) 2010 Tatsuhiro Tsujikawa * Copyright (C) 2013 Nils Maier
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -32,20 +32,79 @@
* files in the program, then also delete it here. * files in the program, then also delete it here.
*/ */
/* copyright --> */ /* copyright --> */
#ifndef D_MESSAGE_DIGEST_IMPL_H #ifndef D_MESSAGE_DIGEST_IMPL_H
#define D_MESSAGE_DIGEST_IMPL_H #define D_MESSAGE_DIGEST_IMPL_H
#include "common.h"
#ifdef USE_APPLE_MD #include <string>
# include "AppleMessageDigestImpl.h" #include <memory>
#elif defined(USE_WINDOWS_MD) #include <functional>
# include "WinMessageDigestImpl.h" #include <map>
#elif defined(USE_LIBNETTLE_MD) #include <tuple>
# include "LibnettleMessageDigestImpl.h"
#elif defined(USE_LIBGCRYPT_MD) #include "a2functional.h"
# include "LibgcryptMessageDigestImpl.h"
#elif defined(USE_OPENSSL_MD) namespace aria2 {
# include "LibsslMessageDigestImpl.h"
#endif class MessageDigestImpl {
public:
typedef std::function<std::unique_ptr<MessageDigestImpl>()> factory_t;
typedef std::tuple<factory_t, size_t> hash_info_t;
typedef std::map<std::string, hash_info_t> hashes_t;
template<typename T>
inline static hash_info_t make_hi() {
return std::make_tuple([]() { return make_unique<T>(); }, T::length());
}
private:
static hashes_t hashes;
MessageDigestImpl(const MessageDigestImpl&) = delete;
MessageDigestImpl& operator=(const MessageDigestImpl&) = delete;
public:
virtual ~MessageDigestImpl() {}
static std::unique_ptr<MessageDigestImpl> sha1();
inline static std::unique_ptr<MessageDigestImpl> create(
const std::string& hashType) {
auto i = hashes.find(hashType);
if (i == hashes.end()) {
return nullptr;
}
factory_t factory;
std::tie(factory, std::ignore) = i->second;
return factory();
}
inline static bool supports(const std::string& hashType) {
auto i = hashes.find(hashType);
return i != hashes.end();
}
inline static size_t getDigestLength(const std::string& hashType) {
auto i = hashes.find(hashType);
if (i == hashes.end()) {
return 0;
}
size_t len;
std::tie(std::ignore, len) = i->second;
return len;
}
public:
virtual size_t getDigestLength() const = 0;
virtual void reset() = 0;
virtual void update(const void* data, size_t length) = 0;
virtual void digest(unsigned char* md) = 0;
protected:
MessageDigestImpl() {}
};
} // namespace aria2
#endif // D_MESSAGE_DIGEST_IMPL_H #endif // D_MESSAGE_DIGEST_IMPL_H

View File

@ -33,14 +33,13 @@
*/ */
/* copyright --> */ /* copyright --> */
#include "WinMessageDigestImpl.h" #include "MessageDigestImpl.h"
#include <wincrypt.h> #include <wincrypt.h>
#include "array_fun.h" #include "fmt.h"
#include "a2functional.h"
#include "HashFuncEntry.h"
#include "DlAbortEx.h" #include "DlAbortEx.h"
#include "LogFactory.h"
namespace { namespace {
using namespace aria2; using namespace aria2;
@ -50,9 +49,12 @@ private:
HCRYPTPROV provider_; HCRYPTPROV provider_;
public: public:
Context() { Context() {
if (!::CryptAcquireContext(&provider_, nullptr, nullptr, PROV_RSA_FULL, if (!::CryptAcquireContext(&provider_, nullptr, nullptr,
CRYPT_VERIFYCONTEXT)) { PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
throw DL_ABORT_EX("Failed to get cryptographic provider"); if (!::CryptAcquireContext(&provider_, nullptr, nullptr, PROV_RSA_AES,
CRYPT_VERIFYCONTEXT)) {
throw DL_ABORT_EX("Failed to get cryptographic provider");
}
} }
} }
~Context() { ~Context() {
@ -67,10 +69,30 @@ public:
// XXX static OK? // XXX static OK?
static Context context_; static Context context_;
inline size_t getAlgLength(ALG_ID id)
{
Context context;
HCRYPTHASH hash;
if (!::CryptCreateHash(context.get(), id, 0, 0, &hash)) {
throw DL_ABORT_EX(fmt("Failed to initialize hash %d", id));
}
DWORD rv = 0;
DWORD len = sizeof(rv);
if (!::CryptGetHashParam(hash, HP_HASHSIZE, reinterpret_cast<BYTE*>(&rv),
&len, 0)) {
throw DL_ABORT_EX("Failed to initialize hash(2)");
}
::CryptDestroyHash(hash);
return rv;
}
} // namespace } // namespace
namespace aria2 { namespace aria2 {
template<ALG_ID id> template<ALG_ID id>
class MessageDigestBase : public MessageDigestImpl { class MessageDigestBase : public MessageDigestImpl {
private: private:
@ -88,6 +110,10 @@ public:
MessageDigestBase() : hash_(0), len_(0) { reset(); } MessageDigestBase() : hash_(0), len_(0) { reset(); }
virtual ~MessageDigestBase() { destroy(); } virtual ~MessageDigestBase() { destroy(); }
static size_t length() {
MessageDigestBase<id> rv;
return rv.getDigestLength();
}
virtual size_t getDigestLength() const CXX11_OVERRIDE { virtual size_t getDigestLength() const CXX11_OVERRIDE {
return len_; return len_;
} }
@ -96,11 +122,10 @@ public:
if (!::CryptCreateHash(context_.get(), id, 0, 0, &hash_)) { if (!::CryptCreateHash(context_.get(), id, 0, 0, &hash_)) {
throw DL_ABORT_EX("Failed to create hash"); throw DL_ABORT_EX("Failed to create hash");
} }
DWORD len = sizeof(len_); DWORD len = sizeof(len_);
if (!::CryptGetHashParam(hash_, HP_HASHSIZE, reinterpret_cast<BYTE*>(&len_), if (!::CryptGetHashParam(hash_, HP_HASHSIZE, reinterpret_cast<BYTE*>(&len_),
&len, 0)) { &len, 0)) {
throw DL_ABORT_EX("Failed to create hash"); throw DL_ABORT_EX("Failed to initialize hash");
} }
} }
virtual void update(const void* data, size_t length) CXX11_OVERRIDE { virtual void update(const void* data, size_t length) CXX11_OVERRIDE {
@ -133,45 +158,36 @@ std::unique_ptr<MessageDigestImpl> MessageDigestImpl::sha1()
return std::unique_ptr<MessageDigestImpl>(new MessageDigestSHA1()); return std::unique_ptr<MessageDigestImpl>(new MessageDigestSHA1());
} }
std::unique_ptr<MessageDigestImpl> MessageDigestImpl::create( namespace {
const std::string& hashType) MessageDigestImpl::hashes_t initialize() {
{ MessageDigestImpl::hashes_t rv = {
if (hashType == "sha-1") { { "sha-1", MessageDigestImpl::make_hi<MessageDigestSHA1>() },
return make_unique<MessageDigestSHA1>(); { "md5", MessageDigestImpl::make_hi<MessageDigestMD5>() },
} };
if (hashType == "sha-256") {
return make_unique<MessageDigestSHA256>();
}
if (hashType == "sha-384") {
return make_unique<MessageDigestSHA384>();
}
if (hashType == "sha-512") {
return make_unique<MessageDigestSHA512>();
}
if (hashType == "md5") {
return make_unique<MessageDigestMD5>();
}
return nullptr;
}
bool MessageDigestImpl::supports(const std::string& hashType)
{
try { try {
return !!create(hashType); rv.emplace("sha-256", MessageDigestImpl::make_hi<MessageDigestSHA256>());
} }
catch (RecoverableException& ex) { catch (RecoverableException &ex) {
// no op printf("SHA-256 is not supported on this machine");
}
try {
rv.emplace("sha-384", MessageDigestImpl::make_hi<MessageDigestSHA384>());
}
catch (RecoverableException &ex) {
printf("SHA-384 is not supported on this machine");
}
try {
rv.emplace("sha-512", MessageDigestImpl::make_hi<MessageDigestSHA512>());
}
catch (RecoverableException &ex) {
printf("SHA-512 is not supported on this machine");
} }
return false;
}
size_t MessageDigestImpl::getDigestLength(const std::string& hashType) return rv;
{ };
std::unique_ptr<MessageDigestImpl> impl = create(hashType); } // namespace
if (!impl) {
return 0; MessageDigestImpl::hashes_t MessageDigestImpl::hashes = initialize();
}
return impl->getDigestLength();
}
} // namespace aria2 } // namespace aria2

View File

@ -1,70 +0,0 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2013 Nils Maier
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#ifndef D_WIN_MESSAGE_DIGEST_IMPL_H
#define D_WIN_MESSAGE_DIGEST_IMPL_H
#include "common.h"
#include <string>
#include <memory>
namespace aria2 {
class MessageDigestImpl {
public:
virtual ~MessageDigestImpl() {}
static std::unique_ptr<MessageDigestImpl> sha1();
static std::unique_ptr<MessageDigestImpl> create(const std::string& hashType);
static bool supports(const std::string& hashType);
static size_t getDigestLength(const std::string& hashType);
public:
virtual size_t getDigestLength() const = 0;
virtual void reset() = 0;
virtual void update(const void* data, size_t length) = 0;
virtual void digest(unsigned char* md) = 0;
protected:
MessageDigestImpl() {}
private:
MessageDigestImpl(const MessageDigestImpl&);
MessageDigestImpl& operator=(const MessageDigestImpl&);
};
} // namespace aria2
#endif // D_WIN_MESSAGE_DIGEST_IMPL_H