1#include <vanetza/asn1/security_profile.hpp>
2#include VANETZA_ASN1_SECURITY_HEADER(Certificate.h)
3#include <vanetza/security/hash_algorithm.hpp>
4#include <vanetza/security/sha.hpp>
5#include <vanetza/security/v3/asn1_conversions.hpp>
6#include <vanetza/security/v3/certificate.hpp>
7#include <vanetza/security/v3/distance.hpp>
8#include <vanetza/security/v3/geometry.hpp>
9#include <boost/optional/optional.hpp>
23HashAlgorithm digest_hash_algorithm(
const asn1::EtsiTs103097Certificate& cert);
24bool copy_curve_point(
PublicKey& to,
const asn1::EccP256CurvePoint& from);
25bool copy_curve_point(
PublicKey& to,
const asn1::EccP384CurvePoint& from);
26ByteBuffer fetch_octets(
const OCTET_STRING_t& octets);
27ByteBuffer get_x_coordinate(
const asn1::EccP256CurvePoint& point);
28ByteBuffer get_x_coordinate(
const asn1::EccP384CurvePoint& point);
32bool is_signature_x_only(
const Vanetza_Security_Signature_t& sig);
35bool contains_permission(
const Vanetza_Security_SequenceOfPsidSspRange_t& permissions, ItsAid aid);
36bool equal(
const asn1::TwoDLocation& lhs,
const asn1::TwoDLocation& rhs);
37bool equal(
const asn1::RectangularRegion& lhs,
const asn1::RectangularRegion& rhs);
38bool equal(
const asn1::SequenceOfRectangularRegion& lhs,
const asn1::SequenceOfRectangularRegion& rhs);
39bool is_within(
const asn1::GeographicRegion& inner,
const asn1::CircularRegion& outer);
40bool is_within(
const asn1::GeographicRegion& inner,
const asn1::SequenceOfRectangularRegion& outer);
41bool is_within(
const asn1::GeographicRegion& inner,
const asn1::PolygonalRegion& outer);
42bool is_within(
const asn1::GeographicRegion& inner,
const asn1::GeographicRegion& outer);
45bool make_signature_x_only(Vanetza_Security_Signature_t& sig);
49CertificateView::CertificateView(
const asn1::EtsiTs103097Certificate* cert) :
55 Wrapper(asn_DEF_Vanetza_Security_EtsiTs103097Certificate),
58 assert(CertificateView::m_cert == Wrapper::m_struct);
61Certificate::Certificate(
const asn1::EtsiTs103097Certificate& cert) :
62 Wrapper(asn_DEF_Vanetza_Security_EtsiTs103097Certificate, &cert),
65 assert(CertificateView::m_cert == Wrapper::m_struct);
71 assert(CertificateView::m_cert == Wrapper::m_struct);
76 Wrapper::operator=(other);
77 CertificateView::m_cert = content();
78 assert(CertificateView::m_cert == Wrapper::m_struct);
85 assert(CertificateView::m_cert == Wrapper::m_struct);
90 Wrapper::operator=(std::move(other));
91 CertificateView::m_cert = content();
92 assert(CertificateView::m_cert == Wrapper::m_struct);
98 return m_cert ? v3::calculate_digest(*m_cert) : boost::none;
103 return m_cert ? v3::get_verification_key_type(*m_cert) : KeyType::Unspecified;
108 return m_cert ? lc ? lc->valid_at_location(*m_cert, location) :
false :
false;
113 return m_cert ? v3::valid_at_timepoint(*m_cert, timepoint) :
false;
116bool valid_at_timepoint(
const asn1::EtsiTs103097Certificate& cert,
const Clock::time_point& timepoint)
118 const asn1::ValidityPeriod& validity = cert.toBeSigned.validityPeriod;
119 Clock::time_point start { std::chrono::seconds(validity.start) };
120 Clock::time_point end = start;
122 switch (validity.duration.present)
124 case Vanetza_Security_Duration_PR_microseconds:
125 end += std::chrono::microseconds(validity.duration.choice.microseconds);
127 case Vanetza_Security_Duration_PR_milliseconds:
128 end += std::chrono::milliseconds(validity.duration.choice.milliseconds);
130 case Vanetza_Security_Duration_PR_seconds:
131 end += std::chrono::seconds(validity.duration.choice.seconds);
133 case Vanetza_Security_Duration_PR_minutes:
134 end += std::chrono::minutes(validity.duration.choice.minutes);
136 case Vanetza_Security_Duration_PR_hours:
137 end += std::chrono::hours(validity.duration.choice.hours);
139 case Vanetza_Security_Duration_PR_sixtyHours:
140 end += std::chrono::hours(60) * validity.duration.choice.sixtyHours;
142 case Vanetza_Security_Duration_PR_years:
144 end += std::chrono::seconds(31556952) * validity.duration.choice.years;
151 return timepoint >= start && timepoint < end;
156 return m_cert ? v3::valid_for_application(*m_cert, aid) :
false;
165 if (
const auto* seq = m_cert->toBeSigned.certIssuePermissions) {
166 for (
int i = 0; i < seq->list.count; ++i) {
167 const auto* group = seq->list.array[i];
172 const auto& subject_permissions = group->subjectPermissions;
173 if (subject_permissions.present == Vanetza_Security_SubjectPermissions_PR_all) {
176 subject_permissions.present == Vanetza_Security_SubjectPermissions_PR_explicit &&
177 contains_permission(subject_permissions.choice.Explicit, aid)) {
188 if (!m_cert || !m_cert->toBeSigned.assuranceLevel || m_cert->toBeSigned.assuranceLevel->size < 1) {
192 return m_cert->toBeSigned.assuranceLevel->buf[0];
197 if (!m_cert || !issuer.m_cert) {
201 const auto* issuer_region = issuer.m_cert->toBeSigned.region;
202 const auto* subject_region = m_cert->toBeSigned.region;
203 if (!issuer_region) {
205 }
else if (!subject_region) {
208 return is_within(*subject_region, *issuer_region);
212bool valid_for_application(
const asn1::EtsiTs103097Certificate& cert, ItsAid aid)
214 const asn1::SequenceOfPsidSsp* permissions = cert.toBeSigned.appPermissions;
216 for (
int i = 0; i < permissions->list.count; ++i) {
217 if (permissions->list.array[i]->psid == aid) {
229 boost::optional<HashedId8> digest;
230 if (m_cert !=
nullptr) {
231 switch (m_cert->issuer.present)
233 case Vanetza_Security_IssuerIdentifier_PR_sha256AndDigest:
234 digest = create_hashed_id8(m_cert->issuer.choice.sha256AndDigest);
236 case Vanetza_Security_IssuerIdentifier_PR_sha384AndDigest:
237 digest = create_hashed_id8(m_cert->issuer.choice.sha384AndDigest);
248 return m_cert->issuer.present == Vanetza_Security_IssuerIdentifier_PR_self;
253 return m_cert ? m_cert->toBeSigned.region !=
nullptr :
false;
258 return m_cert && m_cert->toBeSigned.certIssuePermissions !=
nullptr;
263 return m_cert && m_cert->toBeSigned.certIssuePermissions ==
nullptr && m_cert->toBeSigned.appPermissions !=
nullptr;
268 return m_cert ? v3::is_canonical(*m_cert) :
false;
274 start_and_end.start_validity = Time32(m_cert->toBeSigned.validityPeriod.start);
276 switch (m_cert->toBeSigned.validityPeriod.duration.present)
278 case Vanetza_Security_Duration_PR_NOTHING:
280 case Vanetza_Security_Duration_PR_microseconds:
281 duration += (
int)m_cert->toBeSigned.validityPeriod.duration.choice.microseconds/1000000;
283 case Vanetza_Security_Duration_PR_milliseconds:
284 duration += (
int)m_cert->toBeSigned.validityPeriod.duration.choice.milliseconds/1000;
286 case Vanetza_Security_Duration_PR_seconds:
287 duration += (
int)m_cert->toBeSigned.validityPeriod.duration.choice.seconds;
289 case Vanetza_Security_Duration_PR_minutes:
290 duration += (
int)m_cert->toBeSigned.validityPeriod.duration.choice.minutes*60;
292 case Vanetza_Security_Duration_PR_hours:
293 duration += (
int)m_cert->toBeSigned.validityPeriod.duration.choice.hours*60*60;
295 case Vanetza_Security_Duration_PR_sixtyHours:
296 duration += (
int)m_cert->toBeSigned.validityPeriod.duration.choice.sixtyHours*60*60*60;
298 case Vanetza_Security_Duration_PR_years:
299 duration += (
int)m_cert->toBeSigned.validityPeriod.duration.choice.years*60*60*24*365;
304 start_and_end.end_validity = start_and_end.start_validity + duration;
305 return start_and_end;
308bool is_canonical(
const asn1::EtsiTs103097Certificate& cert)
310 bool compressed_point =
true;
312 if (indicator.present == Vanetza_Security_VerificationKeyIndicator_PR_verificationKey) {
314 switch (pubkey.present) {
315 case Vanetza_Security_PublicVerificationKey_PR_ecdsaNistP256:
316 compressed_point = is_compressed(pubkey.choice.ecdsaNistP256);
318 case Vanetza_Security_PublicVerificationKey_PR_ecdsaBrainpoolP256r1:
319 compressed_point = is_compressed(pubkey.choice.ecdsaBrainpoolP256r1);
321 case Vanetza_Security_PublicVerificationKey_PR_ecdsaBrainpoolP384r1:
322 compressed_point = is_compressed(pubkey.choice.ecdsaBrainpoolP384r1);
327 }
else if (indicator.present == Vanetza_Security_VerificationKeyIndicator_PR_reconstructionValue) {
328 compressed_point = is_compressed(indicator.choice.reconstructionValue);
331 if (!compressed_point) {
333 }
else if (cert.signature && !is_signature_x_only(*cert.signature)) {
342 return m_cert ? asn1::encode_oer(asn_DEF_Vanetza_Security_EtsiTs103097Certificate, m_cert) : ByteBuffer {};
347 return Wrapper::encode();
352 return m_cert ? v3::canonicalize(*m_cert) : boost::none;
359 if (canonical->toBeSigned.verifyKeyIndicator.present == Vanetza_Security_VerificationKeyIndicator_PR_verificationKey) {
361 switch (pubkey.present) {
362 case Vanetza_Security_PublicVerificationKey_PR_ecdsaNistP256:
363 success &= compress(pubkey.choice.ecdsaNistP256);
365 case Vanetza_Security_PublicVerificationKey_PR_ecdsaBrainpoolP256r1:
366 success &= compress(pubkey.choice.ecdsaBrainpoolP256r1);
368 case Vanetza_Security_PublicVerificationKey_PR_ecdsaBrainpoolP384r1:
369 success &= compress(pubkey.choice.ecdsaBrainpoolP384r1);
374 }
else if (canonical->toBeSigned.verifyKeyIndicator.present == Vanetza_Security_VerificationKeyIndicator_PR_reconstructionValue) {
375 success &= compress(canonical->toBeSigned.verifyKeyIndicator.choice.reconstructionValue);
378 if (canonical->toBeSigned.encryptionKey) {
380 switch (pubkey.present) {
381 case Vanetza_Security_BasePublicEncryptionKey_PR_eciesNistP256:
382 success &= compress(pubkey.choice.eciesNistP256);
384 case Vanetza_Security_BasePublicEncryptionKey_PR_eciesBrainpoolP256r1:
385 success &= compress(pubkey.choice.eciesBrainpoolP256r1);
392 if (canonical->signature) {
393 success &= make_signature_x_only(*canonical->signature);
397 assert(is_canonical(*canonical));
404boost::optional<
Certificate> canonicalize(
const asn1::EtsiTs103097Certificate& cert)
408 return canonicalize(std::move(copy));
409 }
catch (
const std::exception&) {
414boost::optional<HashedId8> calculate_digest_internal(
const asn1::EtsiTs103097Certificate& cert, HashAlgorithm hash_algo)
416 boost::optional<HashedId8> digest;
419 ByteBuffer buffer = asn1::encode_oer(asn_DEF_Vanetza_Security_EtsiTs103097Certificate, &cert);
423 case HashAlgorithm::SHA256:
424 digest = create_hashed_id8(calculate_sha256_digest(buffer.data(), buffer.size()));
426 case HashAlgorithm::SHA384:
427 digest = create_hashed_id8(calculate_sha384_digest(buffer.data(), buffer.size()));
432 }
catch (
const std::exception&) {
439boost::optional<HashedId8> calculate_digest(
const asn1::EtsiTs103097Certificate& cert)
441 boost::optional<HashedId8> digest;
442 const HashAlgorithm hash_algo = digest_hash_algorithm(cert);
443 if (hash_algo != HashAlgorithm::Unspecified) {
444 if (is_canonical(cert)) {
445 digest = calculate_digest_internal(cert, hash_algo);
447 auto maybe_canonical_cert = canonicalize(cert);
448 if (maybe_canonical_cert) {
449 digest = calculate_digest_internal(*maybe_canonical_cert.value(), hash_algo);
456KeyType get_verification_key_type(
const asn1::EtsiTs103097Certificate& cert)
458 KeyType key_type = KeyType::Unspecified;
460 if (cert.toBeSigned.verifyKeyIndicator.present == Vanetza_Security_VerificationKeyIndicator_PR_verificationKey)
462 switch (cert.toBeSigned.verifyKeyIndicator.choice.verificationKey.present)
464 case Vanetza_Security_PublicVerificationKey_PR_ecdsaNistP256:
465 key_type = KeyType::NistP256;
467 case Vanetza_Security_PublicVerificationKey_PR_ecdsaBrainpoolP256r1:
468 key_type = KeyType::BrainpoolP256r1;
470 case Vanetza_Security_PublicVerificationKey_PR_ecdsaBrainpoolP384r1:
471 key_type = KeyType::BrainpoolP384r1;
481boost::optional<
PublicKey> get_public_key(
const asn1::EtsiTs103097Certificate& cert)
483 asn1::VerificationKeyIndicator indicator = cert.toBeSigned.verifyKeyIndicator;
484 if (indicator.present != Vanetza_Security_VerificationKeyIndicator_PR_verificationKey) {
488 const asn1::PublicVerificationKey& input = cert.toBeSigned.verifyKeyIndicator.choice.verificationKey;
490 switch (input.present) {
491 case Vanetza_Security_PublicVerificationKey_PR_ecdsaNistP256:
492 output.type = KeyType::NistP256;
493 if (copy_curve_point(output, input.choice.ecdsaNistP256)) {
499 case Vanetza_Security_PublicVerificationKey_PR_ecdsaBrainpoolP256r1:
500 output.type = KeyType::BrainpoolP256r1;
501 if (copy_curve_point(output, input.choice.ecdsaBrainpoolP256r1)) {
507 case Vanetza_Security_PublicVerificationKey_PR_ecdsaBrainpoolP384r1:
508 output.type = KeyType::BrainpoolP384r1;
509 if (copy_curve_point(output, input.choice.ecdsaBrainpoolP384r1)) {
521boost::optional<
PublicKey> get_public_encryption_key(
const asn1::EtsiTs103097Certificate& cert)
523 const asn1::PublicEncryptionKey* enc_key = cert.toBeSigned.encryptionKey;
524 if (!enc_key || enc_key->supportedSymmAlg != Vanetza_Security_SymmAlgorithm_aes128Ccm) {
529 switch (enc_key->publicKey.present) {
530 case Vanetza_Security_BasePublicEncryptionKey_PR_eciesNistP256:
531 output.type = KeyType::NistP256;
532 if (copy_curve_point(output, enc_key->publicKey.choice.eciesNistP256)) {
538 case Vanetza_Security_BasePublicEncryptionKey_PR_eciesBrainpoolP256r1:
539 output.type = KeyType::BrainpoolP256r1;
540 if (copy_curve_point(output, enc_key->publicKey.choice.eciesBrainpoolP256r1)) {
552boost::optional<
Signature> get_signature(
const asn1::EtsiTs103097Certificate& cert)
554 if (!cert.signature) {
558 const asn1::Signature* asn = cert.signature;
560 switch (asn->present) {
561 case Vanetza_Security_Signature_PR_ecdsaNistP256Signature:
562 sig.type = KeyType::NistP256;
563 sig.r = get_x_coordinate(asn->choice.ecdsaNistP256Signature.rSig);
564 sig.s = fetch_octets(asn->choice.ecdsaNistP256Signature.sSig);
566 case Vanetza_Security_Signature_PR_ecdsaBrainpoolP256r1Signature:
567 sig.type = KeyType::BrainpoolP256r1;
568 sig.r = get_x_coordinate(asn->choice.ecdsaBrainpoolP256r1Signature.rSig);
569 sig.s = fetch_octets(asn->choice.ecdsaBrainpoolP256r1Signature.sSig);
571 case Vanetza_Security_Signature_PR_ecdsaBrainpoolP384r1Signature:
572 sig.type = KeyType::BrainpoolP384r1;
573 sig.r = get_x_coordinate(asn->choice.ecdsaBrainpoolP384r1Signature.rSig);
574 sig.s = fetch_octets(asn->choice.ecdsaBrainpoolP384r1Signature.sSig);
583std::list<ItsAid> get_aids(
const asn1::EtsiTs103097Certificate& cert)
585 std::list<ItsAid> aids;
586 const asn1::SequenceOfPsidSsp* seq = cert.toBeSigned.appPermissions;
588 for (
int i = 0; i < seq->list.count; ++i) {
589 aids.push_back(seq->list.array[i]->psid);
595ByteBuffer get_app_permissions(
const asn1::EtsiTs103097Certificate& cert, ItsAid aid)
598 const asn1::SequenceOfPsidSsp* seq = cert.toBeSigned.appPermissions;
600 for (
int i = 0; i < seq->list.count; ++i) {
601 if (seq->list.array[i]->psid == aid && seq->list.array[i]->ssp !=
nullptr) {
602 const asn1::ServiceSpecificPermissions& ssp = *seq->list.array[i]->ssp;
603 if (ssp.present == Vanetza_Security_ServiceSpecificPermissions_PR_bitmapSsp) {
604 const asn1::BitmapSsp& bitmap = ssp.choice.bitmapSsp;
605 perms.assign(bitmap.buf, bitmap.buf + bitmap.size);
607 }
else if (ssp.present == Vanetza_Security_ServiceSpecificPermissions_PR_opaque) {
608 const asn1::Opaque& opaque = ssp.choice.opaque;
609 perms.assign(opaque.buf, opaque.buf + opaque.size);
618void add_psid_group_permission(asn1::PsidGroupPermissions* group_permission, ItsAid aid,
const ByteBuffer& ssp,
const ByteBuffer& bitmask)
620 auto psid_range_scr = asn1::allocate<asn1::PsidSspRange>();
621 psid_range_scr->psid = aid;
622 psid_range_scr->sspRange = asn1::allocate<asn1::SspRange>();
623 psid_range_scr->sspRange->present = Vanetza_Security_SspRange_PR_bitmapSspRange;
624 OCTET_STRING_fromBuf(
625 &psid_range_scr->sspRange->choice.bitmapSspRange.sspValue,
626 reinterpret_cast<
const char*>(ssp.data()),
629 OCTET_STRING_fromBuf(
630 &psid_range_scr->sspRange->choice.bitmapSspRange.sspBitmask,
631 reinterpret_cast<
const char*>(bitmask.data()),
634 ASN_SEQUENCE_ADD(&group_permission->subjectPermissions.choice.Explicit, psid_range_scr);
639 asn1::SequenceOfPsidSsp* seq = m_struct->toBeSigned.appPermissions;
641 seq = asn1::allocate<asn1::SequenceOfPsidSsp>();
642 m_struct->toBeSigned.appPermissions = seq;
645 auto psid_ptr = asn1::allocate<asn1::PsidSsp>();
646 psid_ptr->psid = aid;
648 psid_ptr->ssp = asn1::allocate<asn1::ServiceSpecificPermissions>();
649 psid_ptr->ssp->present = Vanetza_Security_ServiceSpecificPermissions_PR_bitmapSsp;
650 OCTET_STRING_fromBuf(
651 &psid_ptr->ssp->choice.bitmapSsp,
652 reinterpret_cast<
const char *>(ssp.data()),
656 ASN_SEQUENCE_ADD(seq, psid_ptr);
661 asn1::SequenceOfPsidGroupPermissions* seq = m_struct->toBeSigned.certIssuePermissions;
663 seq = asn1::allocate<asn1::SequenceOfPsidGroupPermissions>();
664 m_struct->toBeSigned.certIssuePermissions = seq;
666 ASN_SEQUENCE_ADD(seq, group_permission);
669void Certificate::set_signature(
const SomeEcdsaSignature& signature)
671 if (!m_struct->signature) {
672 m_struct->signature = asn1::allocate<asn1::Signature>();
674 asn1::reset(m_struct->signature);
677 struct signature_visitor :
public boost::static_visitor<>
679 asn1::Signature* sig;
681 explicit signature_visitor(asn1::Signature* s) : sig(s)
687 sig->present = Vanetza_Security_Signature_PR_ecdsaNistP256Signature;
688 assign(&sig->choice.ecdsaNistP256Signature.sSig, signature.s);
689 sig->choice.ecdsaNistP256Signature.rSig = to_asn1(signature.R);
694 this->operator()(signature.get());
698 boost::apply_visitor(signature_visitor(m_struct->signature), signature);
704 cert->issuer.present = Vanetza_Security_IssuerIdentifier_PR_self;
705 cert->toBeSigned.id.present = Vanetza_Security_CertificateId_PR_none;
706 std::array<
char, 3> craca_id = { 0, 0, 0};
707 OCTET_STRING_fromBuf(&cert->toBeSigned.cracaId, craca_id.data(), craca_id.size());
709 cert->toBeSigned.crlSeries = 0;
710 cert->toBeSigned.validityPeriod.start = 0;
711 cert->toBeSigned.validityPeriod.duration.present = Vanetza_Security_Duration_PR_minutes;
712 cert->toBeSigned.validityPeriod.duration.choice.minutes = 10080;
713 cert->toBeSigned.verifyKeyIndicator.present = Vanetza_Security_VerificationKeyIndicator_PR_verificationKey;
714 cert->toBeSigned.verifyKeyIndicator.choice.verificationKey.present = Vanetza_Security_PublicVerificationKey_PR_ecdsaNistP256;
715 cert->toBeSigned.verifyKeyIndicator.choice.verificationKey.choice.ecdsaNistP256.present = Vanetza_Security_EccP256CurvePoint_PR_compressed_y_0;
716 std::array<
char, 32> dummy_r {};
717 OCTET_STRING_fromBuf(
718 &cert->toBeSigned.verifyKeyIndicator.choice.verificationKey.choice.ecdsaNistP256.choice.x_only,
719 dummy_r.data(), dummy_r.size()
727 ByteBuffer buffer = certificate.encode();
728 ar.save_binary(buffer.data(), buffer.size());
734bool contains_permission(
const Vanetza_Security_SequenceOfPsidSspRange_t& permissions, ItsAid aid)
736 for (
int i = 0; i < permissions.list.count; ++i) {
737 const auto* permission = permissions.list.array[i];
738 if (permission && permission->psid == aid) {
746bool equal(
const asn1::TwoDLocation& lhs,
const asn1::TwoDLocation& rhs)
748 return lhs.latitude == rhs.latitude && lhs.longitude == rhs.longitude;
751bool equal(
const asn1::RectangularRegion& lhs,
const asn1::RectangularRegion& rhs)
753 return equal(lhs.northWest, rhs.northWest) && equal(lhs.southEast, rhs.southEast);
756bool equal(
const asn1::SequenceOfRectangularRegion& lhs,
const asn1::SequenceOfRectangularRegion& rhs)
758 if (lhs.list.count != rhs.list.count) {
762 for (
int i = 0; i < lhs.list.count; ++i) {
763 if (!lhs.list.array[i] || !rhs.list.array[i] || !equal(*lhs.list.array[i], *rhs.list.array[i])) {
771bool is_within(
const asn1::GeographicRegion& inner,
const asn1::CircularRegion& outer)
773 if (inner.present != Vanetza_Security_GeographicRegion_PR_circularRegion) {
777 const auto& circle = inner.choice.circularRegion;
778 if (!is_valid(circle.center) || !is_valid(outer.center) || circle.radius < 0 || outer.radius < 0) {
783 inner_center.latitude = convert_latitude(circle.center.latitude);
784 inner_center.longitude = convert_longitude(circle.center.longitude);
785 return distance(inner_center, outer.center) + circle.radius * units::si::meter <= outer.radius * units::si::meter;
788bool is_within(
const asn1::GeographicRegion& inner,
const asn1::SequenceOfRectangularRegion& outer)
790 return inner.present == Vanetza_Security_GeographicRegion_PR_rectangularRegion &&
791 equal(inner.choice.rectangularRegion, outer);
794bool is_within(
const asn1::GeographicRegion&,
const asn1::PolygonalRegion&)
799bool is_within(
const asn1::GeographicRegion& inner,
const asn1::GeographicRegion& outer)
801 switch (outer.present) {
802 case Vanetza_Security_GeographicRegion_PR_circularRegion:
803 return is_within(inner, outer.choice.circularRegion);
804 case Vanetza_Security_GeographicRegion_PR_rectangularRegion:
805 return is_within(inner, outer.choice.rectangularRegion);
806 case Vanetza_Security_GeographicRegion_PR_polygonalRegion:
807 return is_within(inner, outer.choice.polygonalRegion);
808 case Vanetza_Security_GeographicRegion_PR_NOTHING:
815bool copy_curve_point(
PublicKey& to,
const asn1::EccP256CurvePoint& from)
818 switch (from.present) {
819 case Vanetza_Security_EccP256CurvePoint_PR_compressed_y_0:
820 to.compression = KeyCompression::Y0;
821 to.x = fetch_octets(from.choice.compressed_y_0);
823 case Vanetza_Security_EccP256CurvePoint_PR_compressed_y_1:
824 to.compression = KeyCompression::Y1;
825 to.x = fetch_octets(from.choice.compressed_y_1);
827 case Vanetza_Security_EccP256CurvePoint_PR_uncompressedP256:
828 to.compression = KeyCompression::NoCompression;
829 to.x = fetch_octets(from.choice.uncompressedP256.x);
830 to.y = fetch_octets(from.choice.uncompressedP256.y);
840bool copy_curve_point(
PublicKey& to,
const asn1::EccP384CurvePoint& from)
843 switch (from.present) {
844 case Vanetza_Security_EccP384CurvePoint_PR_compressed_y_0:
845 to.compression = KeyCompression::Y0;
846 to.x = fetch_octets(from.choice.compressed_y_0);
848 case Vanetza_Security_EccP384CurvePoint_PR_compressed_y_1:
849 to.compression = KeyCompression::Y1;
850 to.x = fetch_octets(from.choice.compressed_y_1);
852 case Vanetza_Security_EccP384CurvePoint_PR_uncompressedP384:
853 to.compression = KeyCompression::NoCompression;
854 to.x = fetch_octets(from.choice.uncompressedP384.x);
855 to.y = fetch_octets(from.choice.uncompressedP384.y);
865HashAlgorithm digest_hash_algorithm(
const asn1::EtsiTs103097Certificate& cert)
870 const asn1::VerificationKeyIndicator& indicator = cert.toBeSigned.verifyKeyIndicator;
871 switch (indicator.present) {
872 case Vanetza_Security_VerificationKeyIndicator_PR_verificationKey:
873 switch (indicator.choice.verificationKey.present) {
874 case Vanetza_Security_PublicVerificationKey_PR_ecdsaNistP256:
875 case Vanetza_Security_PublicVerificationKey_PR_ecdsaBrainpoolP256r1:
876 return HashAlgorithm::SHA256;
877 case Vanetza_Security_PublicVerificationKey_PR_ecdsaBrainpoolP384r1:
878 return HashAlgorithm::SHA384;
880 return HashAlgorithm::Unspecified;
882 case Vanetza_Security_VerificationKeyIndicator_PR_reconstructionValue:
883 return HashAlgorithm::SHA256;
885 return HashAlgorithm::Unspecified;
889ByteBuffer fetch_octets(
const OCTET_STRING_t& octets)
891 ByteBuffer buffer(octets.size);
892 std::memcpy(buffer.data(), octets.buf, octets.size);
896ByteBuffer get_x_coordinate(
const asn1::EccP256CurvePoint& point)
898 switch (point.present) {
899 case Vanetza_Security_EccP256CurvePoint_PR_compressed_y_0:
900 return fetch_octets(point.choice.compressed_y_0);
901 case Vanetza_Security_EccP256CurvePoint_PR_compressed_y_1:
902 return fetch_octets(point.choice.compressed_y_1);
903 case Vanetza_Security_EccP256CurvePoint_PR_x_only:
904 return fetch_octets(point.choice.x_only);
905 case Vanetza_Security_EccP256CurvePoint_PR_uncompressedP256:
906 return fetch_octets(point.choice.uncompressedP256.x);
908 return ByteBuffer {};
912ByteBuffer get_x_coordinate(
const asn1::EccP384CurvePoint& point)
914 switch (point.present) {
915 case Vanetza_Security_EccP384CurvePoint_PR_compressed_y_0:
916 return fetch_octets(point.choice.compressed_y_0);
917 case Vanetza_Security_EccP384CurvePoint_PR_compressed_y_1:
918 return fetch_octets(point.choice.compressed_y_1);
919 case Vanetza_Security_EccP384CurvePoint_PR_x_only:
920 return fetch_octets(point.choice.x_only);
921 case Vanetza_Security_EccP384CurvePoint_PR_uncompressedP384:
922 return fetch_octets(point.choice.uncompressedP384.x);
924 return ByteBuffer {};
930 switch (point.present) {
931 case Vanetza_Security_EccP256CurvePoint_PR_compressed_y_0:
932 case Vanetza_Security_EccP256CurvePoint_PR_compressed_y_1:
941 switch (point.present) {
942 case Vanetza_Security_EccP384CurvePoint_PR_compressed_y_0:
943 case Vanetza_Security_EccP384CurvePoint_PR_compressed_y_1:
950bool is_signature_x_only(
const Vanetza_Security_Signature_t& sig)
952 switch (sig.present) {
953 case Vanetza_Security_Signature_PR_ecdsaNistP256Signature:
954 return sig.choice.ecdsaNistP256Signature.rSig.present == Vanetza_Security_EccP256CurvePoint_PR_x_only;
955 case Vanetza_Security_Signature_PR_ecdsaBrainpoolP256r1Signature:
956 return sig.choice.ecdsaBrainpoolP256r1Signature.rSig.present == Vanetza_Security_EccP256CurvePoint_PR_x_only;
957 case Vanetza_Security_Signature_PR_ecdsaBrainpoolP384r1Signature:
958 return sig.choice.ecdsaBrainpoolP384r1Signature.rSig.present == Vanetza_Security_EccP384CurvePoint_PR_x_only;
966 if (point.present == Vanetza_Security_EccP256CurvePoint_PR_uncompressedP256) {
967 auto& unc = point.choice.uncompressedP256;
968 const bool y_odd = unc.y.size > 0 && unc.y.buf[unc.y.size - 1] & 0x01;
970 std::free(unc._asn_ctx.ptr);
971 unc._asn_ctx.ptr =
nullptr;
973 assert(&point.choice.uncompressedP256.x == &point.choice.compressed_y_1);
974 point.present = Vanetza_Security_EccP256CurvePoint_PR_compressed_y_1;
976 assert(&point.choice.uncompressedP256.x == &point.choice.compressed_y_0);
977 point.present = Vanetza_Security_EccP256CurvePoint_PR_compressed_y_0;
980 }
else if (point.present == Vanetza_Security_EccP256CurvePoint_PR_compressed_y_0 || point.present == Vanetza_Security_EccP256CurvePoint_PR_compressed_y_1) {
989 if (point.present == Vanetza_Security_EccP384CurvePoint_PR_uncompressedP384) {
990 auto& unc = point.choice.uncompressedP384;
991 const bool y_odd = unc.y.size > 0 && unc.y.buf[unc.y.size - 1] & 0x01;
993 std::free(unc._asn_ctx.ptr);
994 unc._asn_ctx.ptr =
nullptr;
996 assert(&point.choice.uncompressedP384.x == &point.choice.compressed_y_1);
997 point.present = Vanetza_Security_EccP384CurvePoint_PR_compressed_y_1;
999 assert(&point.choice.uncompressedP384.x == &point.choice.compressed_y_0);
1000 point.present = Vanetza_Security_EccP384CurvePoint_PR_compressed_y_0;
1003 }
else if (point.present == Vanetza_Security_EccP384CurvePoint_PR_compressed_y_0 || point.present == Vanetza_Security_EccP384CurvePoint_PR_compressed_y_1) {
1012 if (point.present == Vanetza_Security_EccP256CurvePoint_PR_uncompressedP256) {
1013 auto& unc = point.choice.uncompressedP256;
1014 asn1::reset(&unc.y);
1015 std::free(unc._asn_ctx.ptr);
1016 unc._asn_ctx.ptr =
nullptr;
1017 assert(&unc.x == &point.choice.x_only);
1018 point.present = Vanetza_Security_EccP256CurvePoint_PR_x_only;
1020 }
else if (point.present == Vanetza_Security_EccP256CurvePoint_PR_x_only) {
1029 if (point.present == Vanetza_Security_EccP384CurvePoint_PR_uncompressedP384) {
1030 auto& unc = point.choice.uncompressedP384;
1031 asn1::reset(&unc.y);
1032 std::free(unc._asn_ctx.ptr);
1033 unc._asn_ctx.ptr =
nullptr;
1034 assert(&unc.x == &point.choice.x_only);
1035 point.present = Vanetza_Security_EccP384CurvePoint_PR_x_only;
1037 }
else if (point.present == Vanetza_Security_EccP384CurvePoint_PR_x_only) {
1046 switch (sig.present) {
1047 case Vanetza_Security_Signature_PR_ecdsaNistP256Signature:
1048 return make_x_only(sig.choice.ecdsaNistP256Signature.rSig);
1050 case Vanetza_Security_Signature_PR_ecdsaBrainpoolP256r1Signature:
1051 return make_x_only(sig.choice.ecdsaBrainpoolP256r1Signature.rSig);
1053 case Vanetza_Security_Signature_PR_ecdsaBrainpoolP384r1Signature:
1054 return make_x_only(sig.choice.ecdsaBrainpoolP384r1Signature.rSig);
ByteBuffer encode() const
boost::optional< Certificate > canonicalize() const
bool valid_at_timepoint(const Clock::time_point &time_point) const
StartAndEndValidity get_start_and_end_validity() const
bool is_allowed_to_issue(ItsAid aid) const
bool is_at_certificate() const
bool is_ca_certificate() const
bool issuer_is_self() const
bool valid_for_application(ItsAid aid) const
boost::optional< HashedId8 > calculate_digest() const
bool valid_at_location(const PositionFix &location, const LocationChecker *lc) const
bool has_region_restriction() const
bool region_is_within(const CertificateView &issuer) const
boost::optional< std::uint8_t > assurance_level() const
boost::optional< HashedId8 > issuer_digest() const
KeyType get_verification_key_type() const
bool is_canonical() const
EcdsaSignature specified in TS 103 097 v1.2.1, section 4.2.9.
void add_cert_issue_permission(asn1::PsidGroupPermissions *group_permission)
add cert issuing permission
void add_app_permission(ItsAid aid, const ByteBuffer &ssp)
add application permissions as bitmap