Files
MicrOBU/obu-firmware/external/vanetza-idf/tools/pki/pem.cpp
T
Ashin Walpola d107534eb2 Keep vanetza-idf in obu-firmware, so a plain clone builds the firmware
obu-firmware builds against the vanetza-idf C-ITS library, which until now
came from the colleague's microbu-esp32c5 tree beside the repository and was
not tracked here, so a clone of this repository could not build the firmware
it ships. The library alone is now part of obu-firmware, as
obu-firmware/external/vanetza-idf: their external/vanetza-idf at commit
cf4b99f, unchanged (9775 files; see its PROVENANCE.md). CMake takes it from
there by default; -DVANETZA_IDF_DIR still points the build elsewhere.

The rest of the colleague's tree (their own VAM firmware, PKI tooling,
station-link Python tools, the V2X2MAP bridge) stays out of this repository
and gitignored; nothing is pushed to their repository. NOTES.md, docs/06,
TODO.md and the pcap verifier's usage line point at the new location.
2026-09-24 10:56:05 +02:00

86 lines
2.6 KiB
C++

#include "pem.hpp"
#include "openssl.hpp"
#include <openssl/core_names.h>
#include <openssl/pem.h>
namespace vanetza
{
namespace pki
{
namespace
{
boost::optional<PrivateKey> parse_pem_private_key(const void* data, std::size_t size)
{
OpenSslPointer<BIO> bio { BIO_new(BIO_s_mem()) };
int rc = BIO_write(bio.raw(), data, size);
if (rc < 0) {
throw security::openssl::Exception();
}
EVP_PKEY* evp_key_raw = PEM_read_bio_PrivateKey(bio.raw(), nullptr, nullptr, nullptr);
if (evp_key_raw == nullptr) {
return boost::none;
} else if (EVP_PKEY_get_base_id(evp_key_raw) != EVP_PKEY_EC) {
return boost::none;
}
OpenSslPointer<EVP_PKEY> evp_key { evp_key_raw }; /*< safe deallocation*/
BIGNUM* bn_priv_raw = nullptr;
EVP_PKEY_get_bn_param(evp_key.raw(), OSSL_PKEY_PARAM_PRIV_KEY, &bn_priv_raw);
OpenSslPointer<BIGNUM> bn_priv { bn_priv_raw }; /*< safe deallocation */
char group[80];
if (!EVP_PKEY_get_group_name(evp_key.raw(), group, sizeof(group), nullptr)) {
return boost::none;
}
PrivateKey priv_key;
priv_key.type = openssl_key_type_from_group_name(group);
priv_key.key.resize(BN_num_bytes(bn_priv_raw));
BN_bn2bin(bn_priv_raw, priv_key.key.data());
return priv_key;
}
} // namespace
boost::optional<PrivateKey> parse_pem_private_key(const std::string& pem)
{
return parse_pem_private_key(pem.data(), pem.size());
}
boost::optional<PrivateKey> parse_pem_private_key(const ByteBuffer& pem)
{
return parse_pem_private_key(pem.data(), pem.size());
}
std::string make_pem(const PrivateKey& priv)
{
OpenSslPointer<EC_KEY> ec_key = make_ec_key(priv);
OpenSslPointer<EVP_PKEY> evp_key { EVP_PKEY_new() };
openssl_result(EVP_PKEY_set1_EC_KEY(evp_key.raw(), ec_key.raw()), "EVP_PKEY_set1_EC_KEY");
// unencrypted PKCS#8 PrivateKeyInfo, read back by parse_pem_private_key
OpenSslPointer<BIO> bio { BIO_new(BIO_s_mem()) };
openssl_result(PEM_write_bio_PrivateKey(bio.raw(), evp_key.raw(), nullptr, nullptr, 0, nullptr, nullptr),
"PEM_write_bio_PrivateKey");
char* data = nullptr;
long len = BIO_get_mem_data(bio.raw(), &data);
return std::string(data, len);
}
void write_pem_private_key(const PrivateKey& priv, const std::filesystem::path& path)
{
std::string pem = make_pem(priv);
auto bio = make_owner_only_bio(path);
if (BIO_write(bio.raw(), pem.data(), pem.size()) != static_cast<int>(pem.size())) {
throw OpenSslException(ERR_get_error(), "writing PEM to key file failed");
}
}
} // namespace pki
} // namespace vanetza