Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add optional support for TLS trusted_ca_keys extension #778

Merged
merged 3 commits into from
Aug 23, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/staging/tls/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ find_package(OpenSSL 3)

target_sources(tls
PRIVATE
extensions/status_request.cpp
extensions/trusted_ca_keys.cpp
openssl_conv.cpp
openssl_util.cpp
tls.cpp
Expand Down
51 changes: 51 additions & 0 deletions lib/staging/tls/extensions/helpers.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright 2024 Pionix GmbH and Contributors to EVerest

#include "helpers.hpp"
#include "trusted_ca_keys.hpp"
#include <cstddef>

std::ostream& operator<<(std::ostream& out, const openssl::certificate_ptr& obj) {
const auto subject = openssl::certificate_subject(obj.get());
if (!subject.empty()) {
out << "subject:";
for (const auto& itt : subject) {
out << " " << itt.first << ":" << itt.second;
}
}
return out;
}

std::ostream& operator<<(std::ostream& out, const openssl::sha_1_digest_t& obj) {
const auto sav = out.flags();
for (const auto& c : obj) {
out << std::setw(2) << std::setfill('0') << std::hex << static_cast<std::uint32_t>(c);
}
out.flags(sav);
return out;
}

std::ostream& operator<<(std::ostream& out, const tls::trusted_ca_keys::trusted_ca_keys_t& obj) {
out << "trusted ca keys: pre-agreed: " << obj.pre_agreed << std::endl;
if (!obj.cert_sha1_hash.empty()) {
for (const auto& hash : obj.cert_sha1_hash) {
out << " certificate hash: " << hash << std::endl;
}
}
if (!obj.key_sha1_hash.empty()) {
for (const auto& hash : obj.key_sha1_hash) {
out << " subject key hash: " << hash << std::endl;
}
}
return out;
}

std::ostream& operator<<(std::ostream& out, const openssl::DER& obj) {
const auto sav = out.flags();
const auto* ptr = obj.get();
for (std::size_t i = 0; i < obj.size(); i++) {
out << std::setw(2) << std::setfill('0') << std::hex << static_cast<std::uint32_t>(*ptr++);
}
james-ctc marked this conversation as resolved.
Show resolved Hide resolved
out.flags(sav);
return out;
}
174 changes: 174 additions & 0 deletions lib/staging/tls/extensions/helpers.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright 2024 Pionix GmbH and Contributors to EVerest

#ifndef EXTENSIONS_HELPERS_
#define EXTENSIONS_HELPERS_

#include <cstdint>
#include <cstring>
#include <iomanip>
#include <sstream>
#include <string>

#ifdef UNIT_TEST
#include <iostream>
#endif

#include <openssl_util.hpp>

namespace tls {

using openssl::log_warning;

/**
* \brief update position and remaining by amount
* \param[inout] ptr the pointer to increment
* \param[inout] remaining the value to decrement
*/
constexpr void update_position(const std::uint8_t*& ptr, std::int32_t& remaining, std::size_t amount) {
ptr += amount;
remaining -= amount;
}

/**
* \brief update position and remaining by amount
* \param[inout] ptr the pointer to increment
* \param[inout] remaining the value to decrement
*/
constexpr void update_position(std::uint8_t*& ptr, std::int32_t& remaining, std::size_t amount) {
ptr += amount;
remaining -= amount;
}

/**
* \brief copy structure from data pointer
* \param[out] dest the destination structure
* \param[inout] ptr the pointer the start of the data, updated to point to the
* next byte (ptr += sizeof(dest))
* \param[inout] remaining updated with the remaining number of bytes
* (remaining -= sizeof(dest))
* \param[in] err_message to log on error
* \return true when structure populated from data
*/
template <typename T>
constexpr bool struct_copy(T& dest, const std::uint8_t*& ptr, std::int32_t& remaining, const std::string& err_message) {
bool bResult{false};
if (remaining < sizeof(T)) {
log_warning(err_message);
} else {
std::memcpy(&dest, ptr, sizeof(T));
update_position(ptr, remaining, sizeof(T));
bResult = true;
}
return bResult;
}

/**
* \brief copy structure to data pointer
* \param[out] ptr the destination pointer, updated to point to the
* next byte (ptr += sizeof(src))
* \param[inout] src the source structure
* \param[inout] remaining updated with the remaining number of bytes
* (remaining -= sizeof(src))
* \param[in] err_message to log on error
* \return true when ptr populated from structure
*/
template <typename T>
constexpr bool struct_copy(std::uint8_t*& ptr, const T& src, std::int32_t& remaining, const std::string& err_message) {
bool bResult{false};
if (remaining < sizeof(T)) {
log_warning(err_message);
} else {
std::memcpy(ptr, &src, sizeof(T));
update_position(ptr, remaining, sizeof(T));
bResult = true;
}
return bResult;
}

/**
* \brief copy DER to data pointer
* \param[out] ptr the destination pointer, updated to point to the
* next byte (ptr += src.size())
* \param[inout] src the DER source object
* \param[inout] remaining updated with the remaining number of bytes
* (remaining -= src.size())
* \param[in] err_message to log on error
* \return true when ptr populated from structure
*/
inline bool der_copy(std::uint8_t*& ptr, const openssl::DER& src, std::int32_t& remaining,
const std::string& err_message) {
bool bResult{false};
if (remaining < src.size()) {
log_warning(err_message + ' ' + std::to_string(remaining) + '/' + std::to_string(src.size()));
} else {
std::memcpy(ptr, src.get(), src.size());
update_position(ptr, remaining, src.size());
bResult = true;
}
return bResult;
}

/**
* \brief convert a big endian 3 byte (24 bit) unsigned value to uint32
* \param[in] ptr the pointer to the most significant byte
* \return the interpreted value
*/
constexpr std::uint32_t uint24(const std::uint8_t* ptr) {
return (static_cast<std::uint32_t>(ptr[0]) << 16U) | (static_cast<std::uint32_t>(ptr[1]) << 8U) |
static_cast<std::uint32_t>(ptr[2]);
}

/**
* \brief convert a uint32 to big endian 3 byte (24 bit) value
* \param[in] ptr the pointer to the most significant byte
* \param[in] value the 24 bit value
*/
constexpr void uint24(std::uint8_t* ptr, std::uint32_t value) {
ptr[0] = (value >> 16U) & 0xffU;
ptr[1] = (value >> 8U) & 0xffU;
ptr[2] = value & 0xffU;
}

/**
* \brief convert a big endian 2 byte (16 bit) unsigned value to uint16
* \param[in] ptr the pointer to the most significant byte
* \return the interpreted value
*/
constexpr std::uint16_t uint16(const std::uint8_t* ptr) {
return (static_cast<std::uint32_t>(ptr[0]) << 8U) | static_cast<std::uint32_t>(ptr[1]);
}

/**
* \brief convert a uint16 to big endian 2 byte (16 bit) value
* \param[in] ptr the pointer to the most significant byte
* \param[in] value the 16 bit value
*/
constexpr void uint16(std::uint8_t* ptr, std::uint32_t value) {
ptr[0] = (value >> 8U) & 0xffU;
ptr[1] = value & 0xffU;
}

template <typename T> std::string to_string(const T& digest) {
std::stringstream string_stream;
string_stream << std::hex;
for (const auto& c : digest) {
string_stream << std::setw(2) << std::setfill('0') << static_cast<int>(c);
}
return string_stream.str();
}

} // namespace tls

#ifdef UNIT_TEST
namespace tls::trusted_ca_keys {
struct trusted_ca_keys_t;
}

std::ostream& operator<<(std::ostream& out, const openssl::certificate_ptr& obj);
std::ostream& operator<<(std::ostream& out, const openssl::sha_1_digest_t& obj);
std::ostream& operator<<(std::ostream& out, const tls::trusted_ca_keys::trusted_ca_keys_t& obj);
std::ostream& operator<<(std::ostream& out, const openssl::DER& obj);
#endif

#endif // EXTENSIONS_HELPERS_
Loading
Loading