mirror of https://github.com/aria2/aria2
				
				
				
			WinTLS: Implement messsage digest using the Cryptography Provider
							parent
							
								
									b678bc5e10
								
							
						
					
					
						commit
						a4e29303ef
					
				
							
								
								
									
										88
									
								
								configure.ac
								
								
								
								
							
							
						
						
									
										88
									
								
								configure.ac
								
								
								
								
							| 
						 | 
				
			
			@ -40,6 +40,7 @@ AC_DEFINE_UNQUOTED([TARGET], ["$target"], [Define target-type])
 | 
			
		|||
# Checks for arguments.
 | 
			
		||||
ARIA2_ARG_WITHOUT([libuv])
 | 
			
		||||
ARIA2_ARG_WITHOUT([appletls])
 | 
			
		||||
ARIA2_ARG_WITHOUT([wintls])
 | 
			
		||||
ARIA2_ARG_WITHOUT([gnutls])
 | 
			
		||||
ARIA2_ARG_WITHOUT([libnettle])
 | 
			
		||||
ARIA2_ARG_WITHOUT([libgmp])
 | 
			
		||||
| 
						 | 
				
			
			@ -286,8 +287,30 @@ case "$host" in
 | 
			
		|||
  *darwin*)
 | 
			
		||||
    have_osx="yes"
 | 
			
		||||
  ;;
 | 
			
		||||
  *mingw*)
 | 
			
		||||
    AC_CHECK_HEADERS([windows.h \
 | 
			
		||||
                      winsock2.h \
 | 
			
		||||
                      ws2tcpip.h \
 | 
			
		||||
                      mmsystem.h \
 | 
			
		||||
                      io.h \
 | 
			
		||||
                      iphlpapi.h\
 | 
			
		||||
                      winioctl.h \
 | 
			
		||||
                      share.h], [], [],
 | 
			
		||||
                      [[
 | 
			
		||||
#ifdef HAVE_WS2TCPIP_H
 | 
			
		||||
# include <ws2tcpip.h>
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef HAVE_WINSOCK2_H
 | 
			
		||||
# include <winsock2.h>
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef HAVE_WINDOWS_H
 | 
			
		||||
# include <windows.h>
 | 
			
		||||
#endif
 | 
			
		||||
                      ]])
 | 
			
		||||
  ;;
 | 
			
		||||
esac
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if test "x$with_appletls" = "xyes"; then
 | 
			
		||||
  AC_MSG_CHECKING([whether to enable Mac OS X native SSL/TLS])
 | 
			
		||||
  if test "x$have_osx" = "xyes"; then
 | 
			
		||||
| 
						 | 
				
			
			@ -303,6 +326,23 @@ if test "x$with_appletls" = "xyes"; then
 | 
			
		|||
  fi
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if test "x$with_wintls" = "xyes"; then
 | 
			
		||||
  AC_SEARCH_LIBS([CryptAcquireContextW], [advapi32], [
 | 
			
		||||
                  AC_CHECK_HEADER([wincrypt.h], [have_wincrypt=yes], [have_wincrypt=no],
 | 
			
		||||
                      [[
 | 
			
		||||
#ifdef HAVE_WINDOWS_H
 | 
			
		||||
# include <windows.h>
 | 
			
		||||
#endif
 | 
			
		||||
                      ]])
 | 
			
		||||
                  break;
 | 
			
		||||
                  ], [have_wincrypt=no])
 | 
			
		||||
  if test "x$have_wincrypt" != "xyes"; then
 | 
			
		||||
    if test "x$with_wintls_requested" = "xyes"; then
 | 
			
		||||
      ARIA2_DEP_NOT_MET([wintls])
 | 
			
		||||
    fi
 | 
			
		||||
  fi
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if test "x$with_gnutls" = "xyes" && test "x$have_appletls" != "xyes"; then
 | 
			
		||||
  # gnutls >= 2.8 doesn't have libgnutls-config anymore. We require
 | 
			
		||||
  # 2.2.0 because we use gnutls_priority_set_direct()
 | 
			
		||||
| 
						 | 
				
			
			@ -398,17 +438,22 @@ if test "x$have_osx" == "xyes"; then
 | 
			
		|||
  use_md="apple"
 | 
			
		||||
  AC_DEFINE([USE_APPLE_MD], [1], [What message digest implementation to use])
 | 
			
		||||
