Vanetza
 
Loading...
Searching...
No Matches
certificate_cache.cpp
1#include <vanetza/security/v2/certificate_cache.hpp>
2#include <chrono>
3
4namespace vanetza
5{
6namespace security
7{
8namespace v2
9{
10
11CertificateCache::CertificateCache(const Runtime& rt) : m_runtime(rt)
12{
13}
14
15void CertificateCache::insert(const Certificate& certificate)
16{
17 const HashedId8 id = calculate_hash(certificate);
18
19 // this may drop expired entries and extend some's lifetime
20 std::list<Certificate> certs = lookup(id, certificate.subject_info.subject_type);
21
22 // TODO: implement equality comparison for Certificate
23 if (certs.size()) {
24 const auto binary_insert = convert_for_signing(certificate);
25 for (auto& cert : certs) {
26 const auto binary_found = convert_for_signing(cert);
27 if (binary_insert == binary_found) {
28 return;
29 }
30 }
31 }
32
33 Clock::duration lifetime = Clock::duration::zero();
34 if (certificate.subject_info.subject_type == SubjectType::Authorization_Ticket) {
35 // section 7.1 in ETSI TS 103 097 v1.2.1
36 // there must be a CAM with the authorization ticket every one second
37 // we choose two seconds here to account for one missed message
38 lifetime = std::chrono::seconds(2);
39 } else if (certificate.subject_info.subject_type == SubjectType::Authorization_Authority) {
40 // section 7.1 in ETSI TS 103 097 v1.2.1
41 // chains are only sent upon request, there will probably only be a few authoritation authorities in use
42 // one hour is an arbitrarily choosen cache period for now
43 lifetime = std::chrono::seconds(3600);
44 }
45
46 if (lifetime > Clock::duration::zero()) {
48 entry.certificate = certificate;
49 map_type::iterator stored = m_certificates.emplace(id, entry);
50 heap_type::handle_type& handle = stored->second.handle;
51 handle = m_expiries.push(Expiry { m_runtime.now() + lifetime, stored });
52 }
53}
54
55std::list<Certificate> CertificateCache::lookup(const HashedId8& id, SubjectType type)
56{
57 drop_expired();
58
59 using iterator = std::multimap<HashedId8, CachedCertificate>::iterator;
60 std::pair<iterator, iterator> range = m_certificates.equal_range(id);
61
62 std::list<Certificate> matches;
63 for (auto item = range.first; item != range.second; ++item) {
64 const Certificate& cert = item->second.certificate;
65
66 auto subject_type = cert.subject_info.subject_type;
67 if (subject_type != type) {
68 continue;
69 }
70
71 matches.push_back(cert);
72
73 // renew cached certificate
74 if (subject_type == SubjectType::Authorization_Ticket) {
75 refresh(item->second.handle, std::chrono::seconds(2));
76 } else if (subject_type == SubjectType::Authorization_Authority) {
77 refresh(item->second.handle, std::chrono::seconds(3600));
78 }
79 }
80
81 return matches;
82}
83
84void CertificateCache::drop_expired()
85{
86 while (!m_expiries.empty() && is_expired(m_expiries.top())) {
87 m_certificates.erase(m_expiries.top().certificate);
88 m_expiries.pop();
89 }
90}
91
92bool CertificateCache::is_expired(const Expiry& expiry) const
93{
94 return m_runtime.now() > expiry;
95}
96
97void CertificateCache::refresh(heap_type::handle_type& handle, Clock::duration lifetime)
98{
99 static_cast<Clock::time_point&>(*handle) = m_runtime.now() + lifetime;
100 m_expiries.update(handle);
101}
102
103CertificateCache::Expiry::Expiry(Clock::time_point expiry, map_type::iterator it) :
104 Clock::time_point(expiry), certificate(it)
105{
106}
107
108} // namespace v2
109} // namespace security
110} // namespace vanetza
described in TS 103 097 v1.2.1 (2015-06), section 6.1
Definition: certificate.hpp:28