Vanetza
Loading...
Searching...
No Matches
naive_certificate_provider.cpp
1#include <vanetza/common/its_aid.hpp>
2#include <vanetza/security/v3/naive_certificate_provider.hpp>
3#include <array>
4
5namespace vanetza
6{
7namespace security
8{
9namespace v3
10{
11
12namespace
13{
14
15struct assign_compressed_ecc_point : public boost::static_visitor<>
16{
17 assign_compressed_ecc_point(Vanetza_Security_EccP256CurvePoint* point) : point(point)
18 {
19 }
20
21 void operator()(const Compressed_Lsb_Y_0& y0) const
22 {
23 point->present = Vanetza_Security_EccP256CurvePoint_PR_compressed_y_0;
24 OCTET_STRING_fromBuf(&point->choice.compressed_y_0, reinterpret_cast<const char*>(y0.x.data()), y0.x.size());
25 }
26
27 void operator()(const Compressed_Lsb_Y_1& y1) const
28 {
29 point->present = Vanetza_Security_EccP256CurvePoint_PR_compressed_y_1;
30 OCTET_STRING_fromBuf(&point->choice.compressed_y_1, reinterpret_cast<const char*>(y1.x.data()), y1.x.size());
31 }
32
33 template<typename T>
34 void operator()(const T&) const
35 {
36 point->present = Vanetza_Security_EccP256CurvePoint_PR_NOTHING;
37 }
38
40};
41
42} // namespace
43
44
45NaiveCertificateProvider::NaiveCertificateProvider(const Runtime& rt) :
46 m_crypto_backend(create_backend("default")),
47 m_runtime(rt),
48 m_own_key_pair(m_crypto_backend->generate_key_pair()),
49 m_own_certificate(generate_authorization_ticket()) { }
50
52{
53 // Implement the renewal
54 return m_own_certificate;
55}
56
58{
59 static PrivateKey private_key;
60 private_key.type = KeyType::NistP256;
61 private_key.key.resize(m_own_key_pair.private_key.key.size());
62 std::copy(m_own_key_pair.private_key.key.begin(), m_own_key_pair.private_key.key.end(), private_key.key.data());
63 return private_key;
64}
65
67{
68 static const ecdsa256::KeyPair aa_key_pair = m_crypto_backend->generate_key_pair();
69
70 return aa_key_pair;
71}
72
74{
75 static const ecdsa256::KeyPair root_key_pair = m_crypto_backend->generate_key_pair();
76
77 return root_key_pair;
78}
79
81{
82 static const std::string aa_subject("Naive Authorization CA");
83 static const Certificate aa_certificate = generate_aa_certificate(aa_subject);
84
85 return aa_certificate;
86}
87
89{
90 static const std::string root_subject("Naive Root CA");
91 static const Certificate root_certificate = generate_root_certificate(root_subject);
92
93 return root_certificate;
94}
95
97{
98 // create certificate
99 Certificate certificate;
100
101 const Certificate& aa_certificate = this->aa_certificate();
102
103 // section 6 in TS 103 097 v2.1.1
104 certificate->issuer.present= Vanetza_Security_IssuerIdentifier_PR_sha256AndDigest;
105 auto maybe_aa_cert_digest = aa_certificate.calculate_digest();
106 if (maybe_aa_cert_digest) {
107 const HashedId8& aa_cert_digest = *maybe_aa_cert_digest;
108 OCTET_STRING_fromBuf(
109 &(certificate->issuer.choice.sha256AndDigest),
110 reinterpret_cast<const char *>(aa_cert_digest.data()),
111 aa_cert_digest.size()
112 );
113 }
114
115 // section 6 in TS 103 097 v2.1.1
116 certificate->toBeSigned.id.present = Vanetza_Security_CertificateId_PR_none;
117 std::vector<uint8_t> craciId(3, 0);
118 OCTET_STRING_fromBuf(
119 &certificate->toBeSigned.cracaId,
120 reinterpret_cast<const char*>(craciId.data()),
121 craciId.size()
122 );
123 certificate->version = 3;
124 certificate->toBeSigned.crlSeries = 0;
125
126 // section 7.2.1 in TS 103 097 v2.1.1
127 certificate.add_app_permission(aid::CA, ByteBuffer({ 1, 0, 0 }));
128 certificate.add_app_permission(aid::DEN, ByteBuffer({ 1, 0xff, 0xff, 0xff}));
129 certificate.add_app_permission(aid::GN_MGMT, ByteBuffer({})); // required for beacons
130 certificate.add_app_permission(aid::IPV6_ROUTING, ByteBuffer({})); // required for routing tests
131
132 // section 6 in TS 103 097 v2.1.1
133 // set subject attributes
134 // set the verification_key
135 Uncompressed coordinates;
136 coordinates.x.assign(m_own_key_pair.public_key.x.begin(), m_own_key_pair.public_key.x.end());
137 coordinates.y.assign(m_own_key_pair.public_key.y.begin(), m_own_key_pair.public_key.y.end());
138 certificate->toBeSigned.verifyKeyIndicator.present = Vanetza_Security_VerificationKeyIndicator_PR_verificationKey;
139 certificate->toBeSigned.verifyKeyIndicator.choice.verificationKey.present = Vanetza_Security_PublicVerificationKey_PR_ecdsaNistP256;
140 certificate->toBeSigned.verifyKeyIndicator.choice.verificationKey.choice.ecdsaNistP256.present = Vanetza_Security_EccP256CurvePoint_PR_uncompressedP256;
141 OCTET_STRING_fromBuf(
142 &certificate->toBeSigned.verifyKeyIndicator.choice.verificationKey.choice.ecdsaNistP256.choice.uncompressedP256.x,
143 reinterpret_cast<const char*>(coordinates.x.data()),
144 coordinates.x.size()
145 );
146 OCTET_STRING_fromBuf(
147 &certificate->toBeSigned.verifyKeyIndicator.choice.verificationKey.choice.ecdsaNistP256.choice.uncompressedP256.y,
148 reinterpret_cast<const char*>(coordinates.y.data()),
149 coordinates.y.size()
150 );
151
152 // section 6 in TS 103 097 v2.1.1
153 // No constraint
154 // set validity restriction
155
156 certificate->toBeSigned.validityPeriod.start = v2::convert_time32(m_runtime.now() - std::chrono::hours(1));;
157 certificate->toBeSigned.validityPeriod.duration.present = Vanetza_Security_Duration_PR_hours;
158 certificate->toBeSigned.validityPeriod.duration.choice.hours = 23;
159
161
162 return certificate;
163}
164
166{
167 ByteBuffer data_buffer = certificate.encode();
168 // TODO build to-be-signed data buffer correctly
169 certificate.set_signature(m_crypto_backend->sign_data(aa_key_pair().private_key, data_buffer));
170}
171
173{
174 Certificate aa_certificate;
175
176 //section 7.2.4 in TS 103 097 v2.1.1
177 Certificate root_cert = this->root_certificate();
178 aa_certificate->issuer.present= Vanetza_Security_IssuerIdentifier_PR_sha256AndDigest;
179 auto maybe_root_cert_digest = root_cert.calculate_digest();
180 if (maybe_root_cert_digest) {
181 const HashedId8& root_cert_digest = *maybe_root_cert_digest;
182 OCTET_STRING_fromBuf(
183 &(aa_certificate->issuer.choice.sha256AndDigest),
184 reinterpret_cast<const char *>(root_cert_digest.data()),
185 root_cert_digest.size()
186 );
187 }
188
189 aa_certificate->toBeSigned.id.present = Vanetza_Security_CertificateId_PR_name;
190 OCTET_STRING_fromBuf(&aa_certificate->toBeSigned.id.choice.name, name.data(), name.size());
191
192 // section 6 in TS 103 097 v2.1.1
193 static const std::array<char, 3> craciId { 0, 0, 0 };
194 OCTET_STRING_fromBuf(&aa_certificate->toBeSigned.cracaId, craciId.data(), craciId.size());
195 aa_certificate->version = 3;
196 aa_certificate->toBeSigned.crlSeries = 0;
197
198 // section 7.2.4 in TS 103 097 v2.1.1
199 // certIssuePermissions shall be used to indicate issuing permissions
200 // See https://cpoc.jrc.ec.europa.eu/data/documents/e01941_CPOC_Protocol_v3.0_20240206.pdf for detailled cert_permissions
201 // I.3.8. certIssuePermissions with predefined values
202 asn1::PsidGroupPermissions* cert_permission_message = asn1::allocate<asn1::PsidGroupPermissions>();
203 cert_permission_message->subjectPermissions.present = Vanetza_Security_SubjectPermissions_PR_explicit;
204 add_psid_group_permission(cert_permission_message,aid::CA, {0x01, 0xff, 0xfc}, {0xff, 0x00, 0x03});
205 add_psid_group_permission(cert_permission_message,aid::DEN, {0x01, 0xff, 0xff, 0xff}, {0xff, 0x00, 0x00, 0x00});
206 add_psid_group_permission(cert_permission_message,aid::TLM, {0x01, 0xe0}, {0xff, 0x1f});
207 add_psid_group_permission(cert_permission_message,aid::RLT, {0x01, 0xc0}, {0xff, 0x3f});
208 add_psid_group_permission(cert_permission_message,aid::IVI, {0x01, 0xff, 0xff, 0xff, 0xff, 0xf8}, {0xff, 0x00, 0x00, 0x00, 0x00, 0x07});
209 add_psid_group_permission(cert_permission_message,aid::TLC_R, {0x02, 0xff, 0xff, 0xe0}, {0xff, 0x00, 0x00, 0x1f});
210 add_psid_group_permission(cert_permission_message,aid::GN_MGMT, {0x00}, {0xff});
211 aa_certificate.add_cert_issue_permission(cert_permission_message);
212
213 // section 6 in TS 103 097 v2.1.1
214 // set subject attributes
215 // set the verification_key
216 auto coordinates = compress_public_key(m_own_key_pair.public_key);
217 aa_certificate->toBeSigned.verifyKeyIndicator.present = Vanetza_Security_VerificationKeyIndicator_PR_verificationKey;
218 aa_certificate->toBeSigned.verifyKeyIndicator.choice.verificationKey.present = Vanetza_Security_PublicVerificationKey_PR_ecdsaNistP256;
219 boost::apply_visitor(assign_compressed_ecc_point(&aa_certificate->toBeSigned.verifyKeyIndicator.choice.verificationKey.choice.ecdsaNistP256), coordinates);
220
221 aa_certificate->toBeSigned.validityPeriod.start = v2::convert_time32(m_runtime.now() - std::chrono::hours(1));;
222 aa_certificate->toBeSigned.validityPeriod.duration.present = Vanetza_Security_Duration_PR_years;
223 aa_certificate->toBeSigned.validityPeriod.duration.choice.hours = 4;
224
225 Uncompressed encryption_key;
226 encryption_key.x.assign(m_own_key_pair.public_key.x.begin(), m_own_key_pair.public_key.x.end());
227 encryption_key.y.assign(m_own_key_pair.public_key.y.begin(), m_own_key_pair.public_key.y.end());
228 aa_certificate->toBeSigned.encryptionKey = asn1::allocate<asn1::PublicEncryptionKey>();
229 aa_certificate->toBeSigned.encryptionKey->publicKey.present = Vanetza_Security_BasePublicEncryptionKey_PR_eciesNistP256;
230 aa_certificate->toBeSigned.encryptionKey->publicKey.choice.eciesNistP256.present = Vanetza_Security_EccP256CurvePoint_PR_uncompressedP256;
231 OCTET_STRING_fromBuf(
232 &aa_certificate->toBeSigned.encryptionKey->publicKey.choice.eciesNistP256.choice.uncompressedP256.x,
233 reinterpret_cast<const char*>(encryption_key.x.data()),
234 encryption_key.x.size()
235 );
236 OCTET_STRING_fromBuf(
237 &aa_certificate->toBeSigned.encryptionKey->publicKey.choice.eciesNistP256.choice.uncompressedP256.y,
238 reinterpret_cast<const char*>(encryption_key.y.data()),
239 encryption_key.y.size()
240 );
241
242
243 sign_authorization_ticket(aa_certificate);
244
245 return aa_certificate;
246}
247
249{
250 Certificate root_certificate;
251
252 //section 7.2.3 in TS 103 097 v2.1.1
253 root_certificate->issuer.present = Vanetza_Security_IssuerIdentifier_PR_self;
254 root_certificate->toBeSigned.id.present = Vanetza_Security_CertificateId_PR_name;
255 OCTET_STRING_fromBuf(&root_certificate->toBeSigned.id.choice.name, name.data(), name.size());
256
257 // section 6 in TS 103 097 v2.1.1
258 static const std::array<char, 3> craciId = { 0, 0, 0 };
259 OCTET_STRING_fromBuf(&root_certificate->toBeSigned.cracaId, craciId.data(), craciId.size());
260 root_certificate->version = 3;
261 root_certificate->toBeSigned.crlSeries = 0;
262
263 // section 7.2.3 in TS 103 097 v2.1.1
264 root_certificate.add_app_permission(aid::CRL, ByteBuffer({0x01}));
265 root_certificate.add_app_permission(aid::CTL, ByteBuffer({0x018}));
266
267 // section 7.2.3 in TS 103 097 v2.1.1
268 // certIssuePermissions shall be used to indicate issuing permissions
269 // See https://cpoc.jrc.ec.europa.eu/data/documents/e01941_CPOC_Protocol_v3.0_20240206.pdf for detailled cert_permissions
270 // I.3.8. certIssuePermissions with predefined values
271 auto cert_permission = asn1::allocate<asn1::PsidGroupPermissions>();
272 cert_permission->subjectPermissions.present = Vanetza_Security_SubjectPermissions_PR_explicit;
273 add_psid_group_permission(cert_permission, aid::SCR, {0x01, 0x3e}, {0xff, 0xc1});
274 root_certificate.add_cert_issue_permission(cert_permission);
275
276 auto cert_permission_message = asn1::allocate<asn1::PsidGroupPermissions>();
277 cert_permission_message->subjectPermissions.present = Vanetza_Security_SubjectPermissions_PR_explicit;
278 add_psid_group_permission(cert_permission_message,aid::CA, {0x01, 0xff, 0xfc}, {0xff, 0x00, 0x03});
279 add_psid_group_permission(cert_permission_message,aid::DEN, {0x01, 0xff, 0xff, 0xff}, {0xff, 0x00, 0x00, 0x00});
280 add_psid_group_permission(cert_permission_message,aid::TLM, {0x01, 0xe0}, {0xff, 0x1f});
281 add_psid_group_permission(cert_permission_message,aid::RLT, {0x01, 0xc0}, {0xff,0x3f});
282 add_psid_group_permission(cert_permission_message,aid::IVI, {0x01, 0xff, 0xff,0xff,0xff,0xf8}, {0xff, 0x00, 0x00, 0x00, 0x00, 0x07});
283 add_psid_group_permission(cert_permission_message,aid::TLC_R, {0x02, 0xff, 0xff,0xe0}, {0xff, 0x00, 0x00, 0x1f});
284 add_psid_group_permission(cert_permission_message,aid::GN_MGMT, {0x00}, {0xff});
285 root_certificate.add_cert_issue_permission(cert_permission_message);
286
287 // section 6 in TS 103 097 v2.1.1
288 // set subject attributes
289 // set the verification_key
290 EccPoint coordinates = compress_public_key(m_own_key_pair.public_key);
291 root_certificate->toBeSigned.verifyKeyIndicator.present = Vanetza_Security_VerificationKeyIndicator_PR_verificationKey;
292 root_certificate->toBeSigned.verifyKeyIndicator.choice.verificationKey.present = Vanetza_Security_PublicVerificationKey_PR_ecdsaNistP256;
293 boost::apply_visitor(assign_compressed_ecc_point(&root_certificate->toBeSigned.verifyKeyIndicator.choice.verificationKey.choice.ecdsaNistP256), coordinates);
294 root_certificate->toBeSigned.validityPeriod.start = v2::convert_time32(m_runtime.now() - std::chrono::hours(1));;
295 root_certificate->toBeSigned.validityPeriod.duration.present = Vanetza_Security_Duration_PR_years;
296 root_certificate->toBeSigned.validityPeriod.duration.choice.hours = 4;
297
298 sign_authorization_ticket(root_certificate);
299
300 return root_certificate;
301}
302
303} // namespace v3
304} // namespace security
305} // namespace vanetza
boost::optional< HashedId8 > calculate_digest() const
void sign_authorization_ticket(Certificate &certificate)
sign an authorization ticket
const ecdsa256::KeyPair & aa_key_pair()
get root key (same for all instances)
Certificate generate_root_certificate(const std::string &subject_name)
generate a root certificate
Certificate generate_aa_certificate(const std::string &subject_name)
generate a authorization authority certificate
const Certificate & own_certificate() override
get own certificate for signing
Certificate generate_authorization_ticket()
generate an authorization ticket
const Certificate & root_certificate()
get root certificate (same for all instances)
const PrivateKey & own_private_key() override
get own private key
const ecdsa256::KeyPair & root_key_pair()
get root key (same for all instances)
const Certificate & aa_certificate()
get ticket signer certificate (same for all instances)
Compressed_Lsb_Y_0 specified in TS 103 097 v1.2.1 in section 4.2.5.
Definition ecc_point.hpp:24
Compressed_Lsb_Y_1 specified in TS 103 097 v1.2.1 in section 4.2.5.
Definition ecc_point.hpp:30
Uncompressed specified in TS 103 097 v1.2.1 in section 4.2.5.
Definition ecc_point.hpp:36
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