From b29fba25d2f75d682ee31d37260ecdc68337d525 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Sat, 1 Oct 2022 18:22:05 +0100 Subject: [PATCH] Use system's LibreSSL or OpenSSL for SHA256 if found. --- CMakeLists.txt | 25 ++++ cmake-modules/FindLibreSSL.cmake | 227 +++++++++++++++++++++++++++++++ tests/CMakeLists.txt | 2 +- tests/sha256.cpp | 98 +++++++++++++ 4 files changed, 351 insertions(+), 1 deletion(-) create mode 100644 cmake-modules/FindLibreSSL.cmake create mode 100644 tests/sha256.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index f373389..3b11fb9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -128,4 +128,29 @@ else() set_property(TARGET aaruformat PROPERTY POSITION_INDEPENDENT_CODE FALSE) endif() +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake-modules") + +# include(FindLibreSSL.cmake) + +find_package(OpenSSL QUIET) +find_package(LibreSSL QUIET) + +if(OpenSSL_FOUND) + message("-- OpenSSL VERSION: ${OPENSSL_VERSION}") +endif() + +if(LIBRESSL_FOUND) + message("-- LibreSSL VERSION: ${LIBRESSL_VERSION}") +endif() + +if(OpenSSL_FOUND OR LIBRESSL_FOUND) + add_compile_definitions(AARU_HAS_SHA256) +endif() + +if(LIBRESSL_FOUND) + TARGET_LINK_LIBRARIES_WHOLE_ARCHIVE(aaruformat ${LIBRESSL_CRYPTO_LIBRARY}) +elseif(OpenSSL_FOUND) + TARGET_LINK_LIBRARIES_WHOLE_ARCHIVE(aaruformat ${OPENSSL_CRYPTO_LIBRARY}) +endif() + add_subdirectory(tests) \ No newline at end of file diff --git a/cmake-modules/FindLibreSSL.cmake b/cmake-modules/FindLibreSSL.cmake new file mode 100644 index 0000000..6e4de5b --- /dev/null +++ b/cmake-modules/FindLibreSSL.cmake @@ -0,0 +1,227 @@ +#[=======================================================================[ + +Copyright (c) 2019 John Norrbin + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +FindLibreSSL +------------ + +Find the LibreSSL encryption library. + +Optional Components +^^^^^^^^^^^^^^^^^^^ + +This module supports two optional components: SSL and TLS. Both +components have associated imported targets, as described below. + +Imported Targets +^^^^^^^^^^^^^^^^ + +This module defines the following imported targets: + +LibreSSL::Crypto + The LibreSSL crypto library, if found. + +LibreSSL::SSL + The LibreSSL ssl library, if found. Requires and includes LibreSSL::Crypto automatically. + +LibreSSL::TLS + The LibreSSL tls library, if found. Requires and includes LibreSSL::SSL and LibreSSL::Crypto automatically. + +Result Variables +^^^^^^^^^^^^^^^^ + +This module will set the following variables in your project: + +LIBRESSL_FOUND + System has the LibreSSL library. If no components are requested it only requires the crypto library. +LIBRESSL_INCLUDE_DIR + The LibreSSL include directory. +LIBRESSL_CRYPTO_LIBRARY + The LibreSSL crypto library. +LIBRESSL_SSL_LIBRARY + The LibreSSL SSL library. +LIBRESSL_TLS_LIBRARY + The LibreSSL TLS library. +LIBRESSL_LIBRARIES + All LibreSSL libraries. +LIBRESSL_VERSION + This is set to $major.$minor.$revision (e.g. 2.6.8). + +Hints +^^^^^ + +Set LIBRESSL_ROOT_DIR to the root directory of an LibreSSL installation. + +]=======================================================================] + +INCLUDE(FindPackageHandleStandardArgs) + +# Set Hints +set(_LIBRESSL_ROOT_HINTS + ${LIBRESSL_ROOT_DIR} + ENV LIBRESSL_ROOT_DIR + ) + +# Set Paths +if(WIN32) + file(TO_CMAKE_PATH "$ENV{PROGRAMFILES}" _programfiles) + set(_LIBRESSL_ROOT_PATHS + "${_programfiles}/LibreSSL" + ) + unset(_programfiles) +else() + set(_LIBRESSL_ROOT_PATHS + "/usr/local/" + ) +endif() + +# Combine +set(_LIBRESSL_ROOT_HINTS_AND_PATHS + HINTS ${_LIBRESSL_ROOT_HINTS} + PATHS ${_LIBRESSL_ROOT_PATHS} + ) + +# Find Include Path +find_path(LIBRESSL_INCLUDE_DIR + NAMES + tls.h + ${_LIBRESSL_ROOT_HINTS_AND_PATHS} + PATH_SUFFIXES + include + ) + +# Find Crypto Library +find_library(LIBRESSL_CRYPTO_LIBRARY + NAMES + libcrypto + crypto + NAMES_PER_DIR + ${_LIBRESSL_ROOT_HINTS_AND_PATHS} + PATH_SUFFIXES + lib + ) + +# Find SSL Library +find_library(LIBRESSL_SSL_LIBRARY + NAMES + libssl + ssl + NAMES_PER_DIR + ${_LIBRESSL_ROOT_HINTS_AND_PATHS} + PATH_SUFFIXES + lib + ) + +# Find TLS Library +find_library(LIBRESSL_TLS_LIBRARY + NAMES + libtls + tls + NAMES_PER_DIR + ${_LIBRESSL_ROOT_HINTS_AND_PATHS} + PATH_SUFFIXES + lib + ) + +# Set Libraries +set(LIBRESSL_LIBRARIES ${LIBRESSL_CRYPTO_LIBRARY} ${LIBRESSL_SSL_LIBRARY} ${LIBRESSL_TLS_LIBRARY}) + +# Mark Variables As Advanced +mark_as_advanced(LIBRESSL_INCLUDE_DIR LIBRESSL_LIBRARIES LIBRESSL_CRYPTO_LIBRARY LIBRESSL_SSL_LIBRARY LIBRESSL_TLS_LIBRARY) + +# Find Version File +if(LIBRESSL_INCLUDE_DIR AND EXISTS "${LIBRESSL_INCLUDE_DIR}/openssl/opensslv.h") + + # Get Version From File + file(STRINGS "${LIBRESSL_INCLUDE_DIR}/openssl/opensslv.h" OPENSSLV.H REGEX "#define LIBRESSL_VERSION_TEXT[ ]+\".*\"") + + # Match Version String + string(REGEX REPLACE ".*\".*([0-9]+)\\.([0-9]+)\\.([0-9]+)\"" "\\1;\\2;\\3" LIBRESSL_VERSION_LIST "${OPENSSLV.H}") + + # Split Parts + list(GET LIBRESSL_VERSION_LIST 0 LIBRESSL_VERSION_MAJOR) + list(GET LIBRESSL_VERSION_LIST 1 LIBRESSL_VERSION_MINOR) + list(GET LIBRESSL_VERSION_LIST 2 LIBRESSL_VERSION_REVISION) + + # Set Version String + set(LIBRESSL_VERSION "${LIBRESSL_VERSION_MAJOR}.${LIBRESSL_VERSION_MINOR}.${LIBRESSL_VERSION_REVISION}") + +endif() + +# Set Find Package Arguments +find_package_handle_standard_args(LibreSSL + REQUIRED_VARS + LIBRESSL_CRYPTO_LIBRARY + LIBRESSL_INCLUDE_DIR + VERSION_VAR + LIBRESSL_VERSION + HANDLE_COMPONENTS + FAIL_MESSAGE + "Could NOT find LibreSSL, try setting the path to LibreSSL using the LIBRESSL_ROOT_DIR environment variable" + ) + +# LibreSSL Found +if(LIBRESSL_FOUND) + + # Set LibreSSL::Crypto + if(NOT TARGET LibreSSL::Crypto AND EXISTS "${LIBRESSL_CRYPTO_LIBRARY}") + + # Add Library + add_library(LibreSSL::Crypto UNKNOWN IMPORTED) + + # Set Properties + set_target_properties( + LibreSSL::Crypto + PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${LIBRESSL_INCLUDE_DIR}" + IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION "${LIBRESSL_CRYPTO_LIBRARY}" + ) + + endif() # LibreSSL::Crypto + + # Set LibreSSL::SSL + if(NOT TARGET LibreSSL::SSL AND EXISTS "${LIBRESSL_SSL_LIBRARY}") + + # Add Library + add_library(LibreSSL::SSL UNKNOWN IMPORTED) + + # Set Properties + set_target_properties( + LibreSSL::SSL + PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${LIBRESSL_INCLUDE_DIR}" + IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION "${LIBRESSL_SSL_LIBRARY}" + INTERFACE_LINK_LIBRARIES LibreSSL::Crypto + ) + + endif() # LibreSSL::SSL + + # Set LibreSSL::TLS + if(NOT TARGET LibreSSL::TLS AND EXISTS "${LIBRESSL_TLS_LIBRARY}") + add_library(LibreSSL::TLS UNKNOWN IMPORTED) + set_target_properties( + LibreSSL::TLS + PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${LIBRESSL_INCLUDE_DIR}" + IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION "${LIBRESSL_TLS_LIBRARY}" + INTERFACE_LINK_LIBRARIES LibreSSL::SSL + ) + + endif() # LibreSSL::TLS + +endif(LIBRESSL_FOUND) \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index e135077..1342dab 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -22,5 +22,5 @@ file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/data.bin # 'Google_Tests_run' is the target name # 'test1.cpp tests2.cpp' are source files with tests -add_executable(tests_run crc64.cpp spamsum.cpp crc32.c crc32.h flac.cpp lzma.cpp) +add_executable(tests_run crc64.cpp spamsum.cpp crc32.c crc32.h flac.cpp lzma.cpp sha256.cpp) target_link_libraries(tests_run gtest gtest_main "aaruformat") diff --git a/tests/sha256.cpp b/tests/sha256.cpp new file mode 100644 index 0000000..c113ac9 --- /dev/null +++ b/tests/sha256.cpp @@ -0,0 +1,98 @@ +/* + * This file is part of the Aaru Data Preservation Suite. + * Copyright (c) 2019-2022 Natalia Portillo. + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of the + * License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifdef AARU_HAS_SHA256 + +#include +#include +#include + +#include "gtest/gtest.h" + +static const uint8_t* buffer; + +unsigned char expected_sha256[SHA256_DIGEST_LENGTH] = {0x4d, 0x1a, 0x6b, 0x8a, 0x54, 0x67, 0x00, 0xc4, 0x8e, 0xda, 0x70, + 0xd3, 0x39, 0x1c, 0x8f, 0x15, 0x8a, 0x8d, 0x12, 0xb2, 0x38, 0x92, + 0x89, 0x29, 0x50, 0x47, 0x8c, 0x41, 0x8e, 0x25, 0xcc, 0x39}; + +class sha256Fixture : public ::testing::Test +{ + public: + sha256Fixture() + { + // initialization; + // can also be done in SetUp() + } + + protected: + void SetUp() + { + char path[PATH_MAX]; + char filename[PATH_MAX]; + + getcwd(path, PATH_MAX); + snprintf(filename, PATH_MAX, "%s/data/random", path); + + FILE* file = fopen(filename, "rb"); + buffer = (const uint8_t*)malloc(1048576); + fread((void*)buffer, 1, 1048576, file); + fclose(file); + } + + void TearDown() { free((void*)buffer); } + + ~sha256Fixture() + { + // resources cleanup, no exceptions allowed + } + + // shared user data +}; + +#define EXPECT_ARRAY_EQ(reference, actual, element_count) \ + { \ + unsigned char* reference_ = static_cast(reference); \ + unsigned char* actual_ = static_cast(actual); \ + for(int cmp_i = 0; cmp_i < (element_count); cmp_i++) { EXPECT_EQ(reference_[cmp_i], actual_[cmp_i]); } \ + } + +TEST_F(sha256Fixture, sha256) +{ + SHA256_CTX* ctx; + unsigned char hash[SHA256_DIGEST_LENGTH]; + int ret; + + ctx = static_cast(malloc(sizeof(SHA256_CTX))); + + EXPECT_NE(nullptr, ctx); + + ret = SHA256_Init(ctx); + + EXPECT_EQ(ret, 1); + + ret = SHA256_Update(ctx, buffer, 1048576); + + EXPECT_EQ(ret, 1); + + ret = SHA256_Final(hash, ctx); + + EXPECT_EQ(ret, 1); + EXPECT_ARRAY_EQ(expected_sha256, hash, SHA256_DIGEST_LENGTH); +} + +#endif \ No newline at end of file