From b7959f5b0171234a4b2988fd1fb01c5a743e4dda Mon Sep 17 00:00:00 2001 From: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com> Date: Mon, 20 Nov 2017 15:23:28 -0500 Subject: [PATCH] security: extract DhParams from TlsSession TlsSession will be refactored to handle DTLS and TLS. This patch cleanup TlsSession files to process further. Change-Id: I76b6ac73d9fe46ee6a18c6c9d725f6fcadb465d9 Reviewed-by: Olivier Soldano <olivier.soldano@savoirfairelinux.com> --- src/ringdht/ringaccount.h | 1 + src/security/Makefile.am | 4 +- src/security/diffie-hellman.cpp | 103 ++++++++++++++++++++++++++++++++ src/security/diffie-hellman.h | 71 ++++++++++++++++++++++ src/security/tls_session.cpp | 76 +---------------------- src/security/tls_session.h | 42 +------------ 6 files changed, 181 insertions(+), 116 deletions(-) create mode 100644 src/security/diffie-hellman.cpp create mode 100644 src/security/diffie-hellman.h diff --git a/src/ringdht/ringaccount.h b/src/ringdht/ringaccount.h index 5b36df9647..f850d978ba 100644 --- a/src/ringdht/ringaccount.h +++ b/src/ringdht/ringaccount.h @@ -26,6 +26,7 @@ #endif #include "security/tls_session.h" +#include "security/diffie-hellman.h" #include "sip/sipaccountbase.h" #include "noncopyable.h" diff --git a/src/security/Makefile.am b/src/security/Makefile.am index 382d357323..5ef080c08b 100644 --- a/src/security/Makefile.am +++ b/src/security/Makefile.am @@ -11,4 +11,6 @@ libsecurity_la_SOURCES = \ certstore.cpp \ certstore.h \ memory.cpp \ - memory.h + memory.h \ + diffie-hellman.cpp \ + diffie-hellman.h diff --git a/src/security/diffie-hellman.cpp b/src/security/diffie-hellman.cpp new file mode 100644 index 0000000000..aea39992f6 --- /dev/null +++ b/src/security/diffie-hellman.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2004-2017 Savoir-faire Linux Inc. + * + * Author: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com> + * + * 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 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 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. + */ + +#include "diffie-hellman.h" +#include "logger.h" + +#include <chrono> + +namespace ring { namespace tls { + +DhParams::DhParams(const std::vector<uint8_t>& data) +{ + gnutls_dh_params_t new_params_; + int ret = gnutls_dh_params_init(&new_params_); + if (ret) + throw std::runtime_error(std::string("Error initializing DH params: ") + gnutls_strerror(ret)); + params_.reset(new_params_); + const gnutls_datum_t dat {(uint8_t*)data.data(), (unsigned)data.size()}; + if (int ret_pem = gnutls_dh_params_import_pkcs3(params_.get(), &dat, GNUTLS_X509_FMT_PEM)) + if (int ret_der = gnutls_dh_params_import_pkcs3(params_.get(), &dat, GNUTLS_X509_FMT_DER)) + throw std::runtime_error(std::string("Error importing DH params: ") + gnutls_strerror(ret_pem) + " " + gnutls_strerror(ret_der)); +} + +DhParams& +DhParams::operator=(const DhParams& other) +{ + if (not params_) { + // We need a valid DH params pointer for the copy + gnutls_dh_params_t new_params_; + auto err = gnutls_dh_params_init(&new_params_); + if (err != GNUTLS_E_SUCCESS) + throw std::runtime_error(std::string("Error initializing DH params: ") + gnutls_strerror(err)); + params_.reset(new_params_); + } + + auto err = gnutls_dh_params_cpy(params_.get(), other.get()); + if (err != GNUTLS_E_SUCCESS) + throw std::runtime_error(std::string("Error copying DH params: ") + gnutls_strerror(err)); + + return *this; +} + +std::vector<uint8_t> +DhParams::serialize() const +{ + if (!params_) { + RING_WARN("serialize() called on an empty DhParams"); + return {}; + } + gnutls_datum_t out; + if (gnutls_dh_params_export2_pkcs3(params_.get(), GNUTLS_X509_FMT_PEM, &out)) + return {}; + std::vector<uint8_t> ret {out.data, out.data+out.size}; + gnutls_free(out.data); + return ret; +} + +DhParams +DhParams::generate() +{ + using clock = std::chrono::high_resolution_clock; + + auto bits = gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, /* GNUTLS_SEC_PARAM_HIGH */ GNUTLS_SEC_PARAM_HIGH); + RING_DBG("Generating DH params with %u bits", bits); + auto start = clock::now(); + + gnutls_dh_params_t new_params_; + int ret = gnutls_dh_params_init(&new_params_); + if (ret != GNUTLS_E_SUCCESS) { + RING_ERR("Error initializing DH params: %s", gnutls_strerror(ret)); + return {}; + } + DhParams params {new_params_}; + + ret = gnutls_dh_params_generate2(params.get(), bits); + if (ret != GNUTLS_E_SUCCESS) { + RING_ERR("Error generating DH params: %s", gnutls_strerror(ret)); + return {}; + } + + std::chrono::duration<double> time_span = clock::now() - start; + RING_DBG("Generated DH params with %u bits in %lfs", bits, time_span.count()); + return params; +} + +}} // namespace ring::tls diff --git a/src/security/diffie-hellman.h b/src/security/diffie-hellman.h new file mode 100644 index 0000000000..9bab03e6b1 --- /dev/null +++ b/src/security/diffie-hellman.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2004-2017 Savoir-faire Linux Inc. + * + * Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com> + * Author: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com> + * + * 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 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 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. + */ + +#pragma once + +#include <gnutls/gnutls.h> +#include <vector> +#include <memory> +#include <cstdint> + +namespace ring { namespace tls { + +class DhParams { +public: + DhParams() = default; + DhParams(DhParams&&) = default; + DhParams(const DhParams& other) { + *this = other; + } + + DhParams& operator=(DhParams&& other) = default; + DhParams& operator=(const DhParams& other); + + /// \brief Construct by taking ownership of given gnutls DH params + /// + /// User should not call gnutls_dh_params_deinit on given \a raw_params. + /// The object is stolen and its live is manager by our object. + explicit DhParams(gnutls_dh_params_t p) : params_ {p, gnutls_dh_params_deinit} {} + + /** Deserialize DER or PEM encoded DH-params */ + DhParams(const std::vector<uint8_t>& data); + + gnutls_dh_params_t get() { + return params_.get(); + } + gnutls_dh_params_t get() const { + return params_.get(); + } + + explicit inline operator bool() const { + return bool(params_); + } + + /** Serialize data in PEM format */ + std::vector<uint8_t> serialize() const; + + static DhParams generate(); + +private: + std::unique_ptr<gnutls_dh_params_int, decltype(gnutls_dh_params_deinit)*> params_ {nullptr, gnutls_dh_params_deinit}; +}; + +}} // namespace ring::tls diff --git a/src/security/tls_session.cpp b/src/security/tls_session.cpp index 3c220ae52c..566476728d 100644 --- a/src/security/tls_session.cpp +++ b/src/security/tls_session.cpp @@ -32,6 +32,7 @@ #include "manager.h" #include "certstore.h" #include "array_size.h" +#include "diffie-hellman.h" #include <gnutls/gnutls.h> #include <gnutls/dtls.h> @@ -83,53 +84,6 @@ array2uint(const std::array<uint8_t, 8>& a) return res; } -DhParams::DhParams(const std::vector<uint8_t>& data) -{ - gnutls_dh_params_t new_params_; - int ret = gnutls_dh_params_init(&new_params_); - if (ret) - throw std::runtime_error(std::string("Error initializing DH params: ") + gnutls_strerror(ret)); - params_.reset(new_params_); - const gnutls_datum_t dat {(uint8_t*)data.data(), (unsigned)data.size()}; - if (int ret_pem = gnutls_dh_params_import_pkcs3(params_.get(), &dat, GNUTLS_X509_FMT_PEM)) - if (int ret_der = gnutls_dh_params_import_pkcs3(params_.get(), &dat, GNUTLS_X509_FMT_DER)) - throw std::runtime_error(std::string("Error importing DH params: ") + gnutls_strerror(ret_pem) + " " + gnutls_strerror(ret_der)); -} - -DhParams& -DhParams::operator=(const DhParams& other) -{ - if (not params_) { - // We need a valid DH params pointer for the copy - gnutls_dh_params_t new_params_; - auto err = gnutls_dh_params_init(&new_params_); - if (err != GNUTLS_E_SUCCESS) - throw std::runtime_error(std::string("Error initializing DH params: ") + gnutls_strerror(err)); - params_.reset(new_params_); - } - - auto err = gnutls_dh_params_cpy(params_.get(), other.get()); - if (err != GNUTLS_E_SUCCESS) - throw std::runtime_error(std::string("Error copying DH params: ") + gnutls_strerror(err)); - - return *this; -} - -std::vector<uint8_t> -DhParams::serialize() const -{ - if (!params_) { - RING_WARN("serialize() called on an empty DhParams"); - return {}; - } - gnutls_datum_t out; - if (gnutls_dh_params_export2_pkcs3(params_.get(), GNUTLS_X509_FMT_PEM, &out)) - return {}; - std::vector<uint8_t> ret {out.data, out.data+out.size}; - gnutls_free(out.data); - return ret; -} - class TlsSession::TlsCertificateCredendials { using T = gnutls_certificate_credentials_t; @@ -1085,34 +1039,6 @@ TlsSession::process() callbacks_.onStateChange(new_state); } -DhParams -DhParams::generate() -{ - using clock = std::chrono::high_resolution_clock; - - auto bits = gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, /* GNUTLS_SEC_PARAM_HIGH */ GNUTLS_SEC_PARAM_HIGH); - RING_DBG("Generating DH params with %u bits", bits); - auto start = clock::now(); - - gnutls_dh_params_t new_params_; - int ret = gnutls_dh_params_init(&new_params_); - if (ret != GNUTLS_E_SUCCESS) { - RING_ERR("Error initializing DH params: %s", gnutls_strerror(ret)); - return {}; - } - DhParams params {new_params_}; - - ret = gnutls_dh_params_generate2(params.get(), bits); - if (ret != GNUTLS_E_SUCCESS) { - RING_ERR("Error generating DH params: %s", gnutls_strerror(ret)); - return {}; - } - - std::chrono::duration<double> time_span = clock::now() - start; - RING_DBG("Generated DH params with %u bits in %lfs", bits, time_span.count()); - return params; -} - uint16_t TlsSession::getMtu() { diff --git a/src/security/tls_session.h b/src/security/tls_session.h index 17fce2c9ce..71d3e9b095 100644 --- a/src/security/tls_session.h +++ b/src/security/tls_session.h @@ -57,6 +57,8 @@ struct PrivateKey; namespace ring { namespace tls { +class DhParams; + static constexpr uint8_t MTUS_TO_TEST = 3; //number of mtus to test in path mtu discovery. static constexpr int DTLS_MTU {1232}; // (1280 from IPv6 minimum MTU - 40 IPv6 header - 8 UDP header) static constexpr uint16_t MIN_MTU {512}; @@ -70,46 +72,6 @@ enum class TlsSessionState { SHUTDOWN }; -class DhParams { -public: - DhParams() = default; - DhParams(DhParams&&) = default; - DhParams(const DhParams& other) { - *this = other; - } - - DhParams& operator=(DhParams&& other) = default; - DhParams& operator=(const DhParams& other); - - /// \brief Construct by taking ownership of given gnutls DH params - /// - /// User should not call gnutls_dh_params_deinit on given \a raw_params. - /// The object is stolen and its live is manager by our object. - explicit DhParams(gnutls_dh_params_t p) : params_ {p, gnutls_dh_params_deinit} {} - - /** Deserialize DER or PEM encoded DH-params */ - DhParams(const std::vector<uint8_t>& data); - - gnutls_dh_params_t get() { - return params_.get(); - } - gnutls_dh_params_t get() const { - return params_.get(); - } - - explicit inline operator bool() const { - return bool(params_); - } - - /** Serialize data in PEM format */ - std::vector<uint8_t> serialize() const; - - static DhParams generate(); - -private: - std::unique_ptr<gnutls_dh_params_int, decltype(gnutls_dh_params_deinit)*> params_ {nullptr, gnutls_dh_params_deinit}; -}; - struct TlsParams { // User CA list for session credentials std::string ca_list; -- GitLab