1#include <vanetza/asn1/asn1c_wrapper.hpp>
2#include <vanetza/asn1/security/Certificate.h>
3#include <vanetza/asn1/security/EtsiTs103097Data.h>
4#include <vanetza/security/backend.hpp>
5#include <vanetza/security/v3/secured_message.hpp>
7#include <boost/optional/optional.hpp>
24 if (data && data->content && data->content->present == Ieee1609Dot2Content_PR_signedData) {
25 return data->content->choice.signedData;
35 return &signed_data->tbsData->headerInfo;
41HashedId8 make_hashed_id8(
const HashedId8_t& asn)
44 std::copy_n(asn.buf, std::min(asn.size, result.size()), result.data());
48ByteBuffer copy_octets(
const OCTET_STRING_t& octets)
50 ByteBuffer buffer(octets.size);
51 std::memcpy(buffer.data(), octets.buf, octets.size);
57 switch (point.present) {
58 case EccP256CurvePoint_PR_compressed_y_0:
59 return copy_octets(point.choice.compressed_y_0);
61 case EccP256CurvePoint_PR_compressed_y_1:
62 return copy_octets(point.choice.compressed_y_1);
64 case EccP256CurvePoint_PR_x_only:
65 return copy_octets(point.choice.x_only);
67 case EccP256CurvePoint_PR_uncompressedP256:
68 return copy_octets(point.choice.uncompressedP256.x);
78 switch (point.present) {
79 case EccP384CurvePoint_PR_compressed_y_0:
80 return copy_octets(point.choice.compressed_y_0);
82 case EccP384CurvePoint_PR_compressed_y_1:
83 return copy_octets(point.choice.compressed_y_1);
85 case EccP384CurvePoint_PR_x_only:
86 return copy_octets(point.choice.x_only);
88 case EccP384CurvePoint_PR_uncompressedP384:
89 return copy_octets(point.choice.uncompressedP384.x);
99SecuredMessage::SecuredMessage() :
104uint8_t SecuredMessage::protocol_version()
const
106 return m_struct->protocolVersion;
109ItsAid SecuredMessage::its_aid()
const
112 if (m_struct->content->present == Ieee1609Dot2Content_PR_signedData) {
113 const SignedData* signed_data = m_struct->content->choice.signedData;
114 if (signed_data && signed_data->tbsData) {
115 aid = signed_data->tbsData->headerInfo.psid;
121PacketVariant SecuredMessage::payload()
const
124 switch (m_struct->content->present) {
125 case Ieee1609Dot2Content_PR_unsecuredData:
126 buffer = get_payload(&m_struct->content->choice.unsecuredData);
128 case Ieee1609Dot2Content_PR_signedData:
129 buffer = get_payload(m_struct->content->choice.signedData);
133 return CohesivePacket { std::move(buffer), OsiLayer::Network };
136bool SecuredMessage::is_signed()
const
138 return m_struct->content->present == Ieee1609Dot2Content_PR_signedData;
141boost::optional<SecuredMessage::Time64> SecuredMessage::generation_time()
const
143 boost::optional<Time64> gen_time;
144 auto header_info = get_header_info(m_struct);
147 if (asn_INTEGER2umax(header_info->generationTime, &tmp) == 0) {
154boost::optional<Signature> SecuredMessage::signature()
const
156 const SignedData_t* signed_data = get_signed_data(m_struct);
162 case Signature_PR_ecdsaNistP256Signature:
163 sig.type = KeyType::NistP256;
164 sig.r = get_x_coordinate(asn.choice.ecdsaNistP256Signature.rSig);
165 sig.s = copy_octets(asn.choice.ecdsaNistP256Signature.sSig);
167 case Signature_PR_ecdsaBrainpoolP256r1Signature:
168 sig.type = KeyType::BrainpoolP256r1;
169 sig.r = get_x_coordinate(asn.choice.ecdsaBrainpoolP256r1Signature.rSig);
170 sig.s = copy_octets(asn.choice.ecdsaBrainpoolP256r1Signature.sSig);
172 case Signature_PR_ecdsaBrainpoolP384r1Signature:
173 sig.type = KeyType::BrainpoolP384r1;
174 sig.r = get_x_coordinate(asn.choice.ecdsaBrainpoolP384r1Signature.rSig);
175 sig.s = copy_octets(asn.choice.ecdsaBrainpoolP384r1Signature.sSig);
186SecuredMessage::SignerIdentifier SecuredMessage::signer_identifier()
const
188 const SignedData_t* signed_data = get_signed_data(m_struct);
190 if (signed_data->signer.present == SignerIdentifier_PR_digest) {
191 return &signed_data->signer.choice.digest;
192 }
else if (signed_data->signer.present == SignerIdentifier_PR_certificate) {
195 if (certificates.list.count == 1) {
202 return static_cast<HashedId8_t*
>(
nullptr);
205ByteBuffer SecuredMessage::signing_payload()
const
207 const SignedData_t* signed_data = get_signed_data(m_struct);
209 return asn1::encode_oer(asn_DEF_ToBeSignedData, signed_data->tbsData);
211 return ByteBuffer {};
215size_t get_size(
const SecuredMessage& message)
217 return message.size();
220void serialize(OutputArchive& ar,
const SecuredMessage& msg)
222 ByteBuffer buffer = msg.encode();
223 ar.save_binary(buffer.data(), buffer.size());
226size_t deserialize(InputArchive& ar, SecuredMessage& msg)
228 std::size_t len = ar.remaining_bytes();
232 ar.load_binary(buffer.data(), len);
233 return msg.decode(buffer) ? len : 0;
236ByteBuffer get_payload(
const Opaque_t* unsecured)
239 buffer.reserve(unsecured->size);
240 std::copy_n(unsecured->buf, unsecured->size, std::back_inserter(buffer));
244ByteBuffer get_payload(
const SignedData* signed_data)
247 if (signed_data->tbsData && signed_data->tbsData->payload) {
249 if (signed_payload->data && signed_payload->data->content) {
251 if (content->present == Ieee1609Dot2Content_PR_unsecuredData) {
252 buffer = get_payload(&content->choice.unsecuredData);
259boost::optional<HashedId8> get_certificate_id(
const SecuredMessage::SignerIdentifier& identifier)
261 using result_type = boost::optional<HashedId8>;
262 struct cert_id_visitor :
public boost::static_visitor<result_type> {
263 result_type operator()(
const HashedId8_t* digest)
const
265 return digest ? make_hashed_id8(*digest) : result_type { };
270 return cert ? calculate_hash(*cert) : result_type { };
273 return boost::apply_visitor(cert_id_visitor(), identifier);