1#include <vanetza/asn1/asn1c_wrapper.hpp>
2#include <vanetza/asn1/security/Certificate.h>
3#include <vanetza/asn1/security/EtsiTs103097Data.h>
4#include <vanetza/common/byte_buffer.hpp>
5#include <vanetza/common/byte_buffer_sink.hpp>
6#include <vanetza/net/packet.hpp>
7#include <vanetza/security/backend.hpp>
8#include <vanetza/security/v3/asn1_conversions.hpp>
9#include <vanetza/security/v3/secured_message.hpp>
11#include <boost/iostreams/stream.hpp>
12#include <boost/optional/optional.hpp>
13#include <boost/variant/static_visitor.hpp>
16struct Vanetza_Security_Certificate :
public Vanetza_Security_CertificateBase {};
28const asn1::SignedData* get_signed_data(
const asn1::EtsiTs103097Data* data)
30 if (data && data->content && data->content->present == Vanetza_Security_Ieee1609Dot2Content_PR_signedData) {
31 return data->content->choice.signedData;
37const asn1::HeaderInfo* get_header_info(
const asn1::EtsiTs103097Data* data)
39 const asn1::SignedData* signed_data = get_signed_data(data);
41 return &signed_data->tbsData->headerInfo;
47HashedId8 make_hashed_id8(
const asn1::HashedId8& asn)
50 std::copy_n(asn.buf, std::min(asn.size, result.size()), result.data());
54ByteBuffer copy_octets(
const OCTET_STRING_t& octets)
56 ByteBuffer buffer(octets.size);
57 std::memcpy(buffer.data(), octets.buf, octets.size);
61ByteBuffer get_x_coordinate(
const asn1::EccP256CurvePoint& point)
63 switch (point.present) {
64 case Vanetza_Security_EccP256CurvePoint_PR_compressed_y_0:
65 return copy_octets(point.choice.compressed_y_0);
67 case Vanetza_Security_EccP256CurvePoint_PR_compressed_y_1:
68 return copy_octets(point.choice.compressed_y_1);
70 case Vanetza_Security_EccP256CurvePoint_PR_x_only:
71 return copy_octets(point.choice.x_only);
73 case Vanetza_Security_EccP256CurvePoint_PR_uncompressedP256:
74 return copy_octets(point.choice.uncompressedP256.x);
82ByteBuffer get_x_coordinate(
const asn1::EccP384CurvePoint& point)
84 switch (point.present) {
85 case Vanetza_Security_EccP384CurvePoint_PR_compressed_y_0:
86 return copy_octets(point.choice.compressed_y_0);
88 case Vanetza_Security_EccP384CurvePoint_PR_compressed_y_1:
89 return copy_octets(point.choice.compressed_y_1);
91 case Vanetza_Security_EccP384CurvePoint_PR_x_only:
92 return copy_octets(point.choice.x_only);
94 case Vanetza_Security_EccP384CurvePoint_PR_uncompressedP384:
95 return copy_octets(point.choice.uncompressedP384.x);
103void assign(OCTET_STRING_t* dst,
const ByteBuffer& src)
105 OCTET_STRING_fromBuf(dst,
reinterpret_cast<const char*
>(src.data()), src.size());
112 SecuredMessage secured_message;
113 secured_message->protocolVersion = 3;
114 secured_message->content = asn1::allocate<asn1::Ieee1609Dot2Content>();
115 secured_message->content->present = Vanetza_Security_Ieee1609Dot2Content_PR_signedData;
116 secured_message->content->choice.signedData = asn1::allocate<asn1::SignedData>();
117 secured_message->content->choice.signedData->tbsData = asn1::allocate<asn1::ToBeSignedData>();
118 secured_message->content->choice.signedData->tbsData->payload = asn1::allocate<asn1::SignedDataPayload>();
119 secured_message->content->choice.signedData->tbsData->payload->data = asn1::allocate<asn1::Ieee1609Dot2Data>();
120 secured_message->content->choice.signedData->tbsData->payload->data->protocolVersion = 3;
121 secured_message->content->choice.signedData->tbsData->payload->data->content = asn1::allocate<asn1::Ieee1609Dot2Content>();
122 secured_message->content->choice.signedData->tbsData->payload->data->content->present = Vanetza_Security_Ieee1609Dot2Content_PR_unsecuredData;
123 return secured_message;
128 SecuredMessage secured_message;
129 secured_message->protocolVersion = 3;
130 secured_message->content = asn1::allocate<asn1::Ieee1609Dot2Content>();
131 secured_message->content->present = Vanetza_Security_Ieee1609Dot2Content_PR_signedData;
132 secured_message->content->choice.signedData = asn1::allocate<asn1::SignedData>();
133 secured_message->content->choice.signedData->tbsData = asn1::allocate<asn1::ToBeSignedData>();
134 secured_message->content->choice.signedData->tbsData->payload = asn1::allocate<asn1::SignedDataPayload>();
135 secured_message->content->choice.signedData->tbsData->payload->extDataHash = asn1::allocate<asn1::HashedData>();
136 secured_message->content->choice.signedData->tbsData->payload->extDataHash->present = Vanetza_Security_HashedData_PR_sha256HashedData;
137 return secured_message;
142 SecuredMessage secured_message;
143 secured_message->protocolVersion = 3;
144 secured_message->content = asn1::allocate<asn1::Ieee1609Dot2Content>();
145 secured_message->content->present = Vanetza_Security_Ieee1609Dot2Content_PR_encryptedData;
146 return secured_message;
149SecuredMessage::SecuredMessage() :
150 asn1::asn1c_oer_wrapper<asn1::EtsiTs103097Data>(asn_DEF_Vanetza_Security_EtsiTs103097Data)
154uint8_t SecuredMessage::protocol_version()
const
156 return m_struct->protocolVersion;
159ItsAid SecuredMessage::its_aid()
const
162 if (m_struct->content->present == Vanetza_Security_Ieee1609Dot2Content_PR_signedData) {
163 const asn1::SignedData* signed_data = m_struct->content->choice.signedData;
164 if (signed_data && signed_data->tbsData) {
165 aid = signed_data->tbsData->headerInfo.psid;
171void SecuredMessage::set_its_aid(ItsAid its_aid)
173 if (m_struct->content->present == Vanetza_Security_Ieee1609Dot2Content_PR_signedData) {
174 asn1::SignedData* signed_data = m_struct->content->choice.signedData;
175 if (signed_data && signed_data->tbsData) {
176 signed_data->tbsData->headerInfo.psid = its_aid;
181void SecuredMessage::set_generation_time(Time64 time)
183 if (m_struct->content->present == Vanetza_Security_Ieee1609Dot2Content_PR_signedData) {
184 if (m_struct->content->choice.signedData->tbsData->headerInfo.generationTime ==
nullptr) {
185 m_struct->content->choice.signedData->tbsData->headerInfo.generationTime = asn1::allocate<asn1::Time64>();
187 asn_uint642INTEGER(m_struct->content->choice.signedData->tbsData->headerInfo.generationTime, time);
191void SecuredMessage::set_generation_location(
const asn1::ThreeDLocation& location)
193 if (m_struct->content->present == Vanetza_Security_Ieee1609Dot2Content_PR_signedData) {
194 if (m_struct->content->choice.signedData->tbsData->headerInfo.generationLocation ==
nullptr) {
195 m_struct->content->choice.signedData->tbsData->headerInfo.generationLocation = asn1::allocate<asn1::ThreeDLocation>();
197 m_struct->content->choice.signedData->tbsData->headerInfo.generationLocation->latitude = location.latitude;
198 m_struct->content->choice.signedData->tbsData->headerInfo.generationLocation->longitude = location.longitude;
199 m_struct->content->choice.signedData->tbsData->headerInfo.generationLocation->elevation = location.elevation;
203std::list<HashedId3> SecuredMessage::get_inline_p2pcd_request()
const
205 std::list<HashedId3> requests;
206 if (m_struct->content->present == Vanetza_Security_Ieee1609Dot2Content_PR_signedData) {
207 const asn1::SequenceOfHashedId3* inline_p2pcd_request = m_struct->content->choice.signedData->tbsData->headerInfo.inlineP2pcdRequest;
208 if (inline_p2pcd_request) {
209 for (
int i = 0; i < inline_p2pcd_request->list.count; i++) {
210 HashedId3 new_elem = truncate(convert(*inline_p2pcd_request->list.array[i]));
211 requests.push_back(new_elem);
218void SecuredMessage::set_inline_p2pcd_request(std::list<HashedId3> requests)
220 if (m_struct->content->present == Vanetza_Security_Ieee1609Dot2Content_PR_signedData) {
221 assert(m_struct->content->choice.signedData);
222 assert(m_struct->content->choice.signedData->tbsData);
224 if (m_struct->content->choice.signedData->tbsData->headerInfo.inlineP2pcdRequest) {
225 ASN_STRUCT_RESET(asn_DEF_Vanetza_Security_SequenceOfHashedId3,
226 &m_struct->content->choice.signedData->tbsData->headerInfo.inlineP2pcdRequest);
229 for (HashedId3 request : requests) {
230 this->add_inline_p2pcd_request(request);
235void SecuredMessage::add_inline_p2pcd_request(HashedId3 unknown_certificate_digest)
237 if (m_struct->content->present == Vanetza_Security_Ieee1609Dot2Content_PR_signedData) {
238 if (m_struct->content->choice.signedData->tbsData->headerInfo.inlineP2pcdRequest ==
nullptr) {
239 m_struct->content->choice.signedData->tbsData->headerInfo.inlineP2pcdRequest = asn1::allocate<asn1::SequenceOfHashedId3>();
241 Vanetza_Security_HashedId3_t* asn_digest = OCTET_STRING_new_fromBuf(&asn_DEF_Vanetza_Security_HashedId3,
242 reinterpret_cast<char*
>(unknown_certificate_digest.data()), unknown_certificate_digest.size());
243 ASN_SEQUENCE_ADD(m_struct->content->choice.signedData->tbsData->headerInfo.inlineP2pcdRequest, asn_digest);
247void SecuredMessage::set_dummy_signature()
249 if (m_struct->content->present == Vanetza_Security_Ieee1609Dot2Content_PR_signedData) {
250 asn1::SignedData* signed_data = m_struct->content->choice.signedData;
253 ASN_STRUCT_RESET(asn_DEF_Vanetza_Security_Signature, &(signed_data->signature));
256 signed_data->signature.present = Vanetza_Security_Signature_PR_ecdsaNistP256Signature;
259 signed_data->signature.choice.ecdsaNistP256Signature.rSig.present = Vanetza_Security_EccP256CurvePoint_PR_x_only;
260 std::vector<uint8_t> dummy_r(32, 0);
262 assign(&signed_data->signature.choice.ecdsaNistP256Signature.rSig.choice.x_only, dummy_r);
265 std::vector<uint8_t> dummy_s(32, 0);
266 assign(&signed_data->signature.choice.ecdsaNistP256Signature.sSig, dummy_s);
271void SecuredMessage::set_signature(
const Signature& signature)
273 if (m_struct->content->present == Vanetza_Security_Ieee1609Dot2Content_PR_signedData) {
274 asn1::SignedData* signed_data = m_struct->content->choice.signedData;
277 ASN_STRUCT_RESET(asn_DEF_Vanetza_Security_Signature, &(signed_data->signature));
280 switch (signature.type)
282 case vanetza::security::KeyType::NistP256:
283 signed_data->signature.present = Vanetza_Security_Signature_PR_ecdsaNistP256Signature;
287 signed_data->signature.choice.ecdsaNistP256Signature.rSig.present = Vanetza_Security_EccP256CurvePoint_PR_x_only;
288 assign(&signed_data->signature.choice.ecdsaNistP256Signature.rSig.choice.x_only, signature.r);
289 assign(&signed_data->signature.choice.ecdsaNistP256Signature.sSig, signature.s);
291 case vanetza::security::KeyType::BrainpoolP256r1 :
292 signed_data->signature.present = Vanetza_Security_Signature_PR_ecdsaBrainpoolP256r1Signature;
294 signed_data->signature.choice.ecdsaBrainpoolP256r1Signature.rSig.present = Vanetza_Security_EccP256CurvePoint_PR_x_only;
295 assign(&signed_data->signature.choice.ecdsaBrainpoolP256r1Signature.rSig.choice.x_only, signature.r);
296 assign(&signed_data->signature.choice.ecdsaBrainpoolP256r1Signature.sSig, signature.s);
298 case vanetza::security::KeyType::BrainpoolP384r1 :
299 signed_data->signature.present = Vanetza_Security_Signature_PR_ecdsaBrainpoolP384r1Signature;
301 signed_data->signature.choice.ecdsaBrainpoolP384r1Signature.rSig.present = Vanetza_Security_EccP384CurvePoint_PR_x_only;
302 assign(&signed_data->signature.choice.ecdsaBrainpoolP384r1Signature.rSig.choice.x_only, signature.r);
303 assign(&signed_data->signature.choice.ecdsaBrainpoolP384r1Signature.sSig, signature.s);
306 this->set_dummy_signature();
313void SecuredMessage::set_signature(
const SomeEcdsaSignature& signature)
315 struct ecc_point_visitor :
public boost::static_visitor<asn1::EccP256CurvePoint> {
316 asn1::EccP256CurvePoint operator()(
const X_Coordinate_Only& x_only)
const
318 asn1::EccP256CurvePoint* to_return = asn1::allocate<asn1::EccP256CurvePoint>();
319 to_return->present = Vanetza_Security_EccP256CurvePoint_PR_x_only;
320 assign(&to_return->choice.x_only, x_only.x);
323 asn1::EccP256CurvePoint operator()(
const Compressed_Lsb_Y_0& y0)
const
325 asn1::EccP256CurvePoint* to_return = asn1::allocate<asn1::EccP256CurvePoint>();
326 to_return->present = Vanetza_Security_EccP256CurvePoint_PR_compressed_y_0;
327 assign(&to_return->choice.compressed_y_0, y0.x);
330 asn1::EccP256CurvePoint operator()(
const Compressed_Lsb_Y_1& y1)
const
332 asn1::EccP256CurvePoint* to_return = asn1::allocate<asn1::EccP256CurvePoint>();
333 to_return->present = Vanetza_Security_EccP256CurvePoint_PR_compressed_y_1;
334 assign(&to_return->choice.compressed_y_1, y1.x);
337 asn1::EccP256CurvePoint operator()(
const Uncompressed& unc)
const
339 asn1::EccP256CurvePoint* to_return = asn1::allocate<asn1::EccP256CurvePoint>();
340 to_return->present = Vanetza_Security_EccP256CurvePoint_PR_uncompressedP256;
341 assign(&to_return->choice.uncompressedP256.x, unc.x);
342 assign(&to_return->choice.uncompressedP256.y, unc.y);
347 struct signature_visitor :
public boost::static_visitor<asn1::Signature>
349 asn1::Signature operator()(
const EcdsaSignature& signature)
const
351 asn1::Signature* final_signature = asn1::allocate<asn1::Signature>();
352 final_signature->present = Vanetza_Security_Signature_PR_ecdsaNistP256Signature;
353 assign(&final_signature->choice.ecdsaNistP256Signature.sSig, signature.s);
354 final_signature->choice.ecdsaNistP256Signature.rSig = boost::apply_visitor(
358 return *final_signature;
361 asn1::Signature operator()(
const EcdsaSignatureFuture& signature)
const
363 return this->operator()(signature.get());
367 m_struct->content->choice.signedData->signature = boost::apply_visitor(signature_visitor(), signature);
370PacketVariant SecuredMessage::payload()
const
373 switch (m_struct->content->present) {
374 case Vanetza_Security_Ieee1609Dot2Content_PR_unsecuredData:
375 buffer = get_payload(&m_struct->content->choice.unsecuredData);
377 case Vanetza_Security_Ieee1609Dot2Content_PR_signedData:
378 buffer = get_payload(m_struct->content->choice.signedData);
385 return CohesivePacket { std::move(buffer), OsiLayer::Network };
388void SecuredMessage::set_payload(
const ByteBuffer& payload)
390 switch (m_struct->content->present) {
391 case Vanetza_Security_Ieee1609Dot2Content_PR_unsecuredData:
392 vanetza::security::v3::set_payload(&m_struct->content->choice.unsecuredData, payload);
394 case Vanetza_Security_Ieee1609Dot2Content_PR_signedData:
395 vanetza::security::v3::set_payload(&m_struct->content->choice.signedData->tbsData->payload->data->content->choice.unsecuredData, payload);
403void SecuredMessage::set_external_payload_hash(
const Sha256Digest& hash)
405 assert(m_struct->content->present == Vanetza_Security_Ieee1609Dot2Content_PR_signedData);
406 asn1::HashedData* hashed_data = m_struct->content->choice.signedData->tbsData->payload->extDataHash;
407 ASN_STRUCT_RESET(asn_DEF_Vanetza_Security_HashedData, hashed_data);
408 hashed_data->present = Vanetza_Security_HashedData_PR_sha256HashedData;
409 OCTET_STRING_fromBuf(&hashed_data->choice.sha256HashedData,
reinterpret_cast<const char*
>(hash.data()), hash.size());
412HashAlgorithm SecuredMessage::hash_id()
const
414 HashAlgorithm algo = HashAlgorithm::Unspecified;
416 const asn1::SignedData* signed_data = get_signed_data(m_struct);
418 switch (signed_data->hashId) {
419 case Vanetza_Security_HashAlgorithm_sha256:
420 algo = HashAlgorithm::SHA256;
422 case Vanetza_Security_HashAlgorithm_sha384:
423 algo = HashAlgorithm::SHA384;
433void SecuredMessage::set_hash_id(HashAlgorithm hash)
435 assert(m_struct->content->present == Vanetza_Security_Ieee1609Dot2Content_PR_signedData);
437 case HashAlgorithm::SHA256:
438 m_struct->content->choice.signedData->hashId = Vanetza_Security_HashAlgorithm_sha256;
440 case HashAlgorithm::SHA384:
441 m_struct->content->choice.signedData->hashId = Vanetza_Security_HashAlgorithm_sha384;
444 m_struct->content->choice.signedData->hashId = -1;
448void SecuredMessage::set_signer_identifier_self()
450 assert(m_struct->content->present == Vanetza_Security_Ieee1609Dot2Content_PR_signedData);
451 asn1::SignerIdentifier* signer = &m_struct->content->choice.signedData->signer;
452 ASN_STRUCT_RESET(asn_DEF_Vanetza_Security_SignerIdentifier, signer);
453 signer->present = Vanetza_Security_SignerIdentifier_PR_self;
456void SecuredMessage::set_signer_identifier(
const HashedId8& digest)
458 assert(m_struct->content->present == Vanetza_Security_Ieee1609Dot2Content_PR_signedData);
459 asn1::SignerIdentifier* signer = &m_struct->content->choice.signedData->signer;
460 ASN_STRUCT_RESET(asn_DEF_Vanetza_Security_SignerIdentifier, signer);
461 signer->present = Vanetza_Security_SignerIdentifier_PR_digest;
462 OCTET_STRING_fromBuf(&signer->choice.digest,
reinterpret_cast<const char*
>(digest.data()), digest.size());
465void SecuredMessage::set_signer_identifier(
const Certificate& cert)
467 assert(m_struct->content->present == Vanetza_Security_Ieee1609Dot2Content_PR_signedData);
468 asn1::SignerIdentifier* signer = &m_struct->content->choice.signedData->signer;
469 ASN_STRUCT_RESET(asn_DEF_Vanetza_Security_SignerIdentifier, signer);
470 signer->present = Vanetza_Security_SignerIdentifier_PR_certificate;
471 ASN_SEQUENCE_ADD(&signer->choice.certificate, asn1::copy(asn_DEF_Vanetza_Security_EtsiTs103097Certificate, cert.content()));
474void SecuredMessage::get_aes_ccm_ciphertext(ByteBuffer &ccm_ciphertext, std::array<uint8_t, 12> &nonce)
const
476 assert(m_struct->content->present == Vanetza_Security_Ieee1609Dot2Content_PR_encryptedData);
478 const asn1::SymmetricCiphertext &symmetric_ciphertext = m_struct->content->choice.encryptedData.ciphertext;
479 assert(symmetric_ciphertext.present == Vanetza_Security_SymmetricCiphertext_PR_aes128ccm);
481 const asn1::AesCcmCiphertext &aes_ccm_ciphertext = symmetric_ciphertext.choice.aes128ccm;
482 ccm_ciphertext = copy_octets(aes_ccm_ciphertext.ccmCiphertext);
483 std::memcpy(nonce.data(), aes_ccm_ciphertext.nonce.buf, nonce.size());
486void SecuredMessage::set_aes_ccm_ciphertext(
const ByteBuffer &ccm_ciphertext,
const std::array<uint8_t, 12> &nonce)
488 assert(m_struct->content->present == Vanetza_Security_Ieee1609Dot2Content_PR_encryptedData);
490 asn1::SymmetricCiphertext &symmetric_ciphertext = m_struct->content->choice.encryptedData.ciphertext;
491 CHOICE_variant_set_presence(&asn_DEF_Vanetza_Security_SymmetricCiphertext, &symmetric_ciphertext, Vanetza_Security_SymmetricCiphertext_PR_aes128ccm);
493 asn1::AesCcmCiphertext &aes_ccm_ciphertext = symmetric_ciphertext.choice.aes128ccm;
494 OCTET_STRING_fromBuf(&aes_ccm_ciphertext.ccmCiphertext,
reinterpret_cast<const char *
>(ccm_ciphertext.data()), ccm_ciphertext.size());
495 OCTET_STRING_fromBuf(&aes_ccm_ciphertext.nonce,
reinterpret_cast<const char *
>(nonce.data()), nonce.size());
498void SecuredMessage::set_cert_recip_info(
const HashedId8& recipient_id,
499 const KeyType curve_type,
500 const std::array<uint8_t, 16>& ecies_ciphertext,
501 const std::array<uint8_t, 16>& ecies_tag,
502 const ecdsa256::PublicKey& ecies_pub_key)
504 assert(m_struct->content->present == Vanetza_Security_Ieee1609Dot2Content_PR_encryptedData);
506 asn1::RecipientInfo *cert_recip_info = asn1::allocate<asn1::RecipientInfo>();
507 CHOICE_variant_set_presence(&asn_DEF_Vanetza_Security_RecipientInfo, cert_recip_info, Vanetza_Security_RecipientInfo_PR_certRecipInfo);
509 asn1::PKRecipientInfo &pk_recip_info = cert_recip_info->choice.certRecipInfo;
511 OCTET_STRING_fromBuf(&pk_recip_info.recipientId,
reinterpret_cast<const char *
>(recipient_id.data()), recipient_id.size());
513 asn1::EncryptedDataEncryptionKey &enc_data_enc_key = pk_recip_info.encKey;
514 asn1::EciesP256EncryptedKey *ecies_enc_key_ptr;
515 if (curve_type == KeyType::NistP256) {
516 enc_data_enc_key.present = Vanetza_Security_EncryptedDataEncryptionKey_PR_eciesNistP256;
517 ecies_enc_key_ptr = &enc_data_enc_key.choice.eciesNistP256;
518 }
else if (curve_type == KeyType::BrainpoolP256r1) {
519 enc_data_enc_key.present = Vanetza_Security_EncryptedDataEncryptionKey_PR_eciesBrainpoolP256r1;
520 ecies_enc_key_ptr = &enc_data_enc_key.choice.eciesBrainpoolP256r1;
522 throw std::invalid_argument(
"Unsupported EC curve");
525 asn1::EciesP256EncryptedKey &ecies_enc_key = *ecies_enc_key_ptr;
527 OCTET_STRING_fromBuf(&ecies_enc_key.c,
reinterpret_cast<const char *
>(ecies_ciphertext.data()), ecies_ciphertext.size());
528 OCTET_STRING_fromBuf(&ecies_enc_key.t,
reinterpret_cast<const char *
>(ecies_tag.data()), ecies_tag.size());
531 CHOICE_variant_set_presence(&asn_DEF_Vanetza_Security_EccP256CurvePoint, &ecies_enc_key.v, Vanetza_Security_EccP256CurvePoint_PR_uncompressedP256);
532 OCTET_STRING_fromBuf(&ecies_enc_key.v.choice.uncompressedP256.x,
reinterpret_cast<const char *
>(ecies_pub_key.x.data()), ecies_pub_key.x.size());
533 OCTET_STRING_fromBuf(&ecies_enc_key.v.choice.uncompressedP256.y,
reinterpret_cast<const char *
>(ecies_pub_key.y.data()), ecies_pub_key.y.size());
535 ASN_SEQUENCE_ADD(&m_struct->content->choice.encryptedData.recipients.list, cert_recip_info);
538bool SecuredMessage::check_psk_match(
const std::array<uint8_t, 16>& psk)
const
540 assert(m_struct->content->present == Vanetza_Security_Ieee1609Dot2Content_PR_encryptedData);
543 asn1::asn1c_oer_wrapper<asn1::SymmetricEncryptionKey> psk_key(asn_DEF_Vanetza_Security_SymmetricEncryptionKey);
544 asn1::SymmetricEncryptionKey *psk_key_ptr = &(*psk_key);
545 CHOICE_variant_set_presence(
546 &asn_DEF_Vanetza_Security_SymmetricEncryptionKey,
548 Vanetza_Security_SymmetricEncryptionKey_PR_aes128Ccm);
549 OCTET_STRING_fromBuf(&psk_key_ptr->choice.aes128Ccm,
reinterpret_cast<const char *
>(psk.data()), psk.size());
551 ByteBuffer bytes = psk_key.encode();
552 Sha256Digest psk_digest = calculate_sha256_digest(bytes.data(), bytes.size());
553 HashedId8 psk_id = create_hashed_id8(psk_digest);
556 const auto &recipient_list = m_struct->content->choice.encryptedData.recipients.list;
558 for (
int i = 0; i < recipient_list.count; i++) {
559 const asn1::RecipientInfo &recipient_info = *recipient_list.array[i];
560 if (recipient_info.present != Vanetza_Security_RecipientInfo_PR_pskRecipInfo) {
564 HashedId8 message_psk_id;
565 std::memcpy(message_psk_id.data(), recipient_info.choice.pskRecipInfo.buf, message_psk_id.size());
566 if (psk_id == message_psk_id) {
574bool SecuredMessage::is_signed()
const
576 return m_struct->content->present == Vanetza_Security_Ieee1609Dot2Content_PR_signedData;
579bool SecuredMessage::is_encrypted()
const
581 return m_struct->content->present == Vanetza_Security_Ieee1609Dot2Content_PR_encryptedData;
584boost::optional<SecuredMessage::Time64> SecuredMessage::generation_time()
const
586 boost::optional<Time64> gen_time;
587 auto header_info = get_header_info(m_struct);
590 if (asn_INTEGER2umax(header_info->generationTime, &tmp) == 0) {
597boost::optional<Signature> SecuredMessage::signature()
const
599 const asn1::SignedData* signed_data = get_signed_data(m_struct);
601 const asn1::Signature& asn = signed_data->signature;
605 case Vanetza_Security_Signature_PR_ecdsaNistP256Signature:
606 sig.type = KeyType::NistP256;
607 sig.r = get_x_coordinate(asn.choice.ecdsaNistP256Signature.rSig);
608 sig.s = copy_octets(asn.choice.ecdsaNistP256Signature.sSig);
610 case Vanetza_Security_Signature_PR_ecdsaBrainpoolP256r1Signature:
611 sig.type = KeyType::BrainpoolP256r1;
612 sig.r = get_x_coordinate(asn.choice.ecdsaBrainpoolP256r1Signature.rSig);
613 sig.s = copy_octets(asn.choice.ecdsaBrainpoolP256r1Signature.sSig);
615 case Vanetza_Security_Signature_PR_ecdsaBrainpoolP384r1Signature:
616 sig.type = KeyType::BrainpoolP384r1;
617 sig.r = get_x_coordinate(asn.choice.ecdsaBrainpoolP384r1Signature.rSig);
618 sig.s = copy_octets(asn.choice.ecdsaBrainpoolP384r1Signature.sSig);
629SecuredMessage::SignerIdentifier SecuredMessage::signer_identifier()
const
631 const asn1::SignedData* signed_data = get_signed_data(m_struct);
633 if (signed_data->signer.present == Vanetza_Security_SignerIdentifier_PR_digest) {
634 const asn1::HashedId8* digest = &signed_data->signer.choice.digest;
636 }
else if (signed_data->signer.present == Vanetza_Security_SignerIdentifier_PR_certificate) {
637 const asn1::SequenceOfCertificate& certificates = signed_data->signer.choice.certificate;
639 if (certificates.list.count == 1) {
640 const asn1::Certificate* cert = certificates.list.array[0];
646 return static_cast<asn1::HashedId8*
>(
nullptr);
649ByteBuffer SecuredMessage::signing_payload()
const
651 const asn1::SignedData* signed_data = get_signed_data(m_struct);
653 return asn1::encode_oer(asn_DEF_Vanetza_Security_ToBeSignedData, signed_data->tbsData);
655 return ByteBuffer {};
659void SecuredMessage::set_requested_certificate(
const Certificate& cert)
661 const asn1::SignedData* signed_data = get_signed_data(m_struct);
662 if (signed_data && signed_data->tbsData) {
663 if (signed_data->tbsData->headerInfo.requestedCertificate) {
664 ASN_STRUCT_FREE(asn_DEF_Vanetza_Security_Certificate, signed_data->tbsData->headerInfo.requestedCertificate);
666 signed_data->tbsData->headerInfo.requestedCertificate =
667 static_cast<Vanetza_Security_Certificate*
>(asn1::copy(asn_DEF_Vanetza_Security_Certificate, cert.content()));
671size_t get_size(
const SecuredMessage& message)
673 return message.size();
676void serialize(OutputArchive& ar,
const SecuredMessage& msg)
678 ByteBuffer buffer = msg.encode();
679 ar.save_binary(buffer.data(), buffer.size());
682size_t deserialize(InputArchive& ar, SecuredMessage& msg)
684 std::size_t len = ar.remaining_bytes();
688 ar.load_binary(buffer.data(), len);
689 return msg.decode(buffer) ? len : 0;
692ByteBuffer get_payload(
const asn1::Opaque* unsecured)
695 buffer.reserve(unsecured->size);
696 std::copy_n(unsecured->buf, unsecured->size, std::back_inserter(buffer));
700ByteBuffer convert_to_payload(vanetza::DownPacket packet)
703 byte_buffer_sink sink(buf);
705 boost::iostreams::stream_buffer<byte_buffer_sink> stream(sink);
706 OutputArchive ar(stream);
708 serialize(ar, packet);
714void set_payload(asn1::Opaque* unsecured,
const ByteBuffer& buffer)
716 unsecured->size = buffer.size();
717 unsecured->buf =
new uint8_t[unsecured->size];
718 std::copy(buffer.begin(), buffer.end(), unsecured->buf);
721ByteBuffer get_payload(
const asn1::SignedData* signed_data)
724 if (signed_data->tbsData && signed_data->tbsData->payload) {
725 const asn1::SignedDataPayload* signed_payload = signed_data->tbsData->payload;
726 if (signed_payload->data && signed_payload->data->content) {
727 const asn1::Ieee1609Dot2Content* content = signed_payload->data->content;
728 if (content->present == Vanetza_Security_Ieee1609Dot2Content_PR_unsecuredData) {
729 buffer = get_payload(&content->choice.unsecuredData);
736boost::optional<HashedId8> get_certificate_id(
const SecuredMessage::SignerIdentifier& identifier)
738 using result_type = boost::optional<HashedId8>;
739 struct cert_id_visitor :
public boost::static_visitor<result_type> {
740 result_type operator()(
const asn1::HashedId8* digest)
const
742 return digest ? make_hashed_id8(*digest) : result_type { };
745 result_type operator()(
const asn1::Certificate* cert)
const
747 return cert ? calculate_digest(*cert) : result_type { };
750 return boost::apply_visitor(cert_id_visitor(), identifier);
753bool contains_certificate(
const SecuredMessage::SignerIdentifier& identifier)
755 struct visitor :
public boost::static_visitor<bool> {
756 bool operator()(
const asn1::HashedId8* digest)
const
761 bool operator()(
const asn1::Certificate* cert)
const
766 return boost::apply_visitor(visitor(), identifier);