feat(Core/Crypto): add support OpenSSL 3.0 (#13354)

This commit is contained in:
Winfidonarleyan 2022-11-23 21:12:20 +03:00 committed by GitHub
parent 4a2964e10a
commit a1a1528cb4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 1099 additions and 507 deletions

View File

@ -14,14 +14,11 @@
# (further support will be needed, this is a preliminary release!)
set(OPENSSL_EXPECTED_VERSION 1.0.0)
find_package(OpenSSL REQUIRED)
find_package(OpenSSL REQUIRED COMPONENTS Crypto SSL)
add_library(openssl INTERFACE)
target_link_libraries(openssl
INTERFACE
${OPENSSL_LIBRARIES})
target_include_directories(openssl
INTERFACE
${OPENSSL_INCLUDE_DIR})
OpenSSL::Crypto
OpenSSL::SSL)

View File

@ -1,75 +1,195 @@
# - Try to find the OpenSSL encryption library
# Once done this will define
#
# OPENSSL_ROOT_DIR - Set this variable to the root installation of OpenSSL
#
# Read-Only variables:
# OPENSSL_FOUND - system has the OpenSSL library
# OPENSSL_INCLUDE_DIR - the OpenSSL include directory
# OPENSSL_LIBRARIES - The libraries needed to use OpenSSL
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
#=============================================================================
# Copyright 2006-2009 Kitware, Inc.
# Copyright 2006 Alexander Neundorf <neundorf@kde.org>
# Copyright 2009-2010 Mathieu Malaterre <mathieu.malaterre@gmail.com>
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distributed this file outside of CMake, substitute the full
# License text for the above reference.)
#[=======================================================================[.rst:
FindOpenSSL
-----------
# http://www.slproweb.com/products/Win32OpenSSL.html
Find the OpenSSL encryption library.
SET(_OPENSSL_ROOT_HINTS
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (32-bit)_is1;Inno Setup: App Path]"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (64-bit)_is1;Inno Setup: App Path]"
"$ENV{OPENSSL_ROOT_DIR}"
"${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}"
)
Optional COMPONENTS
^^^^^^^^^^^^^^^^^^^
IF(PLATFORM EQUAL 64)
SET(_OPENSSL_ROOT_PATHS
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (64-bit)_is1;InstallLocation]"
"C:/OpenSSL-Win64/"
"C:/OpenSSL/"
"C:/Program Files/OpenSSL-Win64/"
)
ELSE()
SET(_OPENSSL_ROOT_PATHS
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (32-bit)_is1;InstallLocation]"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (32-bit)_is1;InstallLocation]"
"C:/OpenSSL/"
"C:/Program Files/OpenSSL/"
)
ENDIF()
This module supports two optional COMPONENTS: ``Crypto`` and ``SSL``. Both
components have associated imported targets, as described below.
FIND_PATH(OPENSSL_ROOT_DIR
Imported Targets
^^^^^^^^^^^^^^^^
This module defines the following :prop_tgt:`IMPORTED` targets:
``OpenSSL::SSL``
The OpenSSL ``ssl`` library, if found.
``OpenSSL::Crypto``
The OpenSSL ``crypto`` library, if found.
``OpenSSL::applink``
The OpenSSL ``applink`` components that might be need to be compiled into
projects under MSVC. This target is available only if found OpenSSL version
is not less than 0.9.8. By linking this target the above OpenSSL targets can
be linked even if the project has different MSVC runtime configurations with
the above OpenSSL targets. This target has no effect on platforms other than
MSVC.
NOTE: Due to how ``INTERFACE_SOURCES`` are consumed by the consuming target,
unless you certainly know what you are doing, it is always preferred to link
``OpenSSL::applink`` target as ``PRIVATE`` and to make sure that this target is
linked at most once for the whole dependency graph of any library or
executable:
.. code-block:: cmake
target_link_libraries(myTarget PRIVATE OpenSSL::applink)
Otherwise you would probably encounter unexpected random problems when building
and linking, as both the ISO C and the ISO C++ standard claims almost nothing
about what a link process should be.
Result Variables
^^^^^^^^^^^^^^^^
This module will set the following variables in your project:
``OPENSSL_FOUND``
System has the OpenSSL library. If no components are requested it only
requires the crypto library.
``OPENSSL_INCLUDE_DIR``
The OpenSSL include directory.
``OPENSSL_CRYPTO_LIBRARY``
The OpenSSL crypto library.
``OPENSSL_CRYPTO_LIBRARIES``
The OpenSSL crypto library and its dependencies.
``OPENSSL_SSL_LIBRARY``
The OpenSSL SSL library.
``OPENSSL_SSL_LIBRARIES``
The OpenSSL SSL library and its dependencies.
``OPENSSL_LIBRARIES``
All OpenSSL libraries and their dependencies.
``OPENSSL_VERSION``
This is set to ``$major.$minor.$revision$patch`` (e.g. ``0.9.8s``).
``OPENSSL_APPLINK_SOURCE``
The sources in the target ``OpenSSL::applink`` that is mentioned above. This
variable shall always be undefined if found openssl version is less than
0.9.8 or if platform is not MSVC.
Hints
^^^^^
Set ``OPENSSL_ROOT_DIR`` to the root directory of an OpenSSL installation.
Set ``OPENSSL_USE_STATIC_LIBS`` to ``TRUE`` to look for static libraries.
Set ``OPENSSL_MSVC_STATIC_RT`` set ``TRUE`` to choose the MT version of the lib.
#]=======================================================================]
set(OPENSSL_EXPECTED_VERSION "1.0")
macro(_OpenSSL_test_and_find_dependencies ssl_library crypto_library)
if((CMAKE_SYSTEM_NAME STREQUAL "Linux") AND
(("${ssl_library}" MATCHES "\\${CMAKE_STATIC_LIBRARY_SUFFIX}$") OR
("${crypto_library}" MATCHES "\\${CMAKE_STATIC_LIBRARY_SUFFIX}$")))
set(_OpenSSL_has_dependencies TRUE)
find_package(Threads)
else()
set(_OpenSSL_has_dependencies FALSE)
endif()
endmacro()
function(_OpenSSL_add_dependencies libraries_var)
if(CMAKE_THREAD_LIBS_INIT)
list(APPEND ${libraries_var} ${CMAKE_THREAD_LIBS_INIT})
endif()
list(APPEND ${libraries_var} ${CMAKE_DL_LIBS})
set(${libraries_var} ${${libraries_var}} PARENT_SCOPE)
endfunction()
function(_OpenSSL_target_add_dependencies target)
if(_OpenSSL_has_dependencies)
set_property( TARGET ${target} APPEND PROPERTY INTERFACE_LINK_LIBRARIES Threads::Threads )
set_property( TARGET ${target} APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${CMAKE_DL_LIBS} )
endif()
endfunction()
if (UNIX)
find_package(PkgConfig QUIET)
pkg_check_modules(_OPENSSL QUIET openssl)
endif ()
# Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES
if(OPENSSL_USE_STATIC_LIBS)
set(_openssl_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
if(WIN32)
set(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
else()
set(CMAKE_FIND_LIBRARY_SUFFIXES .a )
endif()
endif()
if (WIN32)
# http://www.slproweb.com/products/Win32OpenSSL.html
set(_OPENSSL_MSI_INSTALL_GUID "")
if(PLATFORM EQUAL 64)
set(_OPENSSL_MSI_INSTALL_GUID "117551DB-A110-4BBD-BB05-CFE0BCB3ED31")
set(_OPENSSL_ROOT_HINTS
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (64-bit)_is1;Inno Setup: App Path]"
${OPENSSL_ROOT_DIR}
ENV OPENSSL_ROOT_DIR
)
file(TO_CMAKE_PATH "$ENV{PROGRAMFILES}" _programfiles)
set(_OPENSSL_ROOT_PATHS
"${_programfiles}/OpenSSL"
"${_programfiles}/OpenSSL-Win64"
"C:/OpenSSL/"
"C:/OpenSSL-Win64/"
)
else()
set(_OPENSSL_MSI_INSTALL_GUID "A1EEC576-43B9-4E75-9E02-03DA542D2A38")
set(_OPENSSL_ROOT_HINTS
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (32-bit)_is1;Inno Setup: App Path]"
${OPENSSL_ROOT_DIR}
ENV OPENSSL_ROOT_DIR
)
file(TO_CMAKE_PATH "$ENV{PROGRAMFILES}" _programfiles)
set(_OPENSSL_ROOT_PATHS
"${_programfiles}/OpenSSL"
"${_programfiles}/OpenSSL-Win32"
"C:/OpenSSL/"
"C:/OpenSSL-Win32/"
)
endif()
unset(_programfiles)
# If OpenSSL was installed using .msi package instead of .exe, Inno Setup registry values are not written to Uninstall\OpenSSL
# but because it is only a shim around Inno Setup it does write the location of uninstaller which we can use to determine path
get_filename_component(_OPENSSL_MSI_INSTALL_PATH "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Inno Setup MSIs\\${_OPENSSL_MSI_INSTALL_GUID};]" DIRECTORY)
if(NOT _OPENSSL_MSI_INSTALL_PATH STREQUAL "/")
list(INSERT _OPENSSL_ROOT_HINTS 0 ${_OPENSSL_MSI_INSTALL_PATH})
endif()
else ()
set(_OPENSSL_ROOT_HINTS
${OPENSSL_ROOT_DIR}
ENV OPENSSL_ROOT_DIR
)
endif ()
set(_OPENSSL_ROOT_HINTS_AND_PATHS
HINTS ${_OPENSSL_ROOT_HINTS}
PATHS ${_OPENSSL_ROOT_PATHS}
)
find_path(OPENSSL_INCLUDE_DIR
NAMES
include/openssl/ssl.h
openssl/ssl.h
${_OPENSSL_ROOT_HINTS_AND_PATHS}
HINTS
${_OPENSSL_ROOT_HINTS}
PATHS
${_OPENSSL_ROOT_PATHS}
)
MARK_AS_ADVANCED(OPENSSL_ROOT_DIR)
# Re-use the previous path:
FIND_PATH(OPENSSL_INCLUDE_DIR openssl/ssl.h
${OPENSSL_ROOT_DIR}/include
${_OPENSSL_INCLUDEDIR}
${_OPENSSL_INCLUDE_DIRS}
PATH_SUFFIXES
include
)
IF(WIN32 AND NOT CYGWIN)
# MINGW should go here too
IF(MSVC)
if(WIN32 AND NOT CYGWIN)
if(MSVC)
# /MD and /MDd are the standard values - if someone wants to use
# others, the libnames have to change here too
# use also ssl and ssleay32 in debug as fallback for openssl < 0.9.8b
# TODO: handle /MT and static lib
# enable OPENSSL_MSVC_STATIC_RT to get the libs build /MT (Multithreaded no-DLL)
# In Visual C++ naming convention each of these four kinds of Windows libraries has it's standard suffix:
# * MD for dynamic-release
# * MDd for dynamic-debug
@ -77,119 +197,475 @@ IF(WIN32 AND NOT CYGWIN)
# * MTd for static-debug
# Implementation details:
# We are using the libraries located in the VC subdir instead of the parent directory eventhough :
# We are using the libraries located in the VC subdir instead of the parent directory even though :
# libeay32MD.lib is identical to ../libeay32.lib, and
# ssleay32MD.lib is identical to ../ssleay32.lib
# enable OPENSSL_USE_STATIC_LIBS to use the static libs located in lib/VC/static
# In 1.1 version of OpenSSL we have other names of libs: libcrypto32MTd.lib and libssl32MTd.lib
if (OPENSSL_MSVC_STATIC_RT)
set(_OPENSSL_MSVC_RT_MODE "MT")
else ()
set(_OPENSSL_MSVC_RT_MODE "MD")
endif ()
# Since OpenSSL 1.1, lib names are like libcrypto32MTd.lib and libssl32MTd.lib
if( "${CMAKE_SIZEOF_VOID_P}" STREQUAL "8" )
set(_OPENSSL_MSVC_ARCH_SUFFIX "64")
else()
set(_OPENSSL_MSVC_ARCH_SUFFIX "32")
endif()
FIND_LIBRARY(LIB_EAY_DEBUG
NAMES
libcrypto${_OPENSSL_MSVC_ARCH_SUFFIX}MDd libcrypto libeay32MDd libeay32
PATHS
${OPENSSL_ROOT_DIR}/lib/VC
${OPENSSL_ROOT_DIR}/debug/lib
)
FIND_LIBRARY(LIB_EAY_RELEASE
NAMES
libcrypto${_OPENSSL_MSVC_ARCH_SUFFIX}MD libcrypto libeay32MD libeay32
PATHS
${OPENSSL_ROOT_DIR}/lib/VC
${OPENSSL_ROOT_DIR}/lib
)
FIND_LIBRARY(SSL_EAY_DEBUG
NAMES
libssl${_OPENSSL_MSVC_ARCH_SUFFIX}MDd libssl ssleay32MDd ssleay32 ssl
PATHS
${OPENSSL_ROOT_DIR}/lib/VC
${OPENSSL_ROOT_DIR}/debug/lib
)
FIND_LIBRARY(SSL_EAY_RELEASE
NAMES
libssl${_OPENSSL_MSVC_ARCH_SUFFIX}MD libssl ssleay32MD ssleay32 ssl
PATHS
${OPENSSL_ROOT_DIR}/lib/VC
${OPENSSL_ROOT_DIR}/lib
)
if( CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE )
set( OPENSSL_LIBRARIES
optimized ${SSL_EAY_RELEASE} ${LIB_EAY_RELEASE}
debug ${SSL_EAY_DEBUG} ${LIB_EAY_DEBUG}
if(OPENSSL_USE_STATIC_LIBS)
set(_OPENSSL_STATIC_SUFFIX
"_static"
)
set(_OPENSSL_PATH_SUFFIXES
"lib/VC/static"
"VC/static"
"lib"
)
else()
set( OPENSSL_LIBRARIES
${SSL_EAY_RELEASE}
${LIB_EAY_RELEASE}
set(_OPENSSL_STATIC_SUFFIX
""
)
set(_OPENSSL_PATH_SUFFIXES
"lib/VC"
"VC"
"lib"
)
endif ()
find_library(LIB_EAY_DEBUG
NAMES
# When OpenSSL is built with default options, the static library name is suffixed with "_static".
# Looking the "libcrypto_static.lib" with a higher priority than "libcrypto.lib" which is the
# import library of "libcrypto.dll".
libcrypto${_OPENSSL_STATIC_SUFFIX}${_OPENSSL_MSVC_ARCH_SUFFIX}${_OPENSSL_MSVC_RT_MODE}d
libcrypto${_OPENSSL_STATIC_SUFFIX}${_OPENSSL_MSVC_RT_MODE}d
libcrypto${_OPENSSL_STATIC_SUFFIX}d
libeay32${_OPENSSL_STATIC_SUFFIX}${_OPENSSL_MSVC_RT_MODE}d
libeay32${_OPENSSL_STATIC_SUFFIX}d
crypto${_OPENSSL_STATIC_SUFFIX}d
# When OpenSSL is built with the "-static" option, only the static build is produced,
# and it is not suffixed with "_static".
libcrypto${_OPENSSL_MSVC_ARCH_SUFFIX}${_OPENSSL_MSVC_RT_MODE}d
libcrypto${_OPENSSL_MSVC_RT_MODE}d
libcryptod
libeay32${_OPENSSL_MSVC_RT_MODE}d
libeay32d
cryptod
NAMES_PER_DIR
${_OPENSSL_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
${_OPENSSL_PATH_SUFFIXES}
)
find_library(LIB_EAY_RELEASE
NAMES
# When OpenSSL is built with default options, the static library name is suffixed with "_static".
# Looking the "libcrypto_static.lib" with a higher priority than "libcrypto.lib" which is the
# import library of "libcrypto.dll".
libcrypto${_OPENSSL_STATIC_SUFFIX}${_OPENSSL_MSVC_ARCH_SUFFIX}${_OPENSSL_MSVC_RT_MODE}
libcrypto${_OPENSSL_STATIC_SUFFIX}${_OPENSSL_MSVC_RT_MODE}
libcrypto${_OPENSSL_STATIC_SUFFIX}
libeay32${_OPENSSL_STATIC_SUFFIX}${_OPENSSL_MSVC_RT_MODE}
libeay32${_OPENSSL_STATIC_SUFFIX}
crypto${_OPENSSL_STATIC_SUFFIX}
# When OpenSSL is built with the "-static" option, only the static build is produced,
# and it is not suffixed with "_static".
libcrypto${_OPENSSL_MSVC_ARCH_SUFFIX}${_OPENSSL_MSVC_RT_MODE}
libcrypto${_OPENSSL_MSVC_RT_MODE}
libcrypto
libeay32${_OPENSSL_MSVC_RT_MODE}
libeay32
crypto
NAMES_PER_DIR
${_OPENSSL_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
${_OPENSSL_PATH_SUFFIXES}
)
find_library(SSL_EAY_DEBUG
NAMES
# When OpenSSL is built with default options, the static library name is suffixed with "_static".
# Looking the "libssl_static.lib" with a higher priority than "libssl.lib" which is the
# import library of "libssl.dll".
libssl${_OPENSSL_STATIC_SUFFIX}${_OPENSSL_MSVC_ARCH_SUFFIX}${_OPENSSL_MSVC_RT_MODE}d
libssl${_OPENSSL_STATIC_SUFFIX}${_OPENSSL_MSVC_RT_MODE}d
libssl${_OPENSSL_STATIC_SUFFIX}d
ssleay32${_OPENSSL_STATIC_SUFFIX}${_OPENSSL_MSVC_RT_MODE}d
ssleay32${_OPENSSL_STATIC_SUFFIX}d
ssl${_OPENSSL_STATIC_SUFFIX}d
# When OpenSSL is built with the "-static" option, only the static build is produced,
# and it is not suffixed with "_static".
libssl${_OPENSSL_MSVC_ARCH_SUFFIX}${_OPENSSL_MSVC_RT_MODE}d
libssl${_OPENSSL_MSVC_RT_MODE}d
libssld
ssleay32${_OPENSSL_MSVC_RT_MODE}d
ssleay32d
ssld
NAMES_PER_DIR
${_OPENSSL_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
${_OPENSSL_PATH_SUFFIXES}
)
find_library(SSL_EAY_RELEASE
NAMES
# When OpenSSL is built with default options, the static library name is suffixed with "_static".
# Looking the "libssl_static.lib" with a higher priority than "libssl.lib" which is the
# import library of "libssl.dll".
libssl${_OPENSSL_STATIC_SUFFIX}${_OPENSSL_MSVC_ARCH_SUFFIX}${_OPENSSL_MSVC_RT_MODE}
libssl${_OPENSSL_STATIC_SUFFIX}${_OPENSSL_MSVC_RT_MODE}
libssl${_OPENSSL_STATIC_SUFFIX}
ssleay32${_OPENSSL_STATIC_SUFFIX}${_OPENSSL_MSVC_RT_MODE}
ssleay32${_OPENSSL_STATIC_SUFFIX}
ssl${_OPENSSL_STATIC_SUFFIX}
# When OpenSSL is built with the "-static" option, only the static build is produced,
# and it is not suffixed with "_static".
libssl${_OPENSSL_MSVC_ARCH_SUFFIX}${_OPENSSL_MSVC_RT_MODE}
libssl${_OPENSSL_MSVC_RT_MODE}
libssl
ssleay32${_OPENSSL_MSVC_RT_MODE}
ssleay32
ssl
NAMES_PER_DIR
${_OPENSSL_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
${_OPENSSL_PATH_SUFFIXES}
)
set(LIB_EAY_LIBRARY_DEBUG "${LIB_EAY_DEBUG}")
set(LIB_EAY_LIBRARY_RELEASE "${LIB_EAY_RELEASE}")
set(SSL_EAY_LIBRARY_DEBUG "${SSL_EAY_DEBUG}")
set(SSL_EAY_LIBRARY_RELEASE "${SSL_EAY_RELEASE}")
include(SelectLibraryConfigurations)
select_library_configurations(LIB_EAY)
select_library_configurations(SSL_EAY)
mark_as_advanced(LIB_EAY_LIBRARY_DEBUG LIB_EAY_LIBRARY_RELEASE
SSL_EAY_LIBRARY_DEBUG SSL_EAY_LIBRARY_RELEASE)
set(OPENSSL_SSL_LIBRARY ${SSL_EAY_LIBRARY} )
set(OPENSSL_CRYPTO_LIBRARY ${LIB_EAY_LIBRARY} )
elseif(MINGW)
# same player, for MinGW
set(LIB_EAY_NAMES crypto libeay32)
set(SSL_EAY_NAMES ssl ssleay32)
find_library(LIB_EAY
NAMES
${LIB_EAY_NAMES}
NAMES_PER_DIR
${_OPENSSL_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
"lib/MinGW"
"lib"
)
find_library(SSL_EAY
NAMES
${SSL_EAY_NAMES}
NAMES_PER_DIR
${_OPENSSL_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
"lib/MinGW"
"lib"
)
mark_as_advanced(SSL_EAY LIB_EAY)
set(OPENSSL_SSL_LIBRARY ${SSL_EAY} )
set(OPENSSL_CRYPTO_LIBRARY ${LIB_EAY} )
unset(LIB_EAY_NAMES)
unset(SSL_EAY_NAMES)
else()
# Not sure what to pick for -say- intel, let's use the toplevel ones and hope someone report issues:
find_library(LIB_EAY
NAMES
libcrypto
libeay32
NAMES_PER_DIR
${_OPENSSL_ROOT_HINTS_AND_PATHS}
HINTS
${_OPENSSL_LIBDIR}
PATH_SUFFIXES
lib
)
find_library(SSL_EAY
NAMES
libssl
ssleay32
NAMES_PER_DIR
${_OPENSSL_ROOT_HINTS_AND_PATHS}
HINTS
${_OPENSSL_LIBDIR}
PATH_SUFFIXES
lib
)
mark_as_advanced(SSL_EAY LIB_EAY)
set(OPENSSL_SSL_LIBRARY ${SSL_EAY} )
set(OPENSSL_CRYPTO_LIBRARY ${LIB_EAY} )
endif()
else()
find_library(OPENSSL_SSL_LIBRARY
NAMES
ssl
ssleay32
ssleay32MD
NAMES_PER_DIR
${_OPENSSL_ROOT_HINTS_AND_PATHS}
HINTS
${_OPENSSL_LIBDIR}
${_OPENSSL_LIBRARY_DIRS}
PATH_SUFFIXES
lib
)
find_library(OPENSSL_CRYPTO_LIBRARY
NAMES
crypto
NAMES_PER_DIR
${_OPENSSL_ROOT_HINTS_AND_PATHS}
HINTS
${_OPENSSL_LIBDIR}
${_OPENSSL_LIBRARY_DIRS}
PATH_SUFFIXES
lib
)
mark_as_advanced(OPENSSL_CRYPTO_LIBRARY OPENSSL_SSL_LIBRARY)
endif()
set(OPENSSL_SSL_LIBRARIES ${OPENSSL_SSL_LIBRARY})
set(OPENSSL_CRYPTO_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
set(OPENSSL_LIBRARIES ${OPENSSL_SSL_LIBRARIES} ${OPENSSL_CRYPTO_LIBRARIES} )
_OpenSSL_test_and_find_dependencies("${OPENSSL_SSL_LIBRARY}" "${OPENSSL_CRYPTO_LIBRARY}")
if(_OpenSSL_has_dependencies)
_OpenSSL_add_dependencies( OPENSSL_SSL_LIBRARIES )
_OpenSSL_add_dependencies( OPENSSL_CRYPTO_LIBRARIES )
_OpenSSL_add_dependencies( OPENSSL_LIBRARIES )
endif()
function(from_hex HEX DEC)
string(TOUPPER "${HEX}" HEX)
set(_res 0)
string(LENGTH "${HEX}" _strlen)
while (_strlen GREATER 0)
math(EXPR _res "${_res} * 16")
string(SUBSTRING "${HEX}" 0 1 NIBBLE)
string(SUBSTRING "${HEX}" 1 -1 HEX)
if (NIBBLE STREQUAL "A")
math(EXPR _res "${_res} + 10")
elseif (NIBBLE STREQUAL "B")
math(EXPR _res "${_res} + 11")
elseif (NIBBLE STREQUAL "C")
math(EXPR _res "${_res} + 12")
elseif (NIBBLE STREQUAL "D")
math(EXPR _res "${_res} + 13")
elseif (NIBBLE STREQUAL "E")
math(EXPR _res "${_res} + 14")
elseif (NIBBLE STREQUAL "F")
math(EXPR _res "${_res} + 15")
else()
math(EXPR _res "${_res} + ${NIBBLE}")
endif()
MARK_AS_ADVANCED(SSL_EAY_DEBUG SSL_EAY_RELEASE LIB_EAY_DEBUG LIB_EAY_RELEASE)
ELSEIF(MINGW)
string(LENGTH "${HEX}" _strlen)
endwhile()
# same player, for MingW
FIND_LIBRARY(LIB_EAY
NAMES
libeay32
PATHS
${OPENSSL_ROOT_DIR}/lib/MinGW
set(${DEC} ${_res} PARENT_SCOPE)
endfunction()
if(OPENSSL_INCLUDE_DIR AND EXISTS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h")
file(STRINGS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h" openssl_version_str
REGEX "^#[\t ]*define[\t ]+OPENSSL_VERSION_NUMBER[\t ]+0x([0-9a-fA-F])+.*")
if(openssl_version_str)
# The version number is encoded as 0xMNNFFPPS: major minor fix patch status
# The status gives if this is a developer or prerelease and is ignored here.
# Major, minor, and fix directly translate into the version numbers shown in
# the string. The patch field translates to the single character suffix that
# indicates the bug fix state, which 00 -> nothing, 01 -> a, 02 -> b and so
# on.
string(REGEX REPLACE "^.*OPENSSL_VERSION_NUMBER[\t ]+0x([0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F]).*$"
"\\1;\\2;\\3;\\4;\\5" OPENSSL_VERSION_LIST "${openssl_version_str}")
list(GET OPENSSL_VERSION_LIST 0 OPENSSL_VERSION_MAJOR)
list(GET OPENSSL_VERSION_LIST 1 OPENSSL_VERSION_MINOR)
from_hex("${OPENSSL_VERSION_MINOR}" OPENSSL_VERSION_MINOR)
list(GET OPENSSL_VERSION_LIST 2 OPENSSL_VERSION_FIX)
from_hex("${OPENSSL_VERSION_FIX}" OPENSSL_VERSION_FIX)
list(GET OPENSSL_VERSION_LIST 3 OPENSSL_VERSION_PATCH)
if (NOT OPENSSL_VERSION_PATCH STREQUAL "00")
from_hex("${OPENSSL_VERSION_PATCH}" _tmp)
# 96 is the ASCII code of 'a' minus 1
math(EXPR OPENSSL_VERSION_PATCH_ASCII "${_tmp} + 96")
unset(_tmp)
# Once anyone knows how OpenSSL would call the patch versions beyond 'z'
# this should be updated to handle that, too. This has not happened yet
# so it is simply ignored here for now.
string(ASCII "${OPENSSL_VERSION_PATCH_ASCII}" OPENSSL_VERSION_PATCH_STRING)
endif ()
set(OPENSSL_VERSION "${OPENSSL_VERSION_MAJOR}.${OPENSSL_VERSION_MINOR}.${OPENSSL_VERSION_FIX}${OPENSSL_VERSION_PATCH_STRING}")
else ()
# Since OpenSSL 3.0.0, the new version format is MAJOR.MINOR.PATCH and
# a new OPENSSL_VERSION_STR macro contains exactly that
file(STRINGS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h" OPENSSL_VERSION_STR
REGEX "^#[\t ]*define[\t ]+OPENSSL_VERSION_STR[\t ]+\"([0-9])+\\.([0-9])+\\.([0-9])+\".*")
string(REGEX REPLACE "^.*OPENSSL_VERSION_STR[\t ]+\"([0-9]+\\.[0-9]+\\.[0-9]+)\".*$"
"\\1" OPENSSL_VERSION_STR "${OPENSSL_VERSION_STR}")
set(OPENSSL_VERSION "${OPENSSL_VERSION_STR}")
unset(OPENSSL_VERSION_STR)
endif ()
endif ()
foreach(_comp IN LISTS OpenSSL_FIND_COMPONENTS)
if(_comp STREQUAL "Crypto")
if(EXISTS "${OPENSSL_INCLUDE_DIR}" AND
(EXISTS "${OPENSSL_CRYPTO_LIBRARY}" OR
EXISTS "${LIB_EAY_LIBRARY_DEBUG}" OR
EXISTS "${LIB_EAY_LIBRARY_RELEASE}")
)
FIND_LIBRARY(SSL_EAY NAMES
NAMES
ssleay32
PATHS
${OPENSSL_ROOT_DIR}/lib/MinGW
set(OpenSSL_${_comp}_FOUND TRUE)
else()
set(OpenSSL_${_comp}_FOUND FALSE)
endif()
elseif(_comp STREQUAL "SSL")
if(EXISTS "${OPENSSL_INCLUDE_DIR}" AND
(EXISTS "${OPENSSL_SSL_LIBRARY}" OR
EXISTS "${SSL_EAY_LIBRARY_DEBUG}" OR
EXISTS "${SSL_EAY_LIBRARY_RELEASE}")
)
MARK_AS_ADVANCED(SSL_EAY LIB_EAY)
set( OPENSSL_LIBRARIES
${SSL_EAY}
${LIB_EAY}
)
ELSE(MSVC)
# Not sure what to pick for -say- intel, let's use the toplevel ones and hope someone report issues:
FIND_LIBRARY(LIB_EAY
NAMES
libeay32
PATHS
${OPENSSL_ROOT_DIR}/lib
${OPENSSL_ROOT_DIR}/lib/VC
)
FIND_LIBRARY(SSL_EAY
NAMES
ssleay32
PATHS
${OPENSSL_ROOT_DIR}/lib
${OPENSSL_ROOT_DIR}/lib/VC
)
MARK_AS_ADVANCED(SSL_EAY LIB_EAY)
SET( OPENSSL_LIBRARIES ${SSL_EAY} ${LIB_EAY} )
ENDIF(MSVC)
ELSE(WIN32 AND NOT CYGWIN)
FIND_LIBRARY(OPENSSL_SSL_LIBRARIES NAMES ssl ssleay32 ssleay32MD)
FIND_LIBRARY(OPENSSL_CRYPTO_LIBRARIES NAMES crypto)
MARK_AS_ADVANCED(OPENSSL_CRYPTO_LIBRARIES OPENSSL_SSL_LIBRARIES)
SET(OPENSSL_LIBRARIES ${OPENSSL_SSL_LIBRARIES} ${OPENSSL_CRYPTO_LIBRARIES})
ENDIF(WIN32 AND NOT CYGWIN)
set(OpenSSL_${_comp}_FOUND TRUE)
else()
set(OpenSSL_${_comp}_FOUND FALSE)
endif()
else()
message(WARNING "${_comp} is not a valid OpenSSL component")
set(OpenSSL_${_comp}_FOUND FALSE)
endif()
endforeach()
unset(_comp)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(OpenSSL DEFAULT_MSG
OPENSSL_LIBRARIES
OPENSSL_INCLUDE_DIR
find_package_handle_standard_args(OpenSSL
REQUIRED_VARS
OPENSSL_CRYPTO_LIBRARY
OPENSSL_INCLUDE_DIR
VERSION_VAR
OPENSSL_VERSION
HANDLE_COMPONENTS
FAIL_MESSAGE
"Could NOT find OpenSSL, try to set the path to OpenSSL root folder in the system variable OPENSSL_ROOT_DIR"
)
MARK_AS_ADVANCED(OPENSSL_INCLUDE_DIR OPENSSL_LIBRARIES)
mark_as_advanced(OPENSSL_INCLUDE_DIR)
if(OPENSSL_FOUND)
message(STATUS "Found OpenSSL library: ${OPENSSL_LIBRARIES}")
message(STATUS "Found OpenSSL headers: ${OPENSSL_INCLUDE_DIR}")
include(EnsureVersion)
ENSURE_VERSION("${OPENSSL_EXPECTED_VERSION}" "${OPENSSL_VERSION}" OPENSSL_VERSION_OK)
if(NOT OPENSSL_VERSION_OK)
message(FATAL_ERROR "TrinityCore needs OpenSSL version ${OPENSSL_EXPECTED_VERSION} but found too new version ${OPENSSL_VERSION}. TrinityCore needs OpenSSL 1.0.x or 1.1.x to work properly. If you still have problems please install OpenSSL 1.0.x if you still have problems search on forum for TCE00022")
endif()
if(NOT TARGET OpenSSL::Crypto AND
(EXISTS "${OPENSSL_CRYPTO_LIBRARY}" OR
EXISTS "${LIB_EAY_LIBRARY_DEBUG}" OR
EXISTS "${LIB_EAY_LIBRARY_RELEASE}")
)
add_library(OpenSSL::Crypto UNKNOWN IMPORTED)
set_target_properties(OpenSSL::Crypto PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${OPENSSL_INCLUDE_DIR}")
if(EXISTS "${OPENSSL_CRYPTO_LIBRARY}")
set_target_properties(OpenSSL::Crypto PROPERTIES
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
IMPORTED_LOCATION "${OPENSSL_CRYPTO_LIBRARY}")
endif()
if(EXISTS "${LIB_EAY_LIBRARY_RELEASE}")
set_property(TARGET OpenSSL::Crypto APPEND PROPERTY
IMPORTED_CONFIGURATIONS RELEASE)
set_target_properties(OpenSSL::Crypto PROPERTIES
IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C"
IMPORTED_LOCATION_RELEASE "${LIB_EAY_LIBRARY_RELEASE}")
endif()
if(EXISTS "${LIB_EAY_LIBRARY_DEBUG}")
set_property(TARGET OpenSSL::Crypto APPEND PROPERTY
IMPORTED_CONFIGURATIONS DEBUG)
set_target_properties(OpenSSL::Crypto PROPERTIES
IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "C"
IMPORTED_LOCATION_DEBUG "${LIB_EAY_LIBRARY_DEBUG}")
endif()
_OpenSSL_target_add_dependencies(OpenSSL::Crypto)
endif()
if(NOT TARGET OpenSSL::SSL AND
(EXISTS "${OPENSSL_SSL_LIBRARY}" OR
EXISTS "${SSL_EAY_LIBRARY_DEBUG}" OR
EXISTS "${SSL_EAY_LIBRARY_RELEASE}")
)
add_library(OpenSSL::SSL UNKNOWN IMPORTED)
set_target_properties(OpenSSL::SSL PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${OPENSSL_INCLUDE_DIR}")
if(EXISTS "${OPENSSL_SSL_LIBRARY}")
set_target_properties(OpenSSL::SSL PROPERTIES
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
IMPORTED_LOCATION "${OPENSSL_SSL_LIBRARY}")
endif()
if(EXISTS "${SSL_EAY_LIBRARY_RELEASE}")
set_property(TARGET OpenSSL::SSL APPEND PROPERTY
IMPORTED_CONFIGURATIONS RELEASE)
set_target_properties(OpenSSL::SSL PROPERTIES
IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C"
IMPORTED_LOCATION_RELEASE "${SSL_EAY_LIBRARY_RELEASE}")
endif()
if(EXISTS "${SSL_EAY_LIBRARY_DEBUG}")
set_property(TARGET OpenSSL::SSL APPEND PROPERTY
IMPORTED_CONFIGURATIONS DEBUG)
set_target_properties(OpenSSL::SSL PROPERTIES
IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "C"
IMPORTED_LOCATION_DEBUG "${SSL_EAY_LIBRARY_DEBUG}")
endif()
if(TARGET OpenSSL::Crypto)
set_target_properties(OpenSSL::SSL PROPERTIES
INTERFACE_LINK_LIBRARIES OpenSSL::Crypto)
endif()
_OpenSSL_target_add_dependencies(OpenSSL::SSL)
endif()
if("${OPENSSL_VERSION_MAJOR}.${OPENSSL_VERSION_MAJOR}.${OPENSSL_VERSION_FIX}" VERSION_GREATER_EQUAL "0.9.8")
if(MSVC)
if(EXISTS "${OPENSSL_INCLUDE_DIR}")
set(_OPENSSL_applink_paths PATHS ${OPENSSL_INCLUDE_DIR})
endif()
find_file(OPENSSL_APPLINK_SOURCE
NAMES
openssl/applink.c
${_OPENSSL_applink_paths}
NO_DEFAULT_PATH)
if(OPENSSL_APPLINK_SOURCE)
set(_OPENSSL_applink_interface_srcs ${OPENSSL_APPLINK_SOURCE})
endif()
endif()
if(NOT TARGET OpenSSL::applink)
add_library(OpenSSL::applink INTERFACE IMPORTED)
set_property(TARGET OpenSSL::applink APPEND
PROPERTY INTERFACE_SOURCES
${_OPENSSL_applink_interface_srcs})
endif()
endif()
endif()
# Restore the original find library ordering
if(OPENSSL_USE_STATIC_LIBS)
set(CMAKE_FIND_LIBRARY_SUFFIXES ${_openssl_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES})
endif()

View File

@ -1,6 +1,18 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
* Copyright (C) 2021+ WarheadCore <https://github.com/WarheadCore>
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 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 Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "AES.h"
@ -30,34 +42,24 @@ bool Acore::Crypto::AES::Process(IV const& iv, uint8* data, size_t length, Tag&
ASSERT(length <= static_cast<size_t>(std::numeric_limits<int>::max()));
int len = static_cast<int>(length);
if (!EVP_CipherInit_ex(_ctx, nullptr, nullptr, nullptr, iv.data(), -1))
{
return false;
}
int outLen;
if (!EVP_CipherUpdate(_ctx, data, &outLen, data, len))
{
return false;
}
len -= outLen;
if (!_encrypting && !EVP_CIPHER_CTX_ctrl(_ctx, EVP_CTRL_GCM_SET_TAG, sizeof(tag), tag))
{
return false;
}
if (!EVP_CipherFinal_ex(_ctx, data + outLen, &outLen))
{
return false;
}
ASSERT(len == outLen);
if (_encrypting && !EVP_CIPHER_CTX_ctrl(_ctx, EVP_CTRL_GCM_GET_TAG, sizeof(tag), tag))
{
return false;
}
return true;
}

View File

@ -1,10 +1,22 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
* Copyright (C) 2021+ WarheadCore <https://github.com/WarheadCore>
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 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 Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef Warhead_AES_h__
#define Warhead_AES_h__
#ifndef Azeroth_AES_h__
#define Azeroth_AES_h__
#include "Define.h"
#include <array>
@ -36,4 +48,4 @@ namespace Acore::Crypto
};
}
#endif // Warhead_AES_h__
#endif // Azeroth_AES_h__

View File

@ -18,17 +18,26 @@
#include "ARC4.h"
#include "Errors.h"
Acore::Crypto::ARC4::ARC4()
: _ctx(EVP_CIPHER_CTX_new())
Acore::Crypto::ARC4::ARC4() : _ctx(EVP_CIPHER_CTX_new())
{
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
_cipher = EVP_CIPHER_fetch(nullptr, "RC4", nullptr);
#else
EVP_CIPHER const* _cipher = EVP_rc4();
#endif
EVP_CIPHER_CTX_init(_ctx);
int result = EVP_EncryptInit_ex(_ctx, EVP_rc4(), nullptr, nullptr, nullptr);
int result = EVP_EncryptInit_ex(_ctx, _cipher, nullptr, nullptr, nullptr);
ASSERT(result == 1);
}
Acore::Crypto::ARC4::~ARC4()
{
EVP_CIPHER_CTX_free(_ctx);
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
EVP_CIPHER_free(_cipher);
#endif
}
void Acore::Crypto::ARC4::Init(uint8 const* seed, size_t len)

View File

@ -24,20 +24,25 @@
namespace Acore::Crypto
{
class ARC4
class AC_COMMON_API ARC4
{
public:
ARC4();
~ARC4();
void Init(uint8 const* seed, size_t len);
template <typename Container>
void Init(Container const& c) { Init(std::data(c), std::size(c)); }
void UpdateData(uint8* data, size_t len);
template <typename Container>
void UpdateData(Container& c) { UpdateData(std::data(c), std::size(c)); }
private:
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
EVP_CIPHER* _cipher;
#endif
EVP_CIPHER_CTX* _ctx;
};
}

View File

@ -1,6 +1,18 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
* Copyright (C) 2021+ WarheadCore <https://github.com/WarheadCore>
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 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 Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Argon2.h"
@ -20,9 +32,7 @@
);
if (status == ARGON2_OK)
{
return std::string(buf);
}
return {};
}

View File

@ -1,15 +1,25 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
* Copyright (C) 2021+ WarheadCore <https://github.com/WarheadCore>
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 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 Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef WARHEAD_ARGON2_H
#define WARHEAD_ARGON2_H
#ifndef AC_ARGON2_H
#define AC_ARGON2_H
#include "BigNumber.h"
#include "Define.h"
#include "Optional.h"
#include <string>
namespace Acore::Crypto
{

View File

@ -19,19 +19,16 @@
#include "Errors.h"
#include "HMAC.h"
AuthCrypt::AuthCrypt() : _initialized(false)
{
}
void AuthCrypt::Init(SessionKey const& K)
{
uint8 ServerEncryptionKey[] = { 0xCC, 0x98, 0xAE, 0x04, 0xE8, 0x97, 0xEA, 0xCA, 0x12, 0xDD, 0xC0, 0x93, 0x42, 0x91, 0x53, 0x57 };
_serverEncrypt.Init(Acore::Crypto::HMAC_SHA1::GetDigestOf(ServerEncryptionKey, K));
uint8 ServerDecryptionKey[] = { 0xC2, 0xB3, 0x72, 0x3C, 0xC6, 0xAE, 0xD9, 0xB5, 0x34, 0x3C, 0x53, 0xEE, 0x2F, 0x43, 0x67, 0xCE };
_clientDecrypt.Init(Acore::Crypto::HMAC_SHA1::GetDigestOf(ServerDecryptionKey, K));
// Drop first 1024 bytes, as WoW uses ARC4-drop1024.
std::array<uint8, 1024> syncBuf;
std::array<uint8, 1024> syncBuf{};
_serverEncrypt.UpdateData(syncBuf);
_clientDecrypt.UpdateData(syncBuf);

View File

@ -20,12 +20,11 @@
#include "ARC4.h"
#include "AuthDefines.h"
#include <array>
class AuthCrypt
class AC_COMMON_API AuthCrypt
{
public:
AuthCrypt();
AuthCrypt() = default;
void Init(SessionKey const& K);
void DecryptRecv(uint8* data, size_t len);
@ -36,6 +35,6 @@ public:
private:
Acore::Crypto::ARC4 _clientDecrypt;
Acore::Crypto::ARC4 _serverEncrypt;
bool _initialized;
bool _initialized{ false };
};
#endif

View File

@ -50,8 +50,8 @@ using SRP6 = Acore::Crypto::SRP6;
/*static*/ SessionKey SRP6::SHA1Interleave(SRP6::EphemeralKey const& S)
{
// split S into two buffers
std::array<uint8, EPHEMERAL_KEY_LENGTH/2> buf0, buf1;
for (size_t i = 0; i < EPHEMERAL_KEY_LENGTH/2; ++i)
std::array<uint8, EPHEMERAL_KEY_LENGTH / 2> buf0{}, buf1{};
for (size_t i = 0; i < EPHEMERAL_KEY_LENGTH / 2; ++i)
{
buf0[i] = S[2 * i + 0];
buf1[i] = S[2 * i + 1];
@ -59,8 +59,12 @@ using SRP6 = Acore::Crypto::SRP6;
// find position of first nonzero byte
size_t p = 0;
while (p < EPHEMERAL_KEY_LENGTH && !S[p]) { ++p; }
if (p & 1) { ++p; } // skip one extra byte if p is odd
while (p < EPHEMERAL_KEY_LENGTH && !S[p])
++p;
if (p & 1)
++p; // skip one extra byte if p is odd
p /= 2; // offset into buffers
// hash each of the halves, starting at the first nonzero byte
@ -82,14 +86,12 @@ SRP6::SRP6(std::string const& username, Salt const& salt, Verifier const& verifi
std::optional<SessionKey> SRP6::VerifyChallengeResponse(EphemeralKey const& A, SHA1::Digest const& clientM)
{
ASSERT(!_used);
ASSERT(!_used, "A single SRP6 object must only ever be used to verify ONCE!");
_used = true;
BigNumber const _A(A);
if ((_A % _N).IsZero())
{
return std::nullopt;
}
BigNumber const u(SHA1::GetDigestOf(A, B));
EphemeralKey const S = (_A * (_v.ModExp(u, _N))).ModExp(_b, N).ToByteArray<32>();
@ -104,11 +106,7 @@ std::optional<SessionKey> SRP6::VerifyChallengeResponse(EphemeralKey const& A, S
SHA1::Digest const ourM = SHA1::GetDigestOf(NgHash, _I, s, A, B, K);
if (ourM == clientM)
{
return K;
}
else
{
return std::nullopt;
}
return std::nullopt;
}

View File

@ -20,21 +20,20 @@
#include "AuthDefines.h"
#include "BigNumber.h"
#include "Common.h"
#include "CryptoHash.h"
#include "Define.h"
#include <array>
#include <optional>
namespace Acore::Crypto
{
class SRP6
class AC_COMMON_API SRP6
{
public:
static constexpr size_t SALT_LENGTH = 32;
using Salt = std::array<uint8, SALT_LENGTH>;
static constexpr size_t VERIFIER_LENGTH = 32;
using Verifier = std::array<uint8, VERIFIER_LENGTH>;
static constexpr size_t EPHEMERAL_KEY_LENGTH = 32;
using EphemeralKey = std::array<uint8, EPHEMERAL_KEY_LENGTH>;
@ -43,6 +42,7 @@ namespace Acore::Crypto
// username + password must be passed through Utf8ToUpperOnlyLatin FIRST!
static std::pair<Salt, Verifier> MakeRegistrationData(std::string const& username, std::string const& password);
// username + password must be passed through Utf8ToUpperOnlyLatin FIRST!
static bool CheckLogin(std::string const& username, std::string const& password, Salt const& salt, Verifier const& verifier)
{

View File

@ -1,11 +1,25 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
* Copyright (C) 2021+ WarheadCore <https://github.com/WarheadCore>
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 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 Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Cryptography/BigNumber.h"
#include "BigNumber.h"
#include "Errors.h"
#include <algorithm>
#include <cstring>
#include <memory>
#include <openssl/bn.h>
BigNumber::BigNumber()
@ -25,9 +39,7 @@ void BigNumber::SetDword(int32 val)
{
SetDword(uint32(std::abs(val)));
if (val < 0)
{
BN_set_negative(_bn, 1);
}
}
void BigNumber::SetDword(uint32 val)
@ -50,9 +62,7 @@ void BigNumber::SetBinary(uint8 const* bytes, int32 len, bool littleEndian)
uint8* array = new uint8[len];
for (int i = 0; i < len; i++)
{
array[i] = bytes[len - 1 - i];
}
BN_bin2bn(array, len, _bn);
@ -62,9 +72,7 @@ void BigNumber::SetBinary(uint8 const* bytes, int32 len, bool littleEndian)
#endif
}
else
{
BN_bin2bn(bytes, len, _bn);
}
}
bool BigNumber::SetHexStr(char const* str)
@ -81,9 +89,7 @@ void BigNumber::SetRand(int32 numbits)
BigNumber& BigNumber::operator=(BigNumber const& bn)
{
if (this == &bn)
{
return *this;
}
BN_copy(_bn, bn._bn);
return *this;
@ -103,7 +109,7 @@ BigNumber& BigNumber::operator-=(BigNumber const& bn)
BigNumber& BigNumber::operator*=(BigNumber const& bn)
{
BN_CTX* bnctx;
BN_CTX *bnctx;
bnctx = BN_CTX_new();
BN_mul(_bn, _bn, bn._bn, bnctx);
@ -114,7 +120,7 @@ BigNumber& BigNumber::operator*=(BigNumber const& bn)
BigNumber& BigNumber::operator/=(BigNumber const& bn)
{
BN_CTX* bnctx;
BN_CTX *bnctx;
bnctx = BN_CTX_new();
BN_div(_bn, nullptr, _bn, bn._bn, bnctx);
@ -125,7 +131,7 @@ BigNumber& BigNumber::operator/=(BigNumber const& bn)
BigNumber& BigNumber::operator%=(BigNumber const& bn)
{
BN_CTX* bnctx;
BN_CTX *bnctx;
bnctx = BN_CTX_new();
BN_mod(_bn, _bn, bn._bn, bnctx);
@ -148,7 +154,7 @@ int BigNumber::CompareTo(BigNumber const& bn) const
BigNumber BigNumber::Exp(BigNumber const& bn) const
{
BigNumber ret;
BN_CTX* bnctx;
BN_CTX *bnctx;
bnctx = BN_CTX_new();
BN_exp(ret._bn, _bn, bn._bn, bnctx);
@ -160,7 +166,7 @@ BigNumber BigNumber::Exp(BigNumber const& bn) const
BigNumber BigNumber::ModExp(BigNumber const& bn1, BigNumber const& bn2) const
{
BigNumber ret;
BN_CTX* bnctx;
BN_CTX *bnctx;
bnctx = BN_CTX_new();
BN_mod_exp(ret._bn, _bn, bn1._bn, bn2._bn, bnctx);
@ -201,17 +207,13 @@ void BigNumber::GetBytes(uint8* buf, size_t bufsize, bool littleEndian) const
// If we need more bytes than length of BigNumber set the rest to 0
if (numBytes < bufsize)
{
memset((void*)buf, 0, bufsize);
}
BN_bn2bin(_bn, buf + (bufsize - numBytes));
// openssl's BN stores data internally in big endian format, reverse if little endian desired
if (littleEndian)
{
std::reverse(buf, buf + bufsize);
}
#else
int res = littleEndian ? BN_bn2lebinpad(_bn, buf, bufsize) : BN_bn2binpad(_bn, buf, bufsize);
ASSERT(res > 0, "Buffer of size {} is too small to hold bignum with {} bytes.\n", bufsize, BN_num_bytes(_bn));

View File

@ -1,6 +1,18 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
* Copyright (C) 2021+ WarheadCore <https://github.com/WarheadCore>
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 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 Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _AUTH_BIGNUMBER_H
@ -8,7 +20,6 @@
#include "Define.h"
#include <array>
#include <memory>
#include <string>
#include <vector>

View File

@ -24,7 +24,8 @@ namespace Acore::Crypto
{
struct Constants
{
static constexpr size_t SHA1_DIGEST_LENGTH_BYTES = 20;
static constexpr size_t MD5_DIGEST_LENGTH_BYTES = 16;
static constexpr size_t SHA1_DIGEST_LENGTH_BYTES = 20;
static constexpr size_t SHA256_DIGEST_LENGTH_BYTES = 32;
};
}

View File

@ -89,6 +89,7 @@ namespace Acore::Crypto
{
using IV = typename Cipher::IV;
using Tag = typename Cipher::Tag;
// extract trailing IV and tag
IV iv;
Tag tag;

View File

@ -19,12 +19,12 @@
#define AZEROTHCORE_CRYPTOHASH_H
#include "CryptoConstants.h"
#include "Define.h"
#include "Errors.h"
#include <array>
#include <openssl/evp.h>
#include <string>
#include <string_view>
#include <utility>
class BigNumber;
@ -35,10 +35,10 @@ namespace Acore::Impl
typedef EVP_MD const* (*HashCreator)();
#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10100000L
static EVP_MD_CTX* MakeCTX() { return EVP_MD_CTX_create(); }
static EVP_MD_CTX* MakeCTX() noexcept { return EVP_MD_CTX_create(); }
static void DestroyCTX(EVP_MD_CTX* ctx) { EVP_MD_CTX_destroy(ctx); }
#else
static EVP_MD_CTX* MakeCTX() { return EVP_MD_CTX_new(); }
static EVP_MD_CTX* MakeCTX() noexcept { return EVP_MD_CTX_new(); }
static void DestroyCTX(EVP_MD_CTX* ctx) { EVP_MD_CTX_free(ctx); }
#endif
};
@ -46,74 +46,104 @@ namespace Acore::Impl
template <GenericHashImpl::HashCreator HashCreator, size_t DigestLength>
class GenericHash
{
public:
static constexpr size_t DIGEST_LENGTH = DigestLength;
using Digest = std::array<uint8, DIGEST_LENGTH>;
public:
static constexpr size_t DIGEST_LENGTH = DigestLength;
using Digest = std::array<uint8, DIGEST_LENGTH>;
static Digest GetDigestOf(uint8 const* data, size_t len)
{
GenericHash hash;
hash.UpdateData(data, len);
hash.Finalize();
return hash.GetDigest();
}
template <typename... Ts>
static auto GetDigestOf(Ts&& ... pack) -> std::enable_if_t < !(std::is_integral_v<std::decay_t<Ts>> || ...), Digest >
{
GenericHash hash;
(hash.UpdateData(std::forward<Ts>(pack)), ...);
hash.Finalize();
return hash.GetDigest();
}
GenericHash() : _ctx(GenericHashImpl::MakeCTX())
{
int result = EVP_DigestInit_ex(_ctx, HashCreator(), nullptr);
ASSERT(result == 1);
}
~GenericHash()
{
if (!_ctx)
static Digest GetDigestOf(uint8 const* data, size_t len)
{
return;
GenericHash hash;
hash.UpdateData(data, len);
hash.Finalize();
return hash.GetDigest();
}
GenericHashImpl::DestroyCTX(_ctx);
_ctx = nullptr;
}
void UpdateData(uint8 const* data, size_t len)
{
int result = EVP_DigestUpdate(_ctx, data, len);
ASSERT(result == 1);
}
void UpdateData(std::string_view str) { UpdateData(reinterpret_cast<uint8 const*>(str.data()), str.size()); }
void UpdateData(std::string const& str) { UpdateData(std::string_view(str)); } /* explicit overload to avoid using the container template */
void UpdateData(char const* str) { UpdateData(std::string_view(str)); } /* explicit overload to avoid using the container template */
template <typename Container>
void UpdateData(Container const& c) { UpdateData(std::data(c), std::size(c)); }
template <typename... Ts>
static auto GetDigestOf(Ts&&... pack) -> std::enable_if_t<!(std::is_integral_v<std::decay_t<Ts>> || ...), Digest>
{
GenericHash hash;
(hash.UpdateData(std::forward<Ts>(pack)), ...);
hash.Finalize();
return hash.GetDigest();
}
void Finalize()
{
uint32 length;
int result = EVP_DigestFinal_ex(_ctx, _digest.data(), &length);
ASSERT(result == 1);
ASSERT(length == DIGEST_LENGTH);
GenericHashImpl::DestroyCTX(_ctx);
_ctx = nullptr;
}
GenericHash() : _ctx(GenericHashImpl::MakeCTX())
{
int result = EVP_DigestInit_ex(_ctx, HashCreator(), nullptr);
ASSERT(result == 1);
}
Digest const& GetDigest() const { return _digest; }
GenericHash(GenericHash const& right) : _ctx(GenericHashImpl::MakeCTX())
{
*this = right;
}
private:
EVP_MD_CTX* _ctx;
Digest _digest = { };
GenericHash(GenericHash&& right) noexcept
{
*this = std::move(right);
}
~GenericHash()
{
if (!_ctx)
return;
GenericHashImpl::DestroyCTX(_ctx);
_ctx = nullptr;
}
GenericHash& operator=(GenericHash const& right)
{
if (this == &right)
return *this;
int result = EVP_MD_CTX_copy_ex(_ctx, right._ctx);
ASSERT(result == 1);
_digest = right._digest;
return *this;
}
GenericHash& operator=(GenericHash&& right) noexcept
{
if (this == &right)
return *this;
_ctx = std::exchange(right._ctx, GenericHashImpl::MakeCTX());
_digest = std::exchange(right._digest, Digest{});
return *this;
}
void UpdateData(uint8 const* data, size_t len)
{
int result = EVP_DigestUpdate(_ctx, data, len);
ASSERT(result == 1);
}
void UpdateData(std::string_view str) { UpdateData(reinterpret_cast<uint8 const*>(str.data()), str.size()); }
void UpdateData(std::string const& str) { UpdateData(std::string_view(str)); } /* explicit overload to avoid using the container template */
void UpdateData(char const* str) { UpdateData(std::string_view(str)); } /* explicit overload to avoid using the container template */
template <typename Container>
void UpdateData(Container const& c) { UpdateData(std::data(c), std::size(c)); }
void Finalize()
{
uint32 length;
int result = EVP_DigestFinal_ex(_ctx, _digest.data(), &length);
ASSERT(result == 1);
ASSERT(length == DIGEST_LENGTH);
}
Digest const& GetDigest() const { return _digest; }
private:
EVP_MD_CTX* _ctx{};
Digest _digest{};
};
}
namespace Acore::Crypto
{
using MD5 = Acore::Impl::GenericHash<EVP_md5, Constants::MD5_DIGEST_LENGTH_BYTES>;
using SHA1 = Acore::Impl::GenericHash<EVP_sha1, Constants::SHA1_DIGEST_LENGTH_BYTES>;
using SHA256 = Acore::Impl::GenericHash<EVP_sha256, Constants::SHA256_DIGEST_LENGTH_BYTES>;
}

View File

@ -22,5 +22,5 @@
void Acore::Crypto::GetRandomBytes(uint8* buf, size_t len)
{
int result = RAND_bytes(buf, len);
ASSERT(result == 1);
ASSERT(result == 1, "Not enough randomness in OpenSSL's entropy pool. What in the world are you running on?");
}

View File

@ -23,7 +23,7 @@
namespace Acore::Crypto
{
void GetRandomBytes(uint8* buf, size_t len);
AC_COMMON_API void GetRandomBytes(uint8* buf, size_t len);
template <typename Container>
void GetRandomBytes(Container& c)

View File

@ -19,10 +19,9 @@
#define AZEROTHCORE_HMAC_H
#include "CryptoConstants.h"
#include "Define.h"
#include "CryptoHash.h"
#include "Errors.h"
#include <array>
#include <openssl/hmac.h>
#include <string>
#include <string_view>
@ -30,96 +29,108 @@ class BigNumber;
namespace Acore::Impl
{
struct HMACImpl
{
typedef EVP_MD const* (*HashCreator)();
#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10100000L
static HMAC_CTX* MakeCTX()
{
HMAC_CTX* ctx = new HMAC_CTX();
HMAC_CTX_init(ctx);
return ctx;
}
static void DestroyCTX(HMAC_CTX* ctx)
{
HMAC_CTX_cleanup(ctx);
delete ctx;
}
#else
static HMAC_CTX* MakeCTX() { return HMAC_CTX_new(); }
static void DestroyCTX(HMAC_CTX* ctx) { HMAC_CTX_free(ctx); }
#endif
};
template <HMACImpl::HashCreator HashCreator, size_t DigestLength>
template <GenericHashImpl::HashCreator HashCreator, size_t DigestLength>
class GenericHMAC
{
public:
static constexpr size_t DIGEST_LENGTH = DigestLength;
using Digest = std::array<uint8, DIGEST_LENGTH>;
public:
static constexpr size_t DIGEST_LENGTH = DigestLength;
using Digest = std::array<uint8, DIGEST_LENGTH>;
template <typename Container>
static Digest GetDigestOf(Container const& seed, uint8 const* data, size_t len)
{
GenericHMAC hash(seed);
hash.UpdateData(data, len);
hash.Finalize();
return hash.GetDigest();
}
template <typename Container, typename... Ts>
static auto GetDigestOf(Container const& seed, Ts&& ... pack) -> std::enable_if_t < !(std::is_integral_v<std::decay_t<Ts>> || ...), Digest >
{
GenericHMAC hash(seed);
(hash.UpdateData(std::forward<Ts>(pack)), ...);
hash.Finalize();
return hash.GetDigest();
}
GenericHMAC(uint8 const* seed, size_t len) : _ctx(HMACImpl::MakeCTX())
{
int result = HMAC_Init_ex(_ctx, seed, len, HashCreator(), nullptr);
ASSERT(result == 1);
}
template <typename Container> GenericHMAC(Container const& container) : GenericHMAC(std::data(container), std::size(container)) {}
~GenericHMAC()
{
if (!_ctx)
template <typename Container>
static Digest GetDigestOf(Container const& seed, uint8 const* data, size_t len)
{
return;
GenericHMAC hash(seed);
hash.UpdateData(data, len);
hash.Finalize();
return hash.GetDigest();
}
HMACImpl::DestroyCTX(_ctx);
_ctx = nullptr;
}
void UpdateData(uint8 const* data, size_t len)
{
int result = HMAC_Update(_ctx, data, len);
ASSERT(result == 1);
}
void UpdateData(std::string_view str) { UpdateData(reinterpret_cast<uint8 const*>(str.data()), str.size()); }
void UpdateData(std::string const& str) { UpdateData(std::string_view(str)); } /* explicit overload to avoid using the container template */
void UpdateData(char const* str) { UpdateData(std::string_view(str)); } /* explicit overload to avoid using the container template */
template <typename Container>
void UpdateData(Container const& c) { UpdateData(std::data(c), std::size(c)); }
template <typename Container, typename... Ts>
static auto GetDigestOf(Container const& seed, Ts&&... pack) -> std::enable_if_t<!(std::is_integral_v<std::decay_t<Ts>> || ...), Digest>
{
GenericHMAC hash(seed);
(hash.UpdateData(std::forward<Ts>(pack)), ...);
hash.Finalize();
return hash.GetDigest();
}
void Finalize()
{
uint32 length = 0;
int result = HMAC_Final(_ctx, _digest.data(), &length);
ASSERT(result == 1);
ASSERT(length == DIGEST_LENGTH);
HMACImpl::DestroyCTX(_ctx);
_ctx = nullptr;
}
GenericHMAC(uint8 const* seed, size_t len) : _ctx(GenericHashImpl::MakeCTX()), _key(EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, nullptr, seed, len))
{
int result = EVP_DigestSignInit(_ctx, nullptr, HashCreator(), nullptr, _key);
ASSERT(result == 1);
}
Digest const& GetDigest() const { return _digest; }
private:
HMAC_CTX* _ctx;
Digest _digest = { };
template <typename Container>
GenericHMAC(Container const& container) : GenericHMAC(std::data(container), std::size(container)) {}
GenericHMAC(GenericHMAC const& right) : _ctx(GenericHashImpl::MakeCTX())
{
*this = right;
}
GenericHMAC(GenericHMAC&& right) noexcept
{
*this = std::move(right);
}
~GenericHMAC()
{
GenericHashImpl::DestroyCTX(_ctx);
_ctx = nullptr;
EVP_PKEY_free(_key);
_key = nullptr;
}
GenericHMAC& operator=(GenericHMAC const& right)
{
if (this == &right)
return *this;
int result = EVP_MD_CTX_copy_ex(_ctx, right._ctx);
ASSERT(result == 1);
_key = right._key; // EVP_PKEY uses reference counting internally, just copy the pointer
EVP_PKEY_up_ref(_key); // Bump reference count for PKEY, as every instance of this class holds two references to PKEY and destructor decrements it twice
_digest = right._digest;
return *this;
}
GenericHMAC& operator=(GenericHMAC&& right) noexcept
{
if (this == &right)
return *this;
_ctx = std::exchange(right._ctx, GenericHashImpl::MakeCTX());
_key = std::exchange(right._key, EVP_PKEY_new());
_digest = std::exchange(right._digest, Digest{});
return *this;
}
void UpdateData(uint8 const* data, size_t len)
{
int result = EVP_DigestSignUpdate(_ctx, data, len);
ASSERT(result == 1);
}
void UpdateData(std::string_view str) { UpdateData(reinterpret_cast<uint8 const*>(str.data()), str.size()); }
void UpdateData(std::string const& str) { UpdateData(std::string_view(str)); } /* explicit overload to avoid using the container template */
void UpdateData(char const* str) { UpdateData(std::string_view(str)); } /* explicit overload to avoid using the container template */
template <typename Container>
void UpdateData(Container const& c) { UpdateData(std::data(c), std::size(c)); }
void Finalize()
{
size_t length = DIGEST_LENGTH;
int result = EVP_DigestSignFinal(_ctx, _digest.data(), &length);
ASSERT(result == 1);
ASSERT(length == DIGEST_LENGTH);
}
Digest const& GetDigest() const { return _digest; }
private:
EVP_MD_CTX* _ctx{};
EVP_PKEY* _key{};
Digest _digest{};
};
}
@ -128,4 +139,5 @@ namespace Acore::Crypto
using HMAC_SHA1 = Acore::Impl::GenericHMAC<EVP_sha1, Constants::SHA1_DIGEST_LENGTH_BYTES>;
using HMAC_SHA256 = Acore::Impl::GenericHMAC<EVP_sha256, Constants::SHA256_DIGEST_LENGTH_BYTES>;
}
#endif

View File

@ -15,49 +15,90 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <OpenSSLCrypto.h>
#include "OpenSSLCrypto.h"
#include <openssl/crypto.h>
#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x1010000fL
#include <vector>
#include <thread>
#include <mutex>
std::vector<std::mutex*> cryptoLocks;
static void lockingCallback(int mode, int type, char const* /*file*/, int /*line*/)
{
if (mode & CRYPTO_LOCK)
{
cryptoLocks[type]->lock();
}
else
{
cryptoLocks[type]->unlock();
}
}
static void threadIdCallback(CRYPTO_THREADID* id)
static void threadIdCallback(CRYPTO_THREADID * id)
{
(void)id;
CRYPTO_THREADID_set_numeric(id, std::hash<std::thread::id>()(std::this_thread::get_id()));
}
#elif OPENSSL_VERSION_NUMBER >= 0x30000000L
#include <openssl/provider.h>
OSSL_PROVIDER* LegacyProvider;
OSSL_PROVIDER* DefaultProvider;
#endif
#if OPENSSL_VERSION_NUMBER >= 0x30000000L && AC_PLATFORM == AC_PLATFORM_WINDOWS
#include <boost/dll/runtime_symbol_info.hpp>
#include <filesystem>
void SetupLibrariesForWindows()
{
namespace fs = std::filesystem;
fs::path programLocation{ boost::dll::program_location().remove_filename().string() };
fs::path libLegacy{ boost::dll::program_location().remove_filename().string() + "/legacy.dll" };
ASSERT(fs::exists(libLegacy), "Not found 'legacy.dll'. Please copy library 'legacy.dll' from OpenSSL default dir to '{}'", programLocation.generic_string());
OSSL_PROVIDER_set_default_search_path(nullptr, programLocation.generic_string().c_str());
}
#endif
void OpenSSLCrypto::threadsSetup()
{
#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x1010000fL
cryptoLocks.resize(CRYPTO_num_locks());
for (int i = 0 ; i < CRYPTO_num_locks(); ++i)
{
cryptoLocks[i] = new std::mutex();
}
(void)&threadIdCallback;
CRYPTO_THREADID_set_callback(threadIdCallback);
(void)&lockingCallback;
CRYPTO_set_locking_callback(lockingCallback);
#elif OPENSSL_VERSION_NUMBER >= 0x30000000L
#if AC_PLATFORM == AC_PLATFORM_WINDOWS
SetupLibrariesForWindows();
#endif
LegacyProvider = OSSL_PROVIDER_load(nullptr, "legacy");
DefaultProvider = OSSL_PROVIDER_load(nullptr, "default");
#endif
}
void OpenSSLCrypto::threadsCleanup()
{
#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x1010000fL
CRYPTO_set_locking_callback(nullptr);
CRYPTO_THREADID_set_callback(nullptr);
for (int i = 0 ; i < CRYPTO_num_locks(); ++i)
{
delete cryptoLocks[i];
}
cryptoLocks.resize(0);
}
#elif OPENSSL_VERSION_NUMBER >= 0x30000000L
OSSL_PROVIDER_unload(LegacyProvider);
OSSL_PROVIDER_unload(DefaultProvider);
OSSL_PROVIDER_set_default_search_path(nullptr, nullptr);
#endif
}

View File

@ -15,11 +15,10 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef OPENSSL_CRYPTO_H_
#define OPENSSL_CRYPTO_H_
#ifndef _AC_OPENSSL_CRYPTO_H
#define _AC_OPENSSL_CRYPTO_H
#include "Define.h"
#include <openssl/opensslv.h>
/**
* A group of functions which setup openssl crypto module to work properly in multithreaded enviroment
@ -27,17 +26,11 @@
*/
namespace OpenSSLCrypto
{
#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x1010000fL
/// Needs to be called before threads using openssl are spawned
void threadsSetup();
/// Needs to be called after threads using openssl are despawned
void threadsCleanup();
#else
void threadsSetup() { };
void threadsCleanup() { };
#endif
AC_COMMON_API void threadsSetup();
/// Needs to be called after threads using openssl are despawned
AC_COMMON_API void threadsCleanup();
}
#endif

View File

@ -15,17 +15,18 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "CryptoHash.h"
#include <cstring>
#ifndef AZEROTHCORE_SESSIONKEYGENERATOR_HPP
#define AZEROTHCORE_SESSIONKEYGENERATOR_HPP
#include "CryptoHash.h"
#include <cstring>
template <typename Hash>
class SessionKeyGenerator
{
public:
template <typename C> SessionKeyGenerator(C const& buf) :
template <typename C>
SessionKeyGenerator(C const& buf) :
o0it(o0.begin())
{
uint8 const* data = std::data(buf);
@ -52,9 +53,9 @@ public:
}
private:
typename Hash::Digest o0 = { };
typename Hash::Digest o1 = { };
typename Hash::Digest o2 = { };
typename Hash::Digest o0{};
typename Hash::Digest o1{};
typename Hash::Digest o2{};
typename Hash::Digest::const_iterator o0it;
};

View File

@ -28,11 +28,8 @@ static constexpr uint32 HMAC_RESULT_SIZE = 20;
{
timestamp /= TOTP_INTERVAL;
unsigned char challenge[8];
for (int i = 8; i--; timestamp >>= 8)
{
challenge[i] = timestamp;
}
unsigned char digest[HMAC_RESULT_SIZE];
uint32 digestSize = HMAC_RESULT_SIZE;
@ -41,7 +38,6 @@ static constexpr uint32 HMAC_RESULT_SIZE = 20;
uint32 offset = digest[19] & 0xF;
uint32 truncated = (digest[offset] << 24) | (digest[offset + 1] << 16) | (digest[offset + 2] << 8) | (digest[offset + 3]);
truncated &= 0x7FFFFFFF;
return (truncated % 1000000);
}

View File

@ -1,6 +1,18 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
* Copyright (C) 2021+ WarheadCore <https://github.com/WarheadCore>
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 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 Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef WARHEAD_TOTP_H

View File

@ -35,6 +35,7 @@
#include "IoContext.h"
#include "Log.h"
#include "MySQLThreading.h"
#include "OpenSSLCrypto.h"
#include "ProcessPriority.h"
#include "RealmList.h"
#include "SecretMgr.h"
@ -96,10 +97,14 @@ int main(int argc, char** argv)
[]()
{
LOG_INFO("server.authserver", "> Using configuration file {}", sConfigMgr->GetFilename());
LOG_INFO("server.authserver", "> Using SSL version: {} (library: {})", OPENSSL_VERSION_TEXT, SSLeay_version(SSLEAY_VERSION));
LOG_INFO("server.authserver", "> Using SSL version: {} (library: {})", OPENSSL_VERSION_TEXT, OpenSSL_version(OPENSSL_VERSION));
LOG_INFO("server.authserver", "> Using Boost version: {}.{}.{}", BOOST_VERSION / 100000, BOOST_VERSION / 100 % 1000, BOOST_VERSION % 100);
});
OpenSSLCrypto::threadsSetup();
std::shared_ptr<void> opensslHandle(nullptr, [](void*) { OpenSSLCrypto::threadsCleanup(); });
// authserver PID file creation
std::string pidFile = sConfigMgr->GetOption<std::string>("PidFile", "");
if (!pidFile.empty())

View File

@ -160,7 +160,7 @@ int main(int argc, char** argv)
[]()
{
LOG_INFO("server.worldserver", "> Using configuration file {}", sConfigMgr->GetFilename());
LOG_INFO("server.worldserver", "> Using SSL version: {} (library: {})", OPENSSL_VERSION_TEXT, SSLeay_version(SSLEAY_VERSION));
LOG_INFO("server.worldserver", "> Using SSL version: {} (library: {})", OPENSSL_VERSION_TEXT, OpenSSL_version(OPENSSL_VERSION));
LOG_INFO("server.worldserver", "> Using Boost version: {}.{}.{}", BOOST_VERSION / 100000, BOOST_VERSION / 100 % 1000, BOOST_VERSION % 100);
});

View File

@ -17,10 +17,10 @@
#include "AddonMgr.h"
#include "DatabaseEnv.h"
#include "CryptoHash.h"
#include "Log.h"
#include "Timer.h"
#include <list>
#include <openssl/md5.h>
namespace AddonMgr
{
@ -66,6 +66,7 @@ namespace AddonMgr
oldMSTime = getMSTime();
result = CharacterDatabase.Query("SELECT id, name, version, UNIX_TIMESTAMP(timestamp) FROM banned_addons");
if (result)
{
uint32 count2 = 0;
@ -78,14 +79,10 @@ namespace AddonMgr
BannedAddon addon{};
addon.Id = fields[0].Get<uint32>() + offset;
addon.Timestamp = uint32(fields[3].Get<uint64>());
addon.NameMD5 = Acore::Crypto::MD5::GetDigestOf(fields[1].Get<std::string>());
addon.VersionMD5 = Acore::Crypto::MD5::GetDigestOf(fields[2].Get<std::string>());
std::string name = fields[1].Get<std::string>();
std::string version = fields[2].Get<std::string>();
MD5(reinterpret_cast<uint8 const*>(name.c_str()), name.length(), addon.NameMD5);
MD5(reinterpret_cast<uint8 const*>(version.c_str()), version.length(), addon.VersionMD5);
m_bannedAddons.push_back(addon);
m_bannedAddons.emplace_back(addon);
++count2;
} while (result->NextRow());

View File

@ -19,6 +19,7 @@
#define _ADDONMGR_H
#include "Define.h"
#include <array>
#include <list>
#include <string>
#include <utility>
@ -49,8 +50,8 @@ struct SavedAddon
struct BannedAddon
{
uint32 Id;
uint8 NameMD5[16];
uint8 VersionMD5[16];
std::array<uint8, 16> NameMD5;
std::array<uint8, 16> VersionMD5;
uint32 Timestamp;
};

View File

@ -1254,8 +1254,8 @@ void WorldSession::SendAddonsInfo()
for (AddonMgr::BannedAddonList::const_iterator itr = bannedAddons->begin(); itr != bannedAddons->end(); ++itr)
{
data << uint32(itr->Id);
data.append(itr->NameMD5, sizeof(itr->NameMD5));
data.append(itr->VersionMD5, sizeof(itr->VersionMD5));
data.append(itr->NameMD5);
data.append(itr->VersionMD5);
data << uint32(itr->Timestamp);
data << uint32(1); // IsBanned
}

View File

@ -18,7 +18,9 @@
#ifndef _WARDEN_MODULE_MAC_H
#define _WARDEN_MODULE_MAC_H
uint8 Module_0DBBF209A27B1E279A9FEC5C168A15F7_Data[9318] =
#include <array>
std::array<uint8, 9318> Module_0DBBF209A27B1E279A9FEC5C168A15F7_Data =
{
0x07, 0x0C, 0x44, 0xCD, 0xC9, 0xFB, 0x99, 0xBC, 0x7C, 0x77, 0xDC, 0xE8, 0x8D, 0x07, 0xBE, 0x55,
0x37, 0x5C, 0x84, 0x10, 0x23, 0xE1, 0x36, 0x5B, 0xF1, 0xBC, 0x60, 0xF3, 0x68, 0xBA, 0x60, 0x69,
@ -605,7 +607,7 @@ uint8 Module_0DBBF209A27B1E279A9FEC5C168A15F7_Data[9318] =
0x43, 0x82, 0xAA, 0x0C, 0xEE, 0x1B
};
uint8 Module_0DBBF209A27B1E279A9FEC5C168A15F7_Key[16] =
std::array<uint8, 16> Module_0DBBF209A27B1E279A9FEC5C168A15F7_Key =
{
0x5B, 0x27, 0x27, 0x01, 0x24, 0x56, 0xB4, 0xD4, 0x2D, 0xD0, 0x96, 0x77, 0x49, 0x51, 0xDC, 0x0A
};

View File

@ -19,7 +19,7 @@
#include "AccountMgr.h"
#include "BanMgr.h"
#include "ByteBuffer.h"
#include "Common.h"
#include "CryptoHash.h"
#include "Log.h"
#include "Opcodes.h"
#include "Player.h"
@ -28,7 +28,6 @@
#include "World.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include <openssl/sha.h>
Warden::Warden() : _session(nullptr), _checkTimer(10000/*10 sec*/), _clientResponseTimer(0),
_dataSent(false), _module(nullptr), _initialized(false)
@ -77,11 +76,11 @@ void Warden::RequestModule()
LOG_DEBUG("warden", "Request module");
// Create packet structure
WardenModuleUse request;
WardenModuleUse request{};
request.Command = WARDEN_SMSG_MODULE_USE;
memcpy(request.ModuleId, _module->Id, 16);
memcpy(request.ModuleKey, _module->Key, 16);
memcpy(request.ModuleId, _module->Id.data(), 16);
memcpy(request.ModuleKey, _module->Key.data(), 16);
request.Size = _module->CompressedSize;
EndianConvert(request.Size);
@ -155,30 +154,21 @@ bool Warden::IsValidCheckSum(uint32 checksum, const uint8* data, const uint16 le
}
}
struct keyData
union keyData
{
union
{
struct
{
uint8 bytes[20];
} bytes;
struct
{
uint32 ints[5];
} ints;
};
std::array<uint8, 20> bytes;
std::array<uint32, 5> ints;
};
uint32 Warden::BuildChecksum(const uint8* data, uint32 length)
{
keyData hash;
SHA1(data, length, hash.bytes.bytes);
keyData hash{};
hash.bytes = Acore::Crypto::SHA1::GetDigestOf(data, size_t(length));
uint32 checkSum = 0;
for (uint8 i = 0; i < 5; ++i)
{
checkSum = checkSum ^ hash.ints.ints[i];
checkSum = checkSum ^ hash.ints[i];
}
return checkSum;

View File

@ -91,10 +91,10 @@ struct WardenHashRequest
struct ClientWardenModule
{
uint8 Id[16];
uint8 Key[16];
uint32 CompressedSize;
uint8* CompressedData;
std::array<uint8, 16> Id{};
std::array<uint8, 16> Key{};
uint32 CompressedSize{};
uint8* CompressedData{};
};
class WorldSession;

View File

@ -25,15 +25,12 @@
#include "WardenModuleMac.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include <openssl/md5.h>
WardenMac::WardenMac() : Warden()
{
}
WardenMac::~WardenMac()
{
}
WardenMac::~WardenMac() = default;
void WardenMac::Init(WorldSession* pClient, SessionKey const& K)
{
@ -64,29 +61,21 @@ void WardenMac::Init(WorldSession* pClient, SessionKey const& K)
_module = GetModuleForClient();
LOG_DEBUG("warden", "Module Key: {}", Acore::Impl::ByteArrayToHexStr(_module->Key, 16));
LOG_DEBUG("warden", "Module ID: {}", Acore::Impl::ByteArrayToHexStr(_module->Id, 16));
LOG_DEBUG("warden", "Module Key: {}", ByteArrayToHexStr(_module->Key));
LOG_DEBUG("warden", "Module ID: {}", ByteArrayToHexStr(_module->Id));
RequestModule();
}
ClientWardenModule* WardenMac::GetModuleForClient()
{
ClientWardenModule* mod = new ClientWardenModule;
uint32 len = sizeof(Module_0DBBF209A27B1E279A9FEC5C168A15F7_Data);
auto mod = new ClientWardenModule;
// data assign
mod->CompressedSize = len;
mod->CompressedData = new uint8[len];
memcpy(mod->CompressedData, Module_0DBBF209A27B1E279A9FEC5C168A15F7_Data, len);
memcpy(mod->Key, Module_0DBBF209A27B1E279A9FEC5C168A15F7_Key, 16);
mod->CompressedSize = Module_0DBBF209A27B1E279A9FEC5C168A15F7_Data.size();
mod->CompressedData = Module_0DBBF209A27B1E279A9FEC5C168A15F7_Data.data();
// md5 hash
MD5_CTX ctx;
MD5_Init(&ctx);
MD5_Update(&ctx, mod->CompressedData, len);
MD5_Final((uint8*)&mod->Id, &ctx);
mod->Id = Acore::Crypto::MD5::GetDigestOf(mod->CompressedData, mod->CompressedSize);
return mod;
}
@ -100,7 +89,7 @@ void WardenMac::RequestHash()
LOG_DEBUG("warden", "Request hash");
// Create packet structure
WardenHashRequest Request;
WardenHashRequest Request{};
Request.Command = WARDEN_SMSG_HASH_REQUEST;
memcpy(Request.Seed, _seed, 16);
@ -242,7 +231,7 @@ void WardenMac::HandleData(ByteBuffer& buff)
sha1.UpdateData((uint8*)&magic, 4);
sha1.Finalize();
std::array<uint8, Acore::Crypto::SHA1::DIGEST_LENGTH> sha1Hash;
Acore::Crypto::SHA1::Digest sha1Hash{};
buff.read(sha1Hash.data(), sha1Hash.size());
if (sha1Hash != sha1.GetDigest())
@ -251,20 +240,15 @@ void WardenMac::HandleData(ByteBuffer& buff)
//found = true;
}
MD5_CTX ctx;
MD5_Init(&ctx);
MD5_Update(&ctx, str.c_str(), str.size());
uint8 ourMD5Hash[16];
MD5_Final(ourMD5Hash, &ctx);
auto ourMD5Hash = Acore::Crypto::MD5::GetDigestOf(str);
Acore::Crypto::MD5::Digest theirsMD5Hash{};
buff.read(theirsMD5Hash);
uint8 theirsMD5Hash[16];
buff.read(theirsMD5Hash, 16);
if (memcmp(ourMD5Hash, theirsMD5Hash, 16))
if (ourMD5Hash != theirsMD5Hash)
{
LOG_DEBUG("warden", "Handle data failed: MD5 hash is wrong!");
//found = true;
}
_session->KickPlayer("WardenMac");
_session->KickPlayer("WardenMac::HandleData");
}

View File

@ -31,7 +31,6 @@
#include "World.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include <openssl/md5.h>
// GUILD is the shortest string that has no client validation (RAID only sends if in a raid group)
static constexpr char _luaEvalPrefix[] = "local S,T,R=SendAddonMessage,function()";
@ -97,9 +96,7 @@ static WorldIntConfigs GetMaxWardenChecksForType(uint8 type)
WardenWin::WardenWin() : Warden(), _serverTicks(0) { }
WardenWin::~WardenWin()
{
}
WardenWin::~WardenWin() = default;
void WardenWin::Init(WorldSession* session, SessionKey const& k)
{
@ -121,14 +118,14 @@ void WardenWin::Init(WorldSession* session, SessionKey const& k)
_module = GetModuleForClient();
LOG_DEBUG("warden", "Module Key: {}", Acore::Impl::ByteArrayToHexStr(_module->Key, 16));
LOG_DEBUG("warden", "Module ID: {}", Acore::Impl::ByteArrayToHexStr(_module->Id, 16));
LOG_DEBUG("warden", "Module Key: {}", ByteArrayToHexStr(_module->Key));
LOG_DEBUG("warden", "Module ID: {}", ByteArrayToHexStr(_module->Id));
RequestModule();
}
ClientWardenModule* WardenWin::GetModuleForClient()
{
ClientWardenModule* mod = new ClientWardenModule;
auto mod = new ClientWardenModule;
uint32 length = sizeof(Module.Module);
@ -136,13 +133,10 @@ ClientWardenModule* WardenWin::GetModuleForClient()
mod->CompressedSize = length;
mod->CompressedData = new uint8[length];
memcpy(mod->CompressedData, Module.Module, length);
memcpy(mod->Key, Module.ModuleKey, 16);
memcpy(mod->Key.data(), Module.ModuleKey, 16);
// md5 hash
MD5_CTX ctx;
MD5_Init(&ctx);
MD5_Update(&ctx, mod->CompressedData, length);
MD5_Final((uint8*)&mod->Id, &ctx);
mod->Id = Acore::Crypto::MD5::GetDigestOf(mod->CompressedData, mod->CompressedSize);
return mod;
}
@ -152,7 +146,7 @@ void WardenWin::InitializeModule()
LOG_DEBUG("warden", "Initialize module");
// Create packet structure
WardenInitModuleRequest Request;
WardenInitModuleRequest Request{};
Request.Command1 = WARDEN_SMSG_MODULE_INITIALIZE;
Request.Size1 = 20;
Request.Unk1 = 1;
@ -209,7 +203,7 @@ void WardenWin::RequestHash()
LOG_DEBUG("warden", "Request hash");
// Create packet structure
WardenHashRequest Request;
WardenHashRequest Request{};
Request.Command = WARDEN_SMSG_HASH_REQUEST;
memcpy(Request.Seed, _seed, 16);

View File

@ -129,7 +129,7 @@ public:
}
handler->PSendSysMessage("%s", GitRevision::GetFullVersion());
handler->PSendSysMessage("Using SSL version: %s (library: %s)", OPENSSL_VERSION_TEXT, SSLeay_version(SSLEAY_VERSION));
handler->PSendSysMessage("Using SSL version: %s (library: %s)", OPENSSL_VERSION_TEXT, OpenSSL_version(OPENSSL_VERSION));
handler->PSendSysMessage("Using Boost version: %i.%i.%i", BOOST_VERSION / 100000, BOOST_VERSION / 100 % 1000, BOOST_VERSION % 100);
handler->PSendSysMessage("Using MySQL version: %u", MySQL::GetLibraryVersion());
handler->PSendSysMessage("Using CMake version: %s", GitRevision::GetCMakeVersion());

View File

@ -16,13 +16,13 @@
*/
#include "Banner.h"
#include "Common.h"
#include "Config.h"
#include "DatabaseEnv.h"
#include "DatabaseLoader.h"
#include "IoContext.h"
#include "Log.h"
#include "MySQLThreading.h"
#include "OpenSSLCrypto.h"
#include "Util.h"
#include <boost/program_options.hpp>
#include <boost/version.hpp>
@ -73,11 +73,15 @@ int main(int argc, char** argv)
[]()
{
LOG_INFO("dbimport", "> Using configuration file: {}", sConfigMgr->GetFilename());
LOG_INFO("dbimport", "> Using SSL version: {} (library: {})", OPENSSL_VERSION_TEXT, SSLeay_version(SSLEAY_VERSION));
LOG_INFO("dbimport", "> Using SSL version: {} (library: {})", OPENSSL_VERSION_TEXT, OpenSSL_version(OPENSSL_VERSION));
LOG_INFO("dbimport", "> Using Boost version: {}.{}.{}", BOOST_VERSION / 100000, BOOST_VERSION / 100 % 1000, BOOST_VERSION % 100);
}
);
OpenSSLCrypto::threadsSetup();
std::shared_ptr<void> opensslHandle(nullptr, [](void*) { OpenSSLCrypto::threadsCleanup(); });
// Initialize the database connection
if (!StartDB())
return 1;