1#include <vanetza/common/its_aid.hpp>
2#include <vanetza/common/position_fix.hpp>
3#include <vanetza/security/hashed_id.hpp>
4#include <vanetza/security/v2/certificate.hpp>
5#include <vanetza/security/v2/certificate_cache.hpp>
6#include <vanetza/security/v2/default_certificate_validator.hpp>
7#include <vanetza/security/v2/signature.hpp>
8#include <vanetza/security/v2/trust_store.hpp>
9#include <vanetza/security/v2/validity_restriction.hpp>
22boost::optional<StartAndEndValidity> extract_validity_time(
const Certificate& certificate)
24 boost::optional<StartAndEndValidity> restriction;
26 for (
auto& validity_restriction : certificate.validity_restriction) {
27 ValidityRestrictionType type = get_type(validity_restriction);
29 if (type == ValidityRestrictionType::Time_Start_And_End) {
35 restriction = boost::get<StartAndEndValidity>(validity_restriction);
38 if (restriction->start_validity >= restriction->end_validity) {
41 }
else if (type == ValidityRestrictionType::Time_End) {
44 }
else if (type == ValidityRestrictionType::Time_Start_And_Duration) {
53bool check_time_consistency(
const Certificate& certificate,
const Certificate& signer)
55 boost::optional<StartAndEndValidity> certificate_time = extract_validity_time(certificate);
56 boost::optional<StartAndEndValidity> signer_time = extract_validity_time(signer);
58 if (!certificate_time || !signer_time) {
62 if (signer_time->start_validity > certificate_time->start_validity) {
66 if (signer_time->end_validity < certificate_time->end_validity) {
73std::list<ItsAid> extract_application_identifiers(
const Certificate& certificate)
75 std::list<ItsAid> aids;
77 auto certificate_type = certificate.subject_info.subject_type;
78 if (certificate_type == SubjectType::Authorization_Ticket) {
79 auto list = certificate.get_attribute<SubjectAttributeType::ITS_AID_SSP_List>();
81 for (
auto& item : *list) {
82 aids.push_back(item.its_aid.get());
86 auto list = certificate.get_attribute<SubjectAttributeType::ITS_AID_List>();
88 for (
auto& item : *list) {
89 aids.push_back(item.get());
97bool check_permission_consistency(
const Certificate& certificate,
const Certificate& signer)
99 auto certificate_aids = extract_application_identifiers(certificate);
100 auto signer_aids = extract_application_identifiers(signer);
101 auto compare = [](ItsAid a, ItsAid b) {
return a < b; };
103 certificate_aids.sort(compare);
104 signer_aids.sort(compare);
106 return std::includes(signer_aids.begin(), signer_aids.end(), certificate_aids.begin(), certificate_aids.end());
109bool check_subject_assurance_consistency(
const Certificate& certificate,
const Certificate& signer)
111 auto certificate_assurance = certificate.get_attribute<SubjectAttributeType::Assurance_Level>();
112 auto signer_assurance = signer.get_attribute<SubjectAttributeType::Assurance_Level>();
114 if (!certificate_assurance || !signer_assurance) {
119 if (certificate_assurance->assurance() > signer_assurance->assurance()) {
121 }
else if (certificate_assurance->assurance() == signer_assurance->assurance()) {
122 if (certificate_assurance->confidence() > signer_assurance->confidence()) {
130bool check_region_consistency(
const Certificate& certificate,
const Certificate& signer)
132 auto certificate_region = certificate.get_restriction<ValidityRestrictionType::Region>();
133 auto signer_region = signer.get_restriction<ValidityRestrictionType::Region>();
135 if (!signer_region) {
139 if (!certificate_region) {
143 return is_within(*certificate_region, *signer_region);
146bool check_consistency(
const Certificate& certificate,
const Certificate& signer)
148 if (!check_time_consistency(certificate, signer)) {
152 if (!check_permission_consistency(certificate, signer)) {
156 if (!check_subject_assurance_consistency(certificate, signer)) {
160 if (!check_region_consistency(certificate, signer)) {
169DefaultCertificateValidator::DefaultCertificateValidator(Backend& backend, CertificateCache& cert_cache,
const TrustStore& trust_store) :
170 m_crypto_backend(backend),
171 m_cert_cache(cert_cache),
172 m_trust_store(trust_store)
178 if (!extract_validity_time(certificate)) {
179 return CertificateInvalidReason::Broken_Time_Period;
182 if (!certificate.
get_attribute<SubjectAttributeType::Assurance_Level>()) {
183 return CertificateInvalidReason::Missing_Subject_Assurance;
186 SubjectType subject_type = certificate.subject_info.subject_type;
189 if (subject_type == SubjectType::Authorization_Ticket && 0 != certificate.subject_info.subject_name.size()) {
190 return CertificateInvalidReason::Invalid_Name;
193 if (get_type(certificate.signer_info) != SignerInfoType::Certificate_Digest_With_SHA256) {
194 return CertificateInvalidReason::Invalid_Signer;
197 HashedId8 signer_hash = boost::get<HashedId8>(certificate.signer_info);
200 boost::optional<EcdsaSignature> sig = extract_ecdsa_signature(certificate.signature);
202 return CertificateInvalidReason::Missing_Signature;
206 ByteBuffer binary_cert = convert_for_signing(certificate);
209 if (subject_type == SubjectType::Authorization_Ticket) {
210 for (
auto& possible_signer : m_cert_cache.lookup(signer_hash, SubjectType::Authorization_Authority)) {
211 auto verification_key = get_public_key(possible_signer, m_crypto_backend);
212 if (!verification_key) {
216 if (m_crypto_backend.verify_data(verification_key.get(), binary_cert, sig.get())) {
217 if (!check_consistency(certificate, possible_signer)) {
218 return CertificateInvalidReason::Inconsistent_With_Signer;
221 return CertificateValidity::valid();
228 if (subject_type == SubjectType::Authorization_Authority) {
229 for (
auto& possible_signer : m_trust_store.lookup(signer_hash)) {
230 auto verification_key = get_public_key(possible_signer, m_crypto_backend);
231 if (!verification_key) {
235 if (m_crypto_backend.verify_data(verification_key.get(), binary_cert, sig.get())) {
236 if (!check_consistency(certificate, possible_signer)) {
237 return CertificateInvalidReason::Inconsistent_With_Signer;
240 return CertificateValidity::valid();
245 return CertificateInvalidReason::Unknown_Signer;
described in TS 103 097 v1.2.1 (2015-06), section 6.1
const SubjectAttribute * get_attribute(SubjectAttributeType type) const