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

95 lines
2.7 KiB
C++

#include <vanetza/security/v2/length_coding.hpp>
#include <cassert>
#include <cmath>
#include <iterator>
#include <list>
namespace vanetza
{
namespace security
{
namespace v2
{
std::size_t count_leading_ones(uint8_t v)
{
std::size_t count = 0;
while ((v & 0x80) != 0) {
v <<= 1;
++count;
}
return count;
}
std::size_t length_coding_size(std::uintmax_t length) {
std::size_t size = 1;
while ((length & ~0x7f) != 0) {
// prefix enlongates by one additional leading "1" per shift
length >>= 7; // shift by 7
++size;
}
return size;
}
ByteBuffer encode_length(std::uintmax_t length)
{
static_assert(sizeof(std::uintmax_t) <= 8, "size of length type exceeds implementation capabilities");
std::list<uint8_t> length_info;
while (length != 0) {
length_info.push_front(static_cast<uint8_t>(length));
length >>= 8;
}
unsigned prefix_length = length_info.size();
if (prefix_length == 0) {
// Zero-size encoding
length_info.push_back(0x00);
}
else {
assert(prefix_length <= 8);
uint8_t prefix_mask = ~((1 << (8 - prefix_length)) - 1);
if ((length_info.front() & ~prefix_mask) != length_info.front()) {
// additional byte needed for prefix
length_info.push_front(prefix_mask);
}
else {
// enough free bits available for prefix
length_info.front() |= (prefix_mask << 1);
}
// Huge lengths have all bits set in leading prefix bytes
length_info.insert(length_info.begin(), prefix_length / 8, 0xff);
}
return ByteBuffer(length_info.begin(), length_info.end());
}
std::tuple<ByteBuffer::const_iterator, std::uintmax_t> decode_length(const ByteBuffer& buffer)
{
if (!buffer.empty()) {
std::size_t additional_prefix = count_leading_ones(buffer.front());
if (additional_prefix >= sizeof(std::uintmax_t)) {
// encoded length is wider than uintmax_t, we cannot represent this number
return std::make_tuple(buffer.begin(), 0);
} else if (buffer.size() > additional_prefix) {
uint8_t prefix_mask = (1 << (8 - additional_prefix)) - 1;
std::uintmax_t length = buffer.front() & prefix_mask;
for (std::size_t i = 1; i <= additional_prefix; ++i) {
length <<= 8;
length |= buffer[i];
}
auto start = buffer.begin();
std::advance(start, additional_prefix + 1);
return std::make_tuple(start, length);
}
}
return std::make_tuple(buffer.end(), 0);
}
} // namespace v2
} // namespace security
} // namespace vanextza