Files
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

83 lines
2.8 KiB
C++

#include "ecies.hpp"
#include <algorithm>
#include <cassert>
namespace vanetza
{
namespace pki
{
ByteBuffer calculate_kdf2(SecurityModule& security, const ByteBuffer& shared_secret, const ByteBuffer& kdp,
std::size_t dl)
{
Sha256Function fn = [&security](const ByteBuffer& buffer) {
return security.calculate_sha256_hash(buffer.data(), buffer.size());
};
return calculate_kdf2(fn, shared_secret, kdp, dl);
}
ByteBuffer calculate_kdf2(Sha256Function hash_fn, const ByteBuffer& shared_secret, const ByteBuffer& kdp,
std::size_t dl)
{
ByteBuffer derived;
ByteBuffer concat;
// each iteration adds 32 bytes (SHA-256 hash)
const std::uint32_t iterations = dl / Sha256Hash::length + (dl % Sha256Hash::length ? 1 : 0);
// initialize counter with 1: see IEEE 1363.2a-2004 KDF2
for (std::uint32_t counter = 1; counter <= iterations; ++counter) {
// start concatenation with shared secret
concat = shared_secret;
// append 4-byte counter in big-endian order
concat.insert(concat.end(), {
static_cast<std::uint8_t>(counter >> 24),
static_cast<std::uint8_t>(counter >> 16),
static_cast<std::uint8_t>(counter >> 8),
static_cast<std::uint8_t>(counter)
});
// finalize with key derivation parameter (P1)
concat.insert(concat.end(), kdp.begin(), kdp.end());
Sha256Hash hash = hash_fn(concat);
std::copy(hash.octets.begin(), hash.octets.end(), std::back_inserter(derived));
}
// left most bytes are the derived key
assert(derived.size() >= dl);
derived.resize(dl);
return derived;
}
EncryptedSymmetricKey encrypt_key(SecurityModule& security, const SecurityModule::EciesContext& ecies,
const ByteBuffer& key, const Sha256Hash& info)
{
const std::size_t ke_length = key.size();
static constexpr std::size_t km_length = 32;
// derive ke and km from shared secret
ByteBuffer kdp { info.octets.begin(), info.octets.end() };
auto hashed_shared_secret = calculate_kdf2(security, ecies.shared_secret(), kdp, ke_length + km_length);
assert(hashed_shared_secret.size() == ke_length + km_length);
EncryptedSymmetricKey result;
result.public_key = ecies.ephemeral_public_key();
// encrypt symmetric key
result.wrapped_key.resize(ke_length);
std::uint8_t* ke = hashed_shared_secret.data();
for (std::size_t i = 0; i < ke_length; ++i) {
result.wrapped_key[i] = ke[i] ^ key[i];
}
// generate authentication tag
ByteBuffer km { std::next(hashed_shared_secret.begin(), ke_length), hashed_shared_secret.end() };
assert(km.size() == km_length);
result.authentication_tag = security.calculate_hmac_sha256(km, result.wrapped_key);
return result;
}
} // namespace pki
} // namespace vanetza