else
 | 
			
		||||
  if test "x$have_libnettle" = "xyes"; then
 | 
			
		||||
    AC_DEFINE([USE_LIBNETTLE_MD], [1], [What message digest implementation to use])
 | 
			
		||||
    use_md="libnettle"
 | 
			
		||||
  if test "x$have_wincrypt" == "xyes"; then
 | 
			
		||||
    use_md="windows"
 | 
			
		||||
    AC_DEFINE([USE_WINDOWS_MD], [1], [What message digest implementation to use])
 | 
			
		||||
  else
 | 
			
		||||
    if test "x$have_libgcrypt" = "xyes"; then
 | 
			
		||||
      AC_DEFINE([USE_LIBGCRYPT_MD], [1], [What message digest implementation to use])
 | 
			
		||||
      use_md="libgcrypt"
 | 
			
		||||
    if test "x$have_libnettle" = "xyes"; then
 | 
			
		||||
      AC_DEFINE([USE_LIBNETTLE_MD], [1], [What message digest implementation to use])
 | 
			
		||||
      use_md="libnettle"
 | 
			
		||||
    else
 | 
			
		||||
      if test "x$have_openssl" = "xyes"; then
 | 
			
		||||
        AC_DEFINE([USE_OPENSSL_MD], [1], [What message digest implementation to use])
 | 
			
		||||
        use_md="openssl"
 | 
			
		||||
      if test "x$have_libgcrypt" = "xyes"; then
 | 
			
		||||
        AC_DEFINE([USE_LIBGCRYPT_MD], [1], [What message digest implementation to use])
 | 
			
		||||
        use_md="libgcrypt"
 | 
			
		||||
      else
 | 
			
		||||
        if test "x$have_openssl" = "xyes"; then
 | 
			
		||||
          AC_DEFINE([USE_OPENSSL_MD], [1], [What message digest implementation to use])
 | 
			
		||||
          use_md="openssl"
 | 
			
		||||
        fi
 | 
			
		||||
      fi
 | 
			
		||||
    fi
 | 
			
		||||
  fi
 | 
			
		||||
| 
						 | 
				
			
			@ -427,6 +472,7 @@ fi
 | 
			
		|||
AM_CONDITIONAL([HAVE_OSX], [ test "x$have_osx" = "xyes" ])
 | 
			
		||||
AM_CONDITIONAL([HAVE_APPLETLS], [ test "x$have_appletls" = "xyes" ])
 | 
			
		||||
AM_CONDITIONAL([USE_APPLE_MD], [ test "x$use_md" = "xapple" ])
 | 
			
		||||
AM_CONDITIONAL([USE_WINDOWS_MD], [ test "x$use_md" = "xwindows" ])
 | 
			
		||||
AM_CONDITIONAL([HAVE_LIBGNUTLS], [ test "x$have_libgnutls" = "xyes" ])
 | 
			
		||||
AM_CONDITIONAL([HAVE_LIBNETTLE], [ test "x$have_libnettle" = "xyes" ])
 | 
			
		||||
AM_CONDITIONAL([USE_LIBNETTLE_MD], [ test "x$use_md" = "xlibnettle"])
 | 
			
		||||
| 
						 | 
				
			
			@ -519,30 +565,6 @@ esac
 | 
			
		|||
AC_FUNC_ALLOCA
 | 
			
		||||
AC_HEADER_STDC
 | 
			
		||||
 | 
			
		||||
case "$host" in
 | 
			
		||||
	*mingw*)
 | 
			
		||||
    AC_CHECK_HEADERS([windows.h \
 | 
			
		||||
                      winsock2.h \
 | 
			
		||||
                      ws2tcpip.h \
 | 
			
		||||
                      mmsystem.h \
 | 
			
		||||
                      io.h \
 | 
			
		||||
                      iphlpapi.h\
 | 
			
		||||
                      winioctl.h \
 | 
			
		||||
                      share.h], [], [],
 | 
			
		||||
                      [[
 | 
			
		||||
#ifdef HAVE_WS2TCPIP_H
 | 
			
		||||
# include <ws2tcpip.h>
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef HAVE_WINSOCK2_H
 | 
			
		||||
# include <winsock2.h>
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef HAVE_WINDOWS_H
 | 
			
		||||
# include <windows.h>
 | 
			
		||||
#endif
 | 
			
		||||
                      ]])
 | 
			
		||||
		;;
 | 
			
		||||
esac
 | 
			
		||||
 | 
			
		||||
AC_CHECK_HEADERS([argz.h \
 | 
			
		||||
                  arpa/inet.h \
 | 
			
		||||
                  fcntl.h \
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
		Loading…
	
		Reference in New Issue