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