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