summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am4
-rw-r--r--src/MessageDigestImpl.h2
-rw-r--r--src/WinMessageDigestImpl.cc177
-rw-r--r--src/WinMessageDigestImpl.h70
4 files changed, 253 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 01532752..c3652181 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -329,6 +329,10 @@ SRCS += AppleTLSContext.cc AppleTLSContext.h \
AppleTLSSession.cc AppleTLSSession.h
endif # HAVE_APPLETLS
+if USE_WINDOWS_MD
+SRCS += WinMessageDigestImpl.cc WinMessageDigestImpl.h
+endif # USE_WINDOWS_MD
+
if HAVE_LIBGNUTLS
SRCS += LibgnutlsTLSContext.cc LibgnutlsTLSContext.h \
LibgnutlsTLSSession.cc LibgnutlsTLSSession.h
diff --git a/src/MessageDigestImpl.h b/src/MessageDigestImpl.h
index e7de69bb..aee3057f 100644
--- a/src/MessageDigestImpl.h
+++ b/src/MessageDigestImpl.h
@@ -38,6 +38,8 @@
#ifdef USE_APPLE_MD
# include "AppleMessageDigestImpl.h"
+#elif defined(USE_WINDOWS_MD)
+# include "WinMessageDigestImpl.h"
#elif defined(USE_LIBNETTLE_MD)
# include "LibnettleMessageDigestImpl.h"
#elif defined(USE_LIBGCRYPT_MD)
diff --git a/src/WinMessageDigestImpl.cc b/src/WinMessageDigestImpl.cc
new file mode 100644
index 00000000..bbc6d897
--- /dev/null
+++ b/src/WinMessageDigestImpl.cc
@@ -0,0 +1,177 @@
+/* <!-- 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 --> */
+
+#include "WinMessageDigestImpl.h"
+
+#include <wincrypt.h>
+
+#include "array_fun.h"
+#include "a2functional.h"
+#include "HashFuncEntry.h"
+#include "DlAbortEx.h"
+
+namespace {
+using namespace aria2;
+
+class Context {
+private:
+ HCRYPTPROV provider_;
+public:
+ Context() {
+ if (!::CryptAcquireContext(&provider_, nullptr, nullptr, PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT)) {
+ throw DL_ABORT_EX("Failed to get cryptographic provider");
+ }
+ }
+ ~Context() {
+ ::CryptReleaseContext(provider_, 0);
+ }
+
+ HCRYPTPROV get() {
+ return provider_;
+ }
+};
+
+// XXX static OK?
+static Context context_;
+
+} // namespace
+
+namespace aria2 {
+
+template<ALG_ID id>
+class MessageDigestBase : public MessageDigestImpl {
+private:
+ HCRYPTHASH hash_;
+ DWORD len_;
+
+ void destroy() {
+ if (hash_) {
+ ::CryptDestroyHash(hash_);
+ hash_ = 0;
+ }
+ }
+
+public:
+ MessageDigestBase() : hash_(0), len_(0) { reset(); }
+ virtual ~MessageDigestBase() { destroy(); }
+
+ virtual size_t getDigestLength() const CXX11_OVERRIDE {
+ return len_;
+ }
+ virtual void reset() CXX11_OVERRIDE {
+ destroy();
+ if (!::CryptCreateHash(context_.get(), id, 0, 0, &hash_)) {
+ throw DL_ABORT_EX("Failed to create hash");
+ }
+
+ DWORD len = sizeof(len_);
+ if (!::CryptGetHashParam(hash_, HP_HASHSIZE, reinterpret_cast<BYTE*>(&len_),
+ &len, 0)) {
+ throw DL_ABORT_EX("Failed to create hash");
+ }
+ }
+ virtual void update(const void* data, size_t length) CXX11_OVERRIDE {
+ auto bytes = reinterpret_cast<const unsigned char*>(data);
+ while (length) {
+ DWORD l = std::min(length, (size_t)std::numeric_limits<uint32_t>::max());
+ if (!::CryptHashData(hash_, bytes, l, 0)) {
+ throw DL_ABORT_EX("Failed to update hash");
+ }
+ length -= l;
+ bytes += l;
+ }
+ }
+ virtual void digest(unsigned char* md) CXX11_OVERRIDE {
+ DWORD len = len_;
+ if (!::CryptGetHashParam(hash_, HP_HASHVAL, md, &len, 0)) {
+ throw DL_ABORT_EX("Failed to create hash digest");
+ }
+ }
+};
+
+typedef MessageDigestBase<CALG_MD5> MessageDigestMD5;
+typedef MessageDigestBase<CALG_SHA1> MessageDigestSHA1;
+typedef MessageDigestBase<CALG_SHA_256> MessageDigestSHA256;
+typedef MessageDigestBase<CALG_SHA_384> MessageDigestSHA384;
+typedef MessageDigestBase<CALG_SHA_512> MessageDigestSHA512;
+
+std::unique_ptr<MessageDigestImpl> MessageDigestImpl::sha1()
+{
+ return std::unique_ptr<MessageDigestImpl>(new MessageDigestSHA1());
+}
+
+std::unique_ptr<MessageDigestImpl> MessageDigestImpl::create(
+ const std::string& hashType)
+{
+ if (hashType == "sha-1") {
+ return make_unique<MessageDigestSHA1>();
+ }
+ 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 {
+ return !!create(hashType);
+ }
+ catch (RecoverableException& ex) {
+ // no op
+ }
+ return false;
+}
+
+size_t MessageDigestImpl::getDigestLength(const std::string& hashType)
+{
+ std::unique_ptr<MessageDigestImpl> impl = create(hashType);
+ if (!impl) {
+ return 0;
+ }
+ return impl->getDigestLength();
+}
+
+} // namespace aria2
diff --git a/src/WinMessageDigestImpl.h b/src/WinMessageDigestImpl.h
new file mode 100644
index 00000000..758937a7
--- /dev/null
+++ b/src/WinMessageDigestImpl.h
@@ -0,0 +1,70 @@
+/* <!-- 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