Skip to content

Commit

Permalink
Added utilities for encoding/decoding base64
Browse files Browse the repository at this point in the history
Signed-off-by: AssemblyJohn <[email protected]>
  • Loading branch information
AssemblyJohn committed Apr 8, 2024
1 parent a415211 commit 0d3d2b8
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 23 deletions.
4 changes: 3 additions & 1 deletion include/evse_security/crypto/interface/crypto_supplier.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,9 @@ class AbstractCryptoSupplier {

public: // Digesting/decoding utils
static bool digest_file_sha256(const fs::path& path, std::vector<std::byte>& out_digest);
static bool decode_base64_signature(const std::string& signature, std::vector<std::byte>& out_decoded);

static bool encode_base64_bytes(const std::vector<std::byte>& bytes, std::string& out_encoded);
static bool decode_base64_string(const std::string& string, std::vector<std::byte>& out_decoded);
};

} // namespace evse_security
4 changes: 3 additions & 1 deletion include/evse_security/crypto/openssl/openssl_supplier.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ class OpenSSLSupplier : public AbstractCryptoSupplier {

public:
static bool digest_file_sha256(const fs::path& path, std::vector<std::byte>& out_digest);
static bool decode_base64_signature(const std::string& signature, std::vector<std::byte>& out_decoded);

static bool encode_base64_bytes(const std::vector<std::byte>& bytes, std::string& out_encoded);
static bool decode_base64_string(const std::string& string, std::vector<std::byte>& out_decoded);
};

} // namespace evse_security
10 changes: 10 additions & 0 deletions include/evse_security/evse_security.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,16 @@ class EvseSecurity {
static bool verify_file_signature(const fs::path& path, const std::string& signing_certificate,
const std::string signature);

/// @brief Decodes the base64 encoded string to the raw byte representation
/// @param encoded_string
/// @return
static std::vector<std::byte> base64_decode(const std::string& encoded_string);

/// @brief Encodes the raw bytes to a base64 string
/// @param decoded_bytes
/// @return
static std::string base64_encode(const std::vector<std::byte>& decoded_bytes);

private:
// Internal versions of the functions do not lock the mutex
CertificateValidationResult verify_certificate_internal(const std::string& certificate_chain,
Expand Down
7 changes: 5 additions & 2 deletions lib/evse_security/crypto/interface/crypto_supplier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,11 @@ bool AbstractCryptoSupplier::digest_file_sha256(const fs::path& path, std::vecto
default_crypto_supplier_usage_error() return false;
}

bool AbstractCryptoSupplier::decode_base64_signature(const std::string& signature,
std::vector<std::byte>& out_decoded) {
static bool encode_base64_bytes(const std::vector<std::byte>& bytes, std::string& out_encoded) {
default_crypto_supplier_usage_error() return false;
}

static bool decode_base64_string(const std::string& string, std::vector<std::byte>& out_decoded) {
default_crypto_supplier_usage_error() return false;
}

Expand Down
53 changes: 43 additions & 10 deletions lib/evse_security/crypto/openssl/openssl_supplier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -850,8 +850,41 @@ bool OpenSSLSupplier::digest_file_sha256(const fs::path& path, std::vector<std::
return true;
}

bool OpenSSLSupplier::decode_base64_signature(const std::string& signature, std::vector<std::byte>& out_decoded) {
// decode base64 encoded signature
bool OpenSSLSupplier::encode_base64_bytes(const std::vector<std::byte>& bytes, std::string& out_encoded) {
EVP_ENCODE_CTX_ptr base64_encode_context_ptr(EVP_ENCODE_CTX_new());
if (!base64_encode_context_ptr.get()) {
EVLOG_error << "Error during EVP_ENCODE_CTX_new";
return false;
}

EVP_EncodeInit(base64_encode_context_ptr.get());
if (!base64_encode_context_ptr.get()) {
EVLOG_error << "Error during EVP_EncodeInit";
return false;
}

const unsigned char* bytes_str = reinterpret_cast<const unsigned char*>(bytes.data());

int base64_length = ((bytes.size() * 4) / 3) + 1;
char base64_out[base64_length]; // If it causes issues, replace with 'alloca' on diff platform

int base64_out_length;
if (EVP_EncodeUpdate(base64_encode_context_ptr.get(), reinterpret_cast<unsigned char*>(base64_out),
&base64_out_length, bytes_str, base64_length) < 0) {
EVLOG_error << "Error during EVP_EncodeUpdate";
return false;
}

int encode_final_out;
EVP_EncodeFinal(base64_encode_context_ptr.get(), reinterpret_cast<unsigned char*>(base64_out), &encode_final_out);

out_encoded.clear();
out_encoded.insert(std::end(out_encoded), base64_out, base64_out + base64_out_length);

return true;
}

bool OpenSSLSupplier::decode_base64_string(const std::string& string, std::vector<std::byte>& out_decoded) {
EVP_ENCODE_CTX_ptr base64_decode_context_ptr(EVP_ENCODE_CTX_new());
if (!base64_decode_context_ptr.get()) {
EVLOG_error << "Error during EVP_ENCODE_CTX_new";
Expand All @@ -864,26 +897,26 @@ bool OpenSSLSupplier::decode_base64_signature(const std::string& signature, std:
return false;
}

const unsigned char* signature_str = reinterpret_cast<const unsigned char*>(signature.data());
int base64_length = signature.size();
std::byte signature_out[base64_length];
const unsigned char* encoded_str = reinterpret_cast<const unsigned char*>(string.data());
int base64_length = string.size();
std::byte decoded_out[base64_length];

int signature_out_length;
if (EVP_DecodeUpdate(base64_decode_context_ptr.get(), reinterpret_cast<unsigned char*>(signature_out),
&signature_out_length, signature_str, base64_length) < 0) {
int decoded_out_length;
if (EVP_DecodeUpdate(base64_decode_context_ptr.get(), reinterpret_cast<unsigned char*>(decoded_out),
&decoded_out_length, encoded_str, base64_length) < 0) {
EVLOG_error << "Error during DecodeUpdate";
return false;
}

int decode_final_out;
if (EVP_DecodeFinal(base64_decode_context_ptr.get(), reinterpret_cast<unsigned char*>(signature_out),
if (EVP_DecodeFinal(base64_decode_context_ptr.get(), reinterpret_cast<unsigned char*>(decoded_out),
&decode_final_out) < 0) {
EVLOG_error << "Error during EVP_DecodeFinal";
return false;
}

out_decoded.clear();
out_decoded.insert(std::end(out_decoded), signature_out, signature_out + signature_out_length);
out_decoded.insert(std::end(out_decoded), decoded_out, decoded_out + decoded_out_length);

return true;
}
Expand Down
38 changes: 29 additions & 9 deletions lib/evse_security/evse_security.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -719,14 +719,14 @@ void EvseSecurity::update_ocsp_cache(const CertificateHashData& certificate_hash

try {
X509CertificateBundle ca_bundle(ca_bundle_path, EncodingFormat::PEM);
auto &certificate_hierarchy = ca_bundle.get_certficate_hierarchy();
auto& certificate_hierarchy = ca_bundle.get_certficate_hierarchy();

try {
// Find the certificate
X509Wrapper cert = certificate_hierarchy.find_certificate(certificate_hash_data);

EVLOG_debug << "Writing OCSP Response to filesystem";
if (cert.get_file().has_value()) {
if (cert.get_file().has_value()) {
const auto ocsp_path = cert.get_file().value().parent_path() / "ocsp";
if (!fs::exists(ocsp_path)) {
fs::create_directories(ocsp_path);
Expand All @@ -739,7 +739,7 @@ void EvseSecurity::update_ocsp_cache(const CertificateHashData& certificate_hash
fs << ocsp_response;
fs.close();
}
} catch(const NoCertificateFound& e) {
} catch (const NoCertificateFound& e) {
EVLOG_error << "Could not find any certificate for ocsp cache update: " << e.what();
}
} catch (const CertificateLoadException& e) {
Expand All @@ -755,19 +755,19 @@ std::optional<std::string> EvseSecurity::retrieve_ocsp_cache(const CertificateHa

try {
X509CertificateBundle ca_bundle(ca_bundle_path, EncodingFormat::PEM);
auto &certificate_hierarchy = ca_bundle.get_certficate_hierarchy();
auto& certificate_hierarchy = ca_bundle.get_certficate_hierarchy();

try {
// Find the certificate
X509Wrapper cert = certificate_hierarchy.find_certificate(certificate_hash_data);

EVLOG_debug << "Reading OCSP Response from filesystem";
if (cert.get_file().has_value()) {
if (cert.get_file().has_value()) {
const auto ocsp_path = cert.get_file().value().parent_path() / "ocsp";
const auto ocsp_file_path =
ocsp_path / cert.get_file().value().filename().replace_extension(".ocsp.der");
if(fs::exists(ocsp_file_path)) {

if (fs::exists(ocsp_file_path)) {
std::ifstream in_fs(ocsp_file_path.c_str());
std::string ocsp_response;

Expand All @@ -777,7 +777,7 @@ std::optional<std::string> EvseSecurity::retrieve_ocsp_cache(const CertificateHa
return std::make_optional<std::string>(std::move(ocsp_response));
}
}
} catch(const NoCertificateFound& e) {
} catch (const NoCertificateFound& e) {
EVLOG_error << "Could not find any certificate for ocsp cache retrieve: " << e.what();
}
} catch (const CertificateLoadException& e) {
Expand Down Expand Up @@ -1153,7 +1153,7 @@ bool EvseSecurity::verify_file_signature(const fs::path& path, const std::string

std::vector<std::byte> signature_decoded;

if (false == CryptoSupplier::decode_base64_signature(signature, signature_decoded)) {
if (false == CryptoSupplier::decode_base64_string(signature, signature_decoded)) {
EVLOG_error << "Error during decoding signature: " << signature;
return false;
}
Expand All @@ -1176,6 +1176,26 @@ bool EvseSecurity::verify_file_signature(const fs::path& path, const std::string
return false;
}

std::vector<std::byte> EvseSecurity::base64_decode(const std::string& encoded_string) {
std::vector<std::byte> decoded_bytes;

if (false == CryptoSupplier::decode_base64_string(encoded_string, decoded_bytes)) {
return {};
}

return decoded_bytes;
}

std::string EvseSecurity::base64_encode(const std::vector<std::byte>& bytes) {
std::string encoded_string;

if (false == CryptoSupplier::encode_base64_bytes(bytes, encoded_string)) {
return {};
}

return encoded_string;
}

CertificateValidationResult EvseSecurity::verify_certificate(const std::string& certificate_chain,
LeafCertificateType certificate_type) {
std::lock_guard<std::mutex> guard(EvseSecurity::security_mutex);
Expand Down

0 comments on commit 0d3d2b8

Please sign in to comment.