Keep the colleague's microbu-esp32c5 tree in this repository
obu-firmware builds against vanetza-idf from microbu-esp32c5/external, but that tree was gitignored, so a clone of this repository could not build the firmware it ships. It is now committed here as ordinary files in its own folder, microbu-esp32c5/: the colleague's commit cf4b99f plus the V2X2MAP bridge's signature verification (--trust) used on the bench. Nothing is fetched from or pushed to the colleague's repository; this repository and its remotes carry everything. The folder's own .gitignore keeps build output, downloaded components and private key material out, as it did there; the committed file set is identical to that repository's tracked files. The ESP32-C5 is still flashed from obu-firmware/, which only takes vanetza-idf from microbu-esp32c5/, so the two stay separate folders. FLASHING.md says how to take a newer version of the colleague's tree (copy it over the folder, rebuild, test, commit).
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
#include <vanetza/security/public_key.hpp>
|
||||
#include <boost/algorithm/hex.hpp>
|
||||
#include <cstdint>
|
||||
#include <iterator>
|
||||
|
||||
namespace vanetza
|
||||
{
|
||||
namespace security
|
||||
{
|
||||
|
||||
std::string canonical_hexstring(const PublicKey& key)
|
||||
{
|
||||
const std::size_t expected_length = key_length(key.type);
|
||||
if (expected_length == 0 || key.x.size() != expected_length) {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string input;
|
||||
switch (key.compression) {
|
||||
case KeyCompression::NoCompression:
|
||||
if (key.y.size() != expected_length) {
|
||||
return {};
|
||||
}
|
||||
input.push_back(*key.y.rbegin() % 2 == 0 ? 0x02 : 0x03);
|
||||
break;
|
||||
case KeyCompression::Y0:
|
||||
input.push_back(0x02);
|
||||
break;
|
||||
case KeyCompression::Y1:
|
||||
input.push_back(0x03);
|
||||
break;
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
std::copy(key.x.begin(), key.x.end(), std::back_inserter(input));
|
||||
return boost::algorithm::hex(input);
|
||||
}
|
||||
|
||||
ByteBuffer encode_subject_public_key_info(const PublicKey& key)
|
||||
{
|
||||
const std::size_t expected_length = key_length(key.type);
|
||||
if (expected_length == 0 || key.x.size() != expected_length) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// RFC 5480: id-ecPublicKey OBJECT IDENTIFIER ::= { 1.2.840.10045.2.1 }
|
||||
static const uint8_t oid_ec_public_key[] = {
|
||||
0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01
|
||||
};
|
||||
// RFC 5480: secp256r1 (NIST P-256) OID 1.2.840.10045.3.1.7
|
||||
static const uint8_t oid_secp256r1[] = {
|
||||
0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07
|
||||
};
|
||||
// RFC 5639: brainpoolP256r1 OID 1.3.36.3.3.2.8.1.1.7
|
||||
static const uint8_t oid_brainpoolP256r1[] = {
|
||||
0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07
|
||||
};
|
||||
// RFC 5639: brainpoolP384r1 OID 1.3.36.3.3.2.8.1.1.11
|
||||
static const uint8_t oid_brainpoolP384r1[] = {
|
||||
0x06, 0x09, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B
|
||||
};
|
||||
|
||||
const uint8_t* named_curve_oid = nullptr;
|
||||
std::size_t named_curve_oid_size = 0;
|
||||
switch (key.type) {
|
||||
case KeyType::NistP256:
|
||||
named_curve_oid = oid_secp256r1;
|
||||
named_curve_oid_size = sizeof(oid_secp256r1);
|
||||
break;
|
||||
case KeyType::BrainpoolP256r1:
|
||||
named_curve_oid = oid_brainpoolP256r1;
|
||||
named_curve_oid_size = sizeof(oid_brainpoolP256r1);
|
||||
break;
|
||||
case KeyType::BrainpoolP384r1:
|
||||
named_curve_oid = oid_brainpoolP384r1;
|
||||
named_curve_oid_size = sizeof(oid_brainpoolP384r1);
|
||||
break;
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
|
||||
uint8_t ec_point_prefix = 0;
|
||||
std::size_t ec_point_size = 0;
|
||||
switch (key.compression) {
|
||||
case KeyCompression::NoCompression:
|
||||
if (key.y.size() != expected_length) {
|
||||
return {};
|
||||
}
|
||||
ec_point_prefix = 0x04;
|
||||
ec_point_size = 1 + 2 * expected_length;
|
||||
break;
|
||||
case KeyCompression::Y0:
|
||||
ec_point_prefix = 0x02;
|
||||
ec_point_size = 1 + expected_length;
|
||||
break;
|
||||
case KeyCompression::Y1:
|
||||
ec_point_prefix = 0x03;
|
||||
ec_point_size = 1 + expected_length;
|
||||
break;
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
|
||||
const std::size_t algo_content_size = sizeof(oid_ec_public_key) + named_curve_oid_size;
|
||||
const std::size_t bit_string_content_size = 1 + ec_point_size; // leading "unused bits" byte
|
||||
const std::size_t spki_content_size = 2 + algo_content_size + 2 + bit_string_content_size;
|
||||
|
||||
ByteBuffer result;
|
||||
result.reserve(2 + spki_content_size);
|
||||
|
||||
result.push_back(0x30); // SEQUENCE (SubjectPublicKeyInfo)
|
||||
result.push_back(static_cast<uint8_t>(spki_content_size));
|
||||
|
||||
result.push_back(0x30); // SEQUENCE (AlgorithmIdentifier)
|
||||
result.push_back(static_cast<uint8_t>(algo_content_size));
|
||||
result.insert(result.end(), oid_ec_public_key, oid_ec_public_key + sizeof(oid_ec_public_key));
|
||||
result.insert(result.end(), named_curve_oid, named_curve_oid + named_curve_oid_size);
|
||||
|
||||
result.push_back(0x03); // BIT STRING (subjectPublicKey)
|
||||
result.push_back(static_cast<uint8_t>(bit_string_content_size));
|
||||
result.push_back(0x00); // unused bits
|
||||
result.push_back(ec_point_prefix);
|
||||
result.insert(result.end(), key.x.begin(), key.x.end());
|
||||
if (key.compression == KeyCompression::NoCompression) {
|
||||
result.insert(result.end(), key.y.begin(), key.y.end());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace security
|
||||
} // namespace vanetza
|
||||
Reference in New Issue
Block a user