Botan 3.9.0
Crypto and TLS for C&
x509_ext.cpp
Go to the documentation of this file.
1/*
2* X.509 Certificate Extensions
3* (C) 1999-2010,2012 Jack Lloyd
4* (C) 2016 René Korthaus, Rohde & Schwarz Cybersecurity
5* (C) 2017 Fabian Weissberg, Rohde & Schwarz Cybersecurity
6* (C) 2024 Anton Einax, Dominik Schricker
7*
8* Botan is released under the Simplified BSD License (see license.txt)
9*/
10
11#include <botan/x509_ext.h>
12
13#include <botan/assert.h>
14#include <botan/ber_dec.h>
15#include <botan/der_enc.h>
16#include <botan/hash.h>
17#include <botan/x509cert.h>
18#include <botan/internal/bit_ops.h>
19#include <botan/internal/fmt.h>
20#include <botan/internal/int_utils.h>
21#include <botan/internal/loadstor.h>
22#include <botan/internal/x509_utils.h>
23#include <algorithm>
24#include <set>
25#include <sstream>
26
27namespace Botan {
28
29namespace {
30
31template <std::derived_from<Certificate_Extension> T>
32auto make_extension([[maybe_unused]] const OID& oid) {
33 BOTAN_DEBUG_ASSERT(oid == T::static_oid());
34 return std::make_unique<T>();
35}
36
37std::unique_ptr<Certificate_Extension> extension_from_oid(const OID& oid) {
38 if(auto iso_ext = is_sub_element_of(oid, {2, 5, 29})) {
39 // NOLINTNEXTLINE(*-switch-missing-default-case)
40 switch(*iso_ext) {
41 case 14:
42 return make_extension<Cert_Extension::Subject_Key_ID>(oid);
43 case 15:
44 return make_extension<Cert_Extension::Key_Usage>(oid);
45 case 17:
46 return make_extension<Cert_Extension::Subject_Alternative_Name>(oid);
47 case 18:
48 return make_extension<Cert_Extension::Issuer_Alternative_Name>(oid);
49 case 19:
50 return make_extension<Cert_Extension::Basic_Constraints>(oid);
51 case 20:
52 return make_extension<Cert_Extension::CRL_Number>(oid);
53 case 21:
54 return make_extension<Cert_Extension::CRL_ReasonCode>(oid);
55 case 28:
56 return make_extension<Cert_Extension::CRL_Issuing_Distribution_Point>(oid);
57 case 30:
58 return make_extension<Cert_Extension::Name_Constraints>(oid);
59 case 31:
60 return make_extension<Cert_Extension::CRL_Distribution_Points>(oid);
61 case 32:
62 return make_extension<Cert_Extension::Certificate_Policies>(oid);
63 case 35:
64 return make_extension<Cert_Extension::Authority_Key_ID>(oid);
65 case 37:
66 return make_extension<Cert_Extension::Extended_Key_Usage>(oid);
67 }
68 }
69
70 if(auto pkix_ext = is_sub_element_of(oid, {1, 3, 6, 1, 5, 5, 7, 1})) {
71 // NOLINTNEXTLINE(*-switch-missing-default-case)
72 switch(*pkix_ext) {
73 case 1:
74 return make_extension<Cert_Extension::Authority_Information_Access>(oid);
75 case 7:
76 return make_extension<Cert_Extension::IPAddressBlocks>(oid);
77 case 8:
78 return make_extension<Cert_Extension::ASBlocks>(oid);
79 case 26:
80 return make_extension<Cert_Extension::TNAuthList>(oid);
81 }
82 }
83
84 return nullptr; // unknown
85}
86
87bool is_valid_telephone_number(const ASN1_String& tn) {
88 //TelephoneNumber ::= IA5String (SIZE (1..15)) (FROM ("0123456789#*"))
89 const std::string valid_tn_chars("0123456789#*");
90
91 if(tn.empty() || (tn.size() > 15)) {
92 return false;
93 }
94
95 if(tn.value().find_first_not_of(valid_tn_chars) != std::string::npos) {
96 return false;
97 }
98
99 return true;
100}
101
102} // namespace
103
104/*
105* Create a Certificate_Extension object of some kind to handle
106*/
107std::unique_ptr<Certificate_Extension> Extensions::create_extn_obj(const OID& oid,
108 bool critical,
109 const std::vector<uint8_t>& body) {
110 auto extn = extension_from_oid(oid);
111
112 if(!extn) {
113 // some other unknown extension type
114 extn = std::make_unique<Cert_Extension::Unknown_Extension>(oid, critical);
115 }
116
117 try {
118 extn->decode_inner(body);
119 } catch(Decoding_Error&) {
120 extn = std::make_unique<Cert_Extension::Unknown_Extension>(oid, critical);
121 extn->decode_inner(body);
122 }
123 return extn;
124}
125
126const Certificate_Extension& Extensions::Extensions_Info::obj() const {
127 BOTAN_ASSERT_NONNULL(m_obj.get());
128 return *m_obj;
129}
130
131/*
132* Validate the extension (the default implementation is a NOP)
133*/
135 const X509_Certificate& /*unused*/,
136 const std::vector<X509_Certificate>& /*unused*/,
137 std::vector<std::set<Certificate_Status_Code>>& /*unused*/,
138 size_t /*unused*/) {}
139
140/*
141* Add a new cert
142*/
143void Extensions::add(std::unique_ptr<Certificate_Extension> extn, bool critical) {
144 // sanity check: we don't want to have the same extension more than once
145 if(m_extension_info.contains(extn->oid_of())) {
146 const std::string name = extn->oid_name();
147 throw Invalid_Argument("Extension " + name + " already present in Extensions::add");
148 }
149
150 const OID oid = extn->oid_of();
151 Extensions_Info info(critical, std::move(extn));
152 m_extension_oids.push_back(oid);
153 m_extension_info.emplace(oid, info);
154}
155
156bool Extensions::add_new(std::unique_ptr<Certificate_Extension> extn, bool critical) {
157 if(m_extension_info.contains(extn->oid_of())) {
158 return false; // already exists
159 }
160
161 const OID oid = extn->oid_of();
162 Extensions_Info info(critical, std::move(extn));
163 m_extension_oids.push_back(oid);
164 m_extension_info.emplace(oid, info);
165 return true;
166}
167
168bool Extensions::remove(const OID& oid) {
169 const bool erased = m_extension_info.erase(oid) > 0;
170
171 if(erased) {
172 m_extension_oids.erase(std::find(m_extension_oids.begin(), m_extension_oids.end(), oid));
173 }
174
175 return erased;
176}
177
178void Extensions::replace(std::unique_ptr<Certificate_Extension> extn, bool critical) {
179 // Remove it if it existed
180 remove(extn->oid_of());
181
182 const OID oid = extn->oid_of();
183 Extensions_Info info(critical, std::move(extn));
184 m_extension_oids.push_back(oid);
185 m_extension_info.emplace(oid, info);
186}
187
188bool Extensions::extension_set(const OID& oid) const {
189 return m_extension_info.contains(oid);
190}
191
193 auto i = m_extension_info.find(oid);
194 if(i != m_extension_info.end()) {
195 return i->second.is_critical();
196 }
197 return false;
198}
199
200std::vector<uint8_t> Extensions::get_extension_bits(const OID& oid) const {
201 auto i = m_extension_info.find(oid);
202 if(i == m_extension_info.end()) {
203 throw Invalid_Argument("Extensions::get_extension_bits no such extension set");
204 }
205
206 return i->second.bits();
207}
208
210 auto extn = m_extension_info.find(oid);
211 if(extn == m_extension_info.end()) {
212 return nullptr;
213 }
214
215 return &extn->second.obj();
216}
217
218std::unique_ptr<Certificate_Extension> Extensions::get(const OID& oid) const {
219 if(const Certificate_Extension* ext = this->get_extension_object(oid)) {
220 return ext->copy();
221 }
222 return nullptr;
223}
224
225std::vector<std::pair<std::unique_ptr<Certificate_Extension>, bool>> Extensions::extensions() const {
226 std::vector<std::pair<std::unique_ptr<Certificate_Extension>, bool>> exts;
227 exts.reserve(m_extension_info.size());
228 for(auto&& ext : m_extension_info) {
229 exts.push_back(std::make_pair(ext.second.obj().copy(), ext.second.is_critical()));
230 }
231 return exts;
232}
233
234std::map<OID, std::pair<std::vector<uint8_t>, bool>> Extensions::extensions_raw() const {
235 std::map<OID, std::pair<std::vector<uint8_t>, bool>> out;
236 for(auto&& ext : m_extension_info) {
237 out.emplace(ext.first, std::make_pair(ext.second.bits(), ext.second.is_critical()));
238 }
239 return out;
240}
241
242/*
243* Encode an Extensions list
244*/
245void Extensions::encode_into(DER_Encoder& to_object) const {
246 for(const auto& [oid, extn] : m_extension_info) {
247 const bool should_encode = extn.obj().should_encode();
248
249 if(should_encode) {
250 const auto is_critical = extn.is_critical() ? std::optional<bool>{true} : std::nullopt;
251 const std::vector<uint8_t>& ext_value = extn.bits();
252
253 to_object.start_sequence()
254 .encode(oid)
255 .encode_optional(is_critical)
256 .encode(ext_value, ASN1_Type::OctetString)
257 .end_cons();
258 }
259 }
260}
261
262/*
263* Decode a list of Extensions
264*/
266 m_extension_oids.clear();
267 m_extension_info.clear();
268
269 BER_Decoder sequence = from_source.start_sequence();
270
271 while(sequence.more_items()) {
272 OID oid;
273 bool critical = false;
274 std::vector<uint8_t> bits;
275
276 sequence.start_sequence()
277 .decode(oid)
280 .end_cons();
281
282 auto obj = create_extn_obj(oid, critical, bits);
283 Extensions_Info info(critical, bits, std::move(obj));
284
285 m_extension_oids.push_back(oid);
286 m_extension_info.emplace(oid, info);
287 }
288 sequence.verify_end();
289}
290
291namespace Cert_Extension {
292
295
297 m_is_ca(is_ca), m_path_length_constraint(path_length_constraint) {
298 if(!m_is_ca && m_path_length_constraint.has_value()) {
299 // RFC 5280 Sec 4.2.1.9 "CAs MUST NOT include the pathLenConstraint field unless the cA boolean is asserted"
300 throw Invalid_Argument(
301 "Basic_Constraints nonsensical to set a path length constraint for a non-CA basicConstraints");
302 }
303}
304
305/*
306* Checked accessor for the path_length_constraint member
307*/
309 if(m_is_ca) {
310 return m_path_length_constraint.value_or(NO_CERT_PATH_LIMIT);
311 } else {
312 throw Invalid_State("Basic_Constraints::get_path_limit: Not a CA");
313 }
314}
315
316/*
317* Encode the extension
318*/
319std::vector<uint8_t> Basic_Constraints::encode_inner() const {
320 std::vector<uint8_t> output;
321
322 if(m_is_ca) {
323 DER_Encoder(output).start_sequence().encode(m_is_ca).encode_optional(m_path_length_constraint).end_cons();
324 } else {
326 }
327
328 return output;
329}
330
331/*
332* Decode the extension
333*/
334void Basic_Constraints::decode_inner(const std::vector<uint8_t>& in) {
335 BER_Decoder(in)
336 .start_sequence()
337 .decode_optional(m_is_ca, ASN1_Type::Boolean, ASN1_Class::Universal, false)
338 .decode_optional(m_path_length_constraint, ASN1_Type::Integer, ASN1_Class::Universal)
339 .end_cons();
340}
341
342/*
343* Encode the extension
344*/
345std::vector<uint8_t> Key_Usage::encode_inner() const {
346 if(m_constraints.empty()) {
347 throw Encoding_Error("Cannot encode empty PKIX key constraints");
348 }
349
350 const size_t constraint_bits = m_constraints.value();
351 const size_t unused_bits = ctz(static_cast<uint32_t>(constraint_bits));
352
353 std::vector<uint8_t> der;
354 der.push_back(static_cast<uint8_t>(ASN1_Type::BitString));
355 der.push_back(2 + ((unused_bits < 8) ? 1 : 0));
356 der.push_back(unused_bits % 8);
357 der.push_back(static_cast<uint8_t>((constraint_bits >> 8) & 0xFF));
358 if((constraint_bits & 0xFF) != 0) {
359 der.push_back(static_cast<uint8_t>(constraint_bits & 0xFF));
360 }
361
362 return der;
363}
364
365/*
366* Decode the extension
367*/
368void Key_Usage::decode_inner(const std::vector<uint8_t>& in) {
369 BER_Decoder ber(in);
370
371 BER_Object obj = ber.get_next_object();
372
373 obj.assert_is_a(ASN1_Type::BitString, ASN1_Class::Universal, "usage constraint");
374
375 if(obj.length() == 2 || obj.length() == 3) {
376 uint16_t usage = 0;
377
378 const uint8_t* bits = obj.bits();
379
380 if(bits[0] >= 8) {
381 throw BER_Decoding_Error("Invalid unused bits in usage constraint");
382 }
383
384 const uint8_t mask = static_cast<uint8_t>(0xFF << bits[0]);
385
386 if(obj.length() == 2) {
387 usage = make_uint16(bits[1] & mask, 0);
388 } else if(obj.length() == 3) {
389 usage = make_uint16(bits[1], bits[2] & mask);
390 }
391
392 m_constraints = Key_Constraints(usage);
393 } else {
394 m_constraints = Key_Constraints(0);
395 }
396}
397
398/*
399* Encode the extension
400*/
401std::vector<uint8_t> Subject_Key_ID::encode_inner() const {
402 std::vector<uint8_t> output;
403 DER_Encoder(output).encode(m_key_id, ASN1_Type::OctetString);
404 return output;
405}
406
407/*
408* Decode the extension
409*/
410void Subject_Key_ID::decode_inner(const std::vector<uint8_t>& in) {
411 BER_Decoder(in).decode(m_key_id, ASN1_Type::OctetString).verify_end();
412}
413
414/*
415* Subject_Key_ID Constructor
416*/
417Subject_Key_ID::Subject_Key_ID(const std::vector<uint8_t>& pub_key, std::string_view hash_name) {
418 auto hash = HashFunction::create_or_throw(hash_name);
419
420 m_key_id.resize(hash->output_length());
421
422 hash->update(pub_key);
423 hash->final(m_key_id.data());
424
425 // Truncate longer hashes, 192 bits here seems plenty
426 const size_t max_skid_len = (192 / 8);
427 if(m_key_id.size() > max_skid_len) {
428 m_key_id.resize(max_skid_len);
429 }
430}
431
432/*
433* Encode the extension
434*/
435std::vector<uint8_t> Authority_Key_ID::encode_inner() const {
436 std::vector<uint8_t> output;
437 DER_Encoder(output)
440 .end_cons();
441 return output;
442}
443
444/*
445* Decode the extension
446*/
447void Authority_Key_ID::decode_inner(const std::vector<uint8_t>& in) {
449}
450
451/*
452* Encode the extension
453*/
454std::vector<uint8_t> Subject_Alternative_Name::encode_inner() const {
455 std::vector<uint8_t> output;
456 DER_Encoder(output).encode(m_alt_name);
457 return output;
458}
459
460/*
461* Encode the extension
462*/
463std::vector<uint8_t> Issuer_Alternative_Name::encode_inner() const {
464 std::vector<uint8_t> output;
465 DER_Encoder(output).encode(m_alt_name);
466 return output;
467}
468
469/*
470* Decode the extension
471*/
472void Subject_Alternative_Name::decode_inner(const std::vector<uint8_t>& in) {
473 BER_Decoder(in).decode(m_alt_name);
474}
475
476/*
477* Decode the extension
478*/
479void Issuer_Alternative_Name::decode_inner(const std::vector<uint8_t>& in) {
480 BER_Decoder(in).decode(m_alt_name);
481}
482
483/*
484* Encode the extension
485*/
486std::vector<uint8_t> Extended_Key_Usage::encode_inner() const {
487 std::vector<uint8_t> output;
488 DER_Encoder(output).start_sequence().encode_list(m_oids).end_cons();
489 return output;
490}
491
492/*
493* Decode the extension
494*/
495void Extended_Key_Usage::decode_inner(const std::vector<uint8_t>& in) {
496 BER_Decoder(in).decode_list(m_oids);
497}
498
499/*
500* Encode the extension
501*/
502std::vector<uint8_t> Name_Constraints::encode_inner() const {
503 throw Not_Implemented("Name_Constraints encoding");
504}
505
506/*
507* Decode the extension
508*/
509void Name_Constraints::decode_inner(const std::vector<uint8_t>& in) {
510 BER_Decoder ber(in);
511 BER_Decoder inner = ber.start_sequence();
512
513 std::vector<GeneralSubtree> permitted;
514 if(inner.decode_optional_list(permitted, ASN1_Type(0), ASN1_Class::ExplicitContextSpecific)) {
515 if(permitted.empty()) {
516 throw Decoding_Error("Empty NameConstraint permitted list");
517 }
518 }
519
520 std::vector<GeneralSubtree> excluded;
521 if(inner.decode_optional_list(excluded, ASN1_Type(1), ASN1_Class::ExplicitContextSpecific)) {
522 if(excluded.empty()) {
523 throw Decoding_Error("Empty NameConstraint excluded list");
524 }
525 }
526
527 inner.end_cons();
528
529 if(permitted.empty() && excluded.empty()) {
530 throw Decoding_Error("Empty NameConstraint extension");
531 }
532
533 m_name_constraints = NameConstraints(std::move(permitted), std::move(excluded));
534}
535
537 const X509_Certificate& /*issuer*/,
538 const std::vector<X509_Certificate>& cert_path,
539 std::vector<std::set<Certificate_Status_Code>>& cert_status,
540 size_t pos) {
541 if(!m_name_constraints.permitted().empty() || !m_name_constraints.excluded().empty()) {
542 if(!subject.is_CA_cert()) {
543 cert_status.at(pos).insert(Certificate_Status_Code::NAME_CONSTRAINT_ERROR);
544 }
545
546 const bool issuer_name_constraint_critical = subject.is_critical("X509v3.NameConstraints");
547
548 // Check that all subordinate certs pass the name constraint
549 for(size_t j = 0; j < pos; ++j) {
550 const auto& cert = cert_path.at(j);
551
552 if(!m_name_constraints.is_permitted(cert, issuer_name_constraint_critical)) {
553 cert_status.at(j).insert(Certificate_Status_Code::NAME_CONSTRAINT_ERROR);
554 continue;
555 }
556
557 if(m_name_constraints.is_excluded(cert, issuer_name_constraint_critical)) {
558 cert_status.at(j).insert(Certificate_Status_Code::NAME_CONSTRAINT_ERROR);
559 continue;
560 }
561 }
562 }
563}
564
565namespace {
566
567/*
568* A policy specifier
569*/
570class Policy_Information final : public ASN1_Object {
571 public:
572 Policy_Information() = default;
573
574 explicit Policy_Information(const OID& oid) : m_oid(oid) {}
575
576 const OID& oid() const { return m_oid; }
577
578 void encode_into(DER_Encoder& codec) const override { codec.start_sequence().encode(m_oid).end_cons(); }
579
580 void decode_from(BER_Decoder& codec) override {
581 codec.start_sequence().decode(m_oid).discard_remaining().end_cons();
582 }
583
584 private:
585 OID m_oid;
586};
587
588} // namespace
589
590/*
591* Encode the extension
592*/
593std::vector<uint8_t> Certificate_Policies::encode_inner() const {
594 std::vector<Policy_Information> policies;
595
596 policies.reserve(m_oids.size());
597 for(const auto& oid : m_oids) {
598 policies.push_back(Policy_Information(oid));
599 }
600
601 std::vector<uint8_t> output;
602 DER_Encoder(output).start_sequence().encode_list(policies).end_cons();
603 return output;
604}
605
606/*
607* Decode the extension
608*/
609void Certificate_Policies::decode_inner(const std::vector<uint8_t>& in) {
610 std::vector<Policy_Information> policies;
611
612 BER_Decoder(in).decode_list(policies);
613 m_oids.clear();
614 for(const auto& policy : policies) {
615 m_oids.push_back(policy.oid());
616 }
617}
618
620 const X509_Certificate& /*issuer*/,
621 const std::vector<X509_Certificate>& /*cert_path*/,
622 std::vector<std::set<Certificate_Status_Code>>& cert_status,
623 size_t pos) {
624 std::set<OID> oid_set(m_oids.begin(), m_oids.end());
625 if(oid_set.size() != m_oids.size()) {
626 cert_status.at(pos).insert(Certificate_Status_Code::DUPLICATE_CERT_POLICY);
627 }
628}
629
630std::vector<uint8_t> Authority_Information_Access::encode_inner() const {
631 std::vector<uint8_t> output;
632 DER_Encoder der(output);
633
634 der.start_sequence();
635 // OCSP
636 if(!m_ocsp_responder.empty()) {
637 ASN1_String url(m_ocsp_responder, ASN1_Type::Ia5String);
638 der.start_sequence()
639 .encode(OID::from_string("PKIX.OCSP"))
640 .add_object(ASN1_Type(6), ASN1_Class::ContextSpecific, url.value())
641 .end_cons();
642 }
643
644 // CA Issuers
645 for(const auto& ca_isser : m_ca_issuers) {
646 ASN1_String asn1_ca_issuer(ca_isser, ASN1_Type::Ia5String);
647 der.start_sequence()
648 .encode(OID::from_string("PKIX.CertificateAuthorityIssuers"))
649 .add_object(ASN1_Type(6), ASN1_Class::ContextSpecific, asn1_ca_issuer.value())
650 .end_cons();
651 }
652
653 der.end_cons();
654 return output;
655}
656
657void Authority_Information_Access::decode_inner(const std::vector<uint8_t>& in) {
658 BER_Decoder ber = BER_Decoder(in).start_sequence();
659
660 while(ber.more_items()) {
661 OID oid;
662
663 BER_Decoder info = ber.start_sequence();
664
665 info.decode(oid);
666
667 if(oid == OID::from_string("PKIX.OCSP")) {
668 BER_Object name = info.get_next_object();
669
670 if(name.is_a(6, ASN1_Class::ContextSpecific)) {
671 m_ocsp_responder = ASN1::to_string(name);
672 }
673 }
674 if(oid == OID::from_string("PKIX.CertificateAuthorityIssuers")) {
675 BER_Object name = info.get_next_object();
676
677 if(name.is_a(6, ASN1_Class::ContextSpecific)) {
678 m_ca_issuers.push_back(ASN1::to_string(name));
679 }
680 }
681 }
682}
683
684/*
685* Checked accessor for the crl_number member
686*/
688 if(!m_has_value) {
689 throw Invalid_State("CRL_Number::get_crl_number: Not set");
690 }
691 return m_crl_number;
692}
693
694/*
695* Copy a CRL_Number extension
696*/
697std::unique_ptr<Certificate_Extension> CRL_Number::copy() const {
698 if(!m_has_value) {
699 throw Invalid_State("CRL_Number::copy: Not set");
700 }
701 return std::make_unique<CRL_Number>(m_crl_number);
702}
703
704/*
705* Encode the extension
706*/
707std::vector<uint8_t> CRL_Number::encode_inner() const {
708 std::vector<uint8_t> output;
709 DER_Encoder(output).encode(m_crl_number);
710 return output;
711}
712
713/*
714* Decode the extension
715*/
716void CRL_Number::decode_inner(const std::vector<uint8_t>& in) {
717 BER_Decoder(in).decode(m_crl_number);
718 m_has_value = true;
719}
720
721/*
722* Encode the extension
723*/
724std::vector<uint8_t> CRL_ReasonCode::encode_inner() const {
725 std::vector<uint8_t> output;
726 DER_Encoder(output).encode(static_cast<size_t>(m_reason), ASN1_Type::Enumerated, ASN1_Class::Universal);
727 return output;
728}
729
730/*
731* Decode the extension
732*/
733void CRL_ReasonCode::decode_inner(const std::vector<uint8_t>& in) {
734 size_t reason_code = 0;
735 BER_Decoder(in).decode(reason_code, ASN1_Type::Enumerated, ASN1_Class::Universal);
736 m_reason = static_cast<CRL_Code>(reason_code);
737}
738
739std::vector<uint8_t> CRL_Distribution_Points::encode_inner() const {
740 std::vector<uint8_t> output;
741 DER_Encoder(output).start_sequence().encode_list(m_distribution_points).end_cons();
742 return output;
743}
744
745void CRL_Distribution_Points::decode_inner(const std::vector<uint8_t>& buf) {
746 BER_Decoder(buf).decode_list(m_distribution_points).verify_end();
747
748 std::stringstream ss;
749
750 for(const auto& distribution_point : m_distribution_points) {
751 auto contents = distribution_point.point().contents();
752
753 for(const auto& pair : contents) {
754 ss << pair.first << ": " << pair.second << " ";
755 }
756 }
757
758 m_crl_distribution_urls.push_back(ss.str());
759}
760
762 const auto uris = m_point.uris();
763
764 if(uris.empty()) {
765 throw Not_Implemented("Empty CRL_Distribution_Point encoding not implemented");
766 }
767
768 for(const auto& uri : uris) {
769 der.start_sequence()
773 .end_cons()
774 .end_cons()
775 .end_cons();
776 }
777}
778
790
791std::vector<uint8_t> CRL_Issuing_Distribution_Point::encode_inner() const {
792 throw Not_Implemented("CRL_Issuing_Distribution_Point encoding");
793}
794
795void CRL_Issuing_Distribution_Point::decode_inner(const std::vector<uint8_t>& buf) {
796 BER_Decoder(buf).decode(m_distribution_point).verify_end();
797}
798
800 throw Not_Implemented("TNAuthList extension entry serialization is not supported");
801}
802
804 BER_Object obj = ber.get_next_object();
805
806 const uint32_t type_tag = static_cast<Type>(obj.type_tag());
807
808 if(type_tag == ServiceProviderCode) {
809 m_type = ServiceProviderCode;
810 ASN1_String spc_string;
811 BER_Decoder(obj).decode(spc_string);
812 m_data = std::move(spc_string);
813 } else if(type_tag == TelephoneNumberRange) {
814 m_type = TelephoneNumberRange;
815 m_data = RangeContainer();
816 auto& range_items = std::get<RangeContainer>(m_data);
818 while(list.more_items()) {
820
821 list.decode(entry.start);
822 if(!is_valid_telephone_number(entry.start)) {
823 throw Decoding_Error(fmt("Invalid TelephoneNumberRange start {}", entry.start.value()));
824 }
825
826 list.decode(entry.count);
827 if(entry.count < 2) {
828 throw Decoding_Error(fmt("Invalid TelephoneNumberRange count {}", entry.count));
829 }
830
831 range_items.emplace_back(std::move(entry));
832 }
833 list.end_cons();
834
835 if(range_items.empty()) {
836 throw Decoding_Error("TelephoneNumberRange is empty");
837 }
838 } else if(type_tag == TelephoneNumber) {
839 m_type = TelephoneNumber;
840 ASN1_String one_string;
841 BER_Decoder(obj).decode(one_string);
842 if(!is_valid_telephone_number(one_string)) {
843 throw Decoding_Error(fmt("Invalid TelephoneNumber {}", one_string.value()));
844 }
845 m_data = std::move(one_string);
846 } else {
847 throw Decoding_Error(fmt("Unexpected TNEntry type code {}", type_tag));
848 };
849}
850
851std::vector<uint8_t> TNAuthList::encode_inner() const {
852 throw Not_Implemented("TNAuthList extension serialization is not supported");
853}
854
855void TNAuthList::decode_inner(const std::vector<uint8_t>& in) {
856 BER_Decoder(in).decode_list(m_tn_entries).verify_end();
857 if(m_tn_entries.empty()) {
858 throw Decoding_Error("TNAuthorizationList is empty");
859 }
860}
861
864 return std::get<ASN1_String>(m_data).value();
865}
866
871
872const std::string& TNAuthList::Entry::telephone_number() const {
874 return std::get<ASN1_String>(m_data).value();
875}
876
877std::vector<uint8_t> IPAddressBlocks::encode_inner() const {
878 std::vector<uint8_t> output;
879 DER_Encoder(output).start_sequence().encode_list(m_ip_addr_blocks).end_cons();
880 return output;
881}
882
883void IPAddressBlocks::decode_inner(const std::vector<uint8_t>& in) {
884 BER_Decoder(in).decode_list(m_ip_addr_blocks).verify_end();
885 sort_and_merge();
886}
887
889 into.start_sequence();
890
891 std::vector<uint8_t> afam = {get_byte<0>(m_afi), get_byte<1>(m_afi)};
892
893 if(m_safi.has_value()) {
894 afam.push_back(m_safi.value());
895 }
896
898
899 if(std::holds_alternative<IPAddressChoice<Version::IPv4>>(m_ip_addr_choice)) {
900 into.encode(std::get<IPAddressChoice<Version::IPv4>>(m_ip_addr_choice));
901 } else {
902 into.encode(std::get<IPAddressChoice<Version::IPv6>>(m_ip_addr_choice));
903 }
904 into.end_cons();
905}
906
908 const ASN1_Type next_tag = from.peek_next_object().type_tag();
909 if(next_tag != ASN1_Type::Sequence) {
910 throw Decoding_Error(fmt("Unexpected type for IPAddressFamily {}", static_cast<uint32_t>(next_tag)));
911 }
912
913 BER_Decoder seq_dec = from.start_sequence();
914
915 std::vector<uint8_t> addr_family;
916 seq_dec.decode(addr_family, ASN1_Type::OctetString);
917 const size_t addr_family_length = addr_family.size();
918
919 if(addr_family_length != 2 && addr_family_length != 3) {
920 throw Decoding_Error("(S)AFI can only contain 2 or 3 bytes");
921 }
922
923 m_afi = (addr_family[0] << 8) | addr_family[1];
924
925 if(addr_family_length == 3) {
926 m_safi = addr_family[2];
927 }
928
929 if(m_afi == 1) {
931 seq_dec.decode(addr_choice);
932 m_ip_addr_choice = addr_choice;
933 } else if(m_afi == 2) {
935 seq_dec.decode(addr_choice);
936 m_ip_addr_choice = addr_choice;
937 } else {
938 throw Decoding_Error("Only AFI IPv4 and IPv6 are supported.");
939 }
940
941 seq_dec.end_cons();
942}
943
944void IPAddressBlocks::sort_and_merge() {
945 // Sort IPAddressFamilies by afi/safi values
946 //
947 // see: https://www.rfc-editor.org/rfc/rfc3779.html#section-2.2.3.3
948 //
949 // v4 families are ordered before v6 families (i.e. they are sorted by afis, primarily),
950 // families with no safis are ordered before families with safis
951 //
952 // families with the same afi/safi combination are then merged
953
954 // std::map is ordered, so using a pair (afi, optional(safi)) here works - std::nullopt is sorted before any actual values
955 std::map<std::pair<uint16_t, std::optional<uint8_t>>, std::vector<IPAddressFamily>> afam_map;
956 for(const IPAddressFamily& block : m_ip_addr_blocks) {
957 auto key = std::make_pair(block.afi(), block.safi());
958 std::vector<IPAddressFamily>& fams = afam_map[key];
959 fams.push_back(block);
960 }
961
962 std::vector<IPAddressFamily> merged_blocks;
963 for(auto& it : afam_map) {
964 // fams consists of families with the same afi/safi combination
965 std::vector<IPAddressFamily>& fams = it.second;
966 // since at least 1 block has to belong to a afi/safi combination for it to appear in the map,
967 // fams cannot be empty
968 BOTAN_ASSERT_NOMSG(!fams.empty());
969
970 // fams[0] has to have the same choice type as the fams in the same bucket
971 if(std::holds_alternative<IPAddressChoice<Version::IPv4>>(fams[0].addr_choice())) {
972 merged_blocks.push_back(merge<Version::IPv4>(fams));
973 } else {
974 merged_blocks.push_back(merge<Version::IPv6>(fams));
975 }
976 }
977 m_ip_addr_blocks = merged_blocks;
978}
979
980template <IPAddressBlocks::Version V>
981IPAddressBlocks::IPAddressFamily IPAddressBlocks::merge(std::vector<IPAddressFamily>& blocks) {
982 // Merge IPAddressFamilies that have the same afi/safi combination
983 //
984 // see: https://www.rfc-editor.org/rfc/rfc3779.html#section-2.2.3.3
985
986 BOTAN_ASSERT(!blocks.empty(), "Cannot merge an empty set of IP address blocks into a single family");
987
988 // nothing to merge
989 if(blocks.size() == 1) {
990 return blocks[0];
991 }
992
993 bool all_inherit = true;
994 bool none_inherit = true;
995 for(IPAddressFamily& block : blocks) {
996 IPAddressChoice<V> choice = std::get<IPAddressChoice<V>>(block.addr_choice());
997 all_inherit = !choice.ranges().has_value() && all_inherit; // all the blocks have the 'inherit' value
998 none_inherit = choice.ranges().has_value() && none_inherit;
999 }
1000
1001 // they are all 'inherit', short-circuit using default constructor for nullopt
1002 if(all_inherit) {
1003 return IPAddressFamily(IPAddressChoice<V>(), blocks[0].safi());
1004 }
1005
1006 // some are inherit, and some have values - no sensible way to merge them
1007 if(!all_inherit && !none_inherit) {
1008 throw Decoding_Error("Invalid IPAddressBlocks: Only one of 'inherit' or 'do not inherit' is allowed per family");
1009 }
1010
1011 std::vector<IPAddressOrRange<V>> merged_ranges;
1012 for(IPAddressFamily& block : blocks) {
1013 IPAddressChoice<V> choice = std::get<IPAddressChoice<V>>(block.addr_choice());
1014 std::vector<IPAddressOrRange<V>> ranges = choice.ranges().value();
1015 for(IPAddressOrRange<V>& r : ranges) {
1016 merged_ranges.push_back(r);
1017 }
1018 }
1019
1020 // we have extracted all the ranges, and now rely on the constructor of IPAddressChoice to merge them
1021 IPAddressChoice<V> choice(merged_ranges);
1022 IPAddressFamily fam(choice, blocks[0].safi());
1023 return fam;
1024}
1025
1026namespace {
1027
1028constexpr auto IPv4 = IPAddressBlocks::Version::IPv4;
1029constexpr auto IPv6 = IPAddressBlocks::Version::IPv6;
1030
1031template <IPAddressBlocks::Version V>
1032using IPRangeVec = std::vector<IPAddressBlocks::IPAddressOrRange<V>>;
1033
1034// (S)AFI -> (needs_check, ptr to IPRangeVec)
1035// the pointer can be null, in which case the boolean will be false, as such the pointer's value will never be looked at
1036template <IPAddressBlocks::Version V>
1037using IPValidationMap = std::map<uint32_t, std::pair<bool, const IPRangeVec<V>*>>;
1038
1039template <typename T>
1040std::optional<std::vector<T>> sort_and_merge_ranges(std::optional<std::span<const T>> ranges) {
1041 // This method iteratively both sorts and combines IPAddressOrRange or ASIdOrRange objects.
1042 // cf. https://www.rfc-editor.org/rfc/rfc3779.html#section-2.2.3.6 and https://www.rfc-editor.org/rfc/rfc3779.html#section-3.2.3.4
1043 // This implementation uses only min-max ranges internally, so sorting by the prefix length is not necessary / impossible here.
1044 //
1045 // We first sort all range objects by their minimum value, then check if two adjacent elements can be combined into one
1046 // (either one ends and the other immediately starts, or they overlap), in which case the two are removed, and a new combined object is added.
1047 // This process is repeated until there are no further changes, because multiple adjacent elements may need to be combined one by one.
1048
1049 if(!ranges.has_value()) {
1050 return std::nullopt;
1051 }
1052
1053 std::vector<T> current(ranges.value().begin(), ranges.value().end());
1054
1055 if(current.empty()) {
1056 return current;
1057 }
1058 // sort by size of the min value
1059 std::sort(current.begin(), current.end(), [](T& a, T& b) { return a.min() < b.min(); });
1060 for(size_t i = 0; i < current.size() - 1;) {
1061 const T a = current[i];
1062 const T b = current[i + 1];
1063 // they either overlap or are adjacent
1064 if(b.min() <= a.max() || b.min() == (a.max() + 1)) {
1065 // erase old a and b
1066 current.erase(current.begin() + i, current.begin() + i + 2);
1067 current.insert(current.begin() + i, T(a.min(), std::max(a.max(), b.max())));
1068 } else {
1069 i++;
1070 }
1071 }
1072 return current;
1073}
1074
1075template <typename T>
1076bool validate_subject_in_issuer(std::span<const T> subject, std::span<const T> issuer) {
1077 // ensures that the subject ranges are enclosed by the issuer ranges
1078 // both vectors are already sorted, so we can do this in O(n+m)
1079
1080 // the issuer has 0 ranges to validate against, so this can only work if the subject also has none
1081 if(issuer.empty()) {
1082 return subject.empty();
1083 }
1084 for(auto subj = subject.begin(), issu = issuer.begin(); subj != subject.end();) {
1085 // the issuer range is smaller than the subject range, step to the next issuer range to check next round
1086 if(subj->min() > issu->max()) {
1087 issu++;
1088 // we have run out of issuer ranges, but still have subject ranges left to validate
1089 if(issu == issuer.end() && subj != subject.end()) {
1090 return false;
1091 }
1092 } else {
1093 // the subject is outside of the closest issuer range on the left (min) side
1094 if(subj->min() < issu->min()) {
1095 return false;
1096 }
1097 // the subject is outside of the closest issuer range on the right (max) side
1098 if(subj->max() > issu->max()) {
1099 return false;
1100 }
1101 // this range is contained within the issuer, advance to the next subject range
1102 subj++;
1103 }
1104 }
1105 return true;
1106}
1107
1108template <IPAddressBlocks::Version V>
1109void populate_validation_map(uint32_t afam,
1111 IPValidationMap<V>& map) {
1112 const std::optional<IPRangeVec<V>>& ranges = std::get<IPAddressBlocks::IPAddressChoice<V>>(choice).ranges();
1113 bool has_value = ranges.has_value();
1114 const IPRangeVec<V>* value = has_value ? &ranges.value() : nullptr;
1115 map.emplace(afam, std::make_pair(has_value, std::move(value)));
1116}
1117
1118std::pair<IPValidationMap<IPv4>, IPValidationMap<IPv6>> create_validation_map(
1119 const std::vector<IPAddressBlocks::IPAddressFamily>& addr_blocks) {
1120 IPValidationMap<IPv4> v4_map;
1121 IPValidationMap<IPv6> v6_map;
1122
1123 for(const IPAddressBlocks::IPAddressFamily& block : addr_blocks) {
1124 uint32_t afam = block.afi();
1125 if(block.safi().has_value()) {
1126 afam = static_cast<uint32_t>(afam << 8) | block.safi().value();
1127 }
1128
1129 const IPAddressBlocks::IPAddressFamily::AddrChoice& a_choice = block.addr_choice();
1130 if(std::holds_alternative<IPAddressBlocks::IPAddressChoice<IPv4>>(a_choice)) {
1131 populate_validation_map(afam, a_choice, v4_map);
1132 } else {
1133 populate_validation_map(afam, a_choice, v6_map);
1134 }
1135 }
1136
1137 return std::make_pair(v4_map, v6_map);
1138}
1139
1140} // namespace
1141
1142template <IPAddressBlocks::Version V>
1144 std::optional<std::span<const IPAddressBlocks::IPAddressOrRange<V>>> ranges) {
1145 // NOLINTNEXTLINE(*-prefer-member-initializer)
1146 m_ip_addr_ranges = sort_and_merge_ranges<IPAddressOrRange<V>>(ranges);
1147}
1148
1149template <IPAddressBlocks::Version V>
1151 if(m_ip_addr_ranges.has_value()) {
1152 into.start_sequence().encode_list(m_ip_addr_ranges.value()).end_cons();
1153 } else {
1154 into.encode_null();
1155 }
1156}
1157
1158template <IPAddressBlocks::Version V>
1160 const ASN1_Type next_tag = from.peek_next_object().type_tag();
1161
1162 if(next_tag == ASN1_Type::Null) {
1163 from.decode_null();
1164 m_ip_addr_ranges = std::nullopt;
1165 } else if(next_tag == ASN1_Type::Sequence) {
1166 std::vector<IPAddressOrRange<V>> ip_ranges;
1167 from.decode_list(ip_ranges);
1168 m_ip_addr_ranges = sort_and_merge_ranges<IPAddressOrRange<V>>(ip_ranges);
1169 } else {
1170 throw Decoding_Error(fmt("Unexpected type for IPAddressChoice {}", static_cast<uint32_t>(next_tag)));
1171 }
1172}
1173
1174template <IPAddressBlocks::Version V>
1176 // Compress IPAddressOrRange as much as possible
1177 // cf. https://www.rfc-editor.org/rfc/rfc3779.html#section-2.2.3.7 - https://www.rfc-editor.org/rfc/rfc3779.html#section-2.2.3.9
1178 //
1179 // If possible encode as a prefix x.x.x.x/x, else encode as a range of min-max.
1180 // Single addresses are encoded as is (technically a /32 or /128 prefix).
1181 //
1182 // A range can be encoded as a prefix if the lowest n bits of the min address are 0
1183 // and the highest n bits of the max address are 1, or in other words, contiguous sequences of 0s and 1s are omitted.
1184 // To make reconstruction possible, an 'unused' octet is included at the start, since in the case of e.g. /25 only
1185 // the highest bit of the last octet is actually meaningful.
1186 //
1187 // If encoding requires a range, the individual elements can still be compressed using the above method,
1188 // but the number of used bits varies between them.
1189
1190 const size_t version_octets = static_cast<size_t>(V);
1191
1192 std::array<uint8_t, version_octets> min = m_min.value();
1193 std::array<uint8_t, version_octets> max = m_max.value();
1194
1195 uint8_t zeros = 0;
1196 uint8_t ones = 0;
1197
1198 bool zeros_done = false;
1199 bool ones_done = false;
1200
1201 // count contiguous 0s/1s from the right of the min/max addresses
1202 for(size_t i = version_octets; i > 0; i--) {
1203 if(!zeros_done) {
1204 uint8_t local_zeros = static_cast<uint8_t>(std::countr_zero(min[i - 1]));
1205 zeros += local_zeros;
1206 zeros_done = (local_zeros != 8);
1207 }
1208
1209 if(!ones_done) {
1210 uint8_t local_ones = static_cast<uint8_t>(std::countr_one(max[i - 1]));
1211 ones += local_ones;
1212 ones_done = (local_ones != 8);
1213 }
1214
1215 if(zeros_done && ones_done) {
1216 break;
1217 }
1218 }
1219
1220 // the part we want to compress
1221 const uint8_t host = std::min(zeros, ones);
1222
1223 // these we can outright drop
1224 const uint8_t discarded_octets = host / 8;
1225 // in a partially used octet
1226 const uint8_t unused_bits = host % 8;
1227
1228 bool octets_match = true;
1229 bool used_bits_match = true;
1230
1231 // we have octets to check
1232 if(discarded_octets < version_octets) {
1233 // check all but the last octet
1234 for(size_t i = 0; i < static_cast<uint8_t>(version_octets - discarded_octets - 1); i++) {
1235 if(min[i] != max[i]) {
1236 octets_match = false;
1237 break;
1238 }
1239 }
1240 // check the last significant octet if we have matched so far
1241 if(octets_match) {
1242 const uint8_t shifted_min = (min[version_octets - 1 - discarded_octets] >> unused_bits);
1243 const uint8_t shifted_max = (max[version_octets - 1 - discarded_octets] >> unused_bits);
1244 used_bits_match = (shifted_min == shifted_max);
1245 }
1246 }
1247
1248 // both the full octets and the partially used one match
1249 if(octets_match && used_bits_match) {
1250 // at this point the range can be encoded as a prefix
1251 std::vector<uint8_t> prefix;
1252
1253 prefix.push_back(unused_bits);
1254 for(size_t i = 0; i < static_cast<uint8_t>(version_octets - discarded_octets); i++) {
1255 prefix.push_back(min[i]);
1256 }
1257
1259 } else {
1260 const uint8_t discarded_octets_min = zeros / 8;
1261 const uint8_t unused_bits_min = zeros % 8;
1262
1263 const uint8_t discarded_octets_max = ones / 8;
1264 const uint8_t unused_bits_max = ones % 8;
1265
1266 // compress the max address by setting unused bits to 0, for the min address these are already 0
1267 if(unused_bits_max != 0) {
1268 BOTAN_ASSERT_NOMSG(discarded_octets_max < version_octets);
1269 max[version_octets - 1 - discarded_octets_max] >>= unused_bits_max;
1270 max[version_octets - 1 - discarded_octets_max] <<= unused_bits_max;
1271 }
1272
1273 std::vector<uint8_t> compressed_min;
1274 std::vector<uint8_t> compressed_max;
1275
1276 // construct the address as a byte sequence of the unused bits followed by the compressed address
1277 compressed_min.push_back(unused_bits_min);
1278 for(size_t i = 0; i < static_cast<uint8_t>(version_octets - discarded_octets_min); i++) {
1279 compressed_min.push_back(min[i]);
1280 }
1281
1282 compressed_max.push_back(unused_bits_max);
1283 for(size_t i = 0; i < static_cast<uint8_t>(version_octets - discarded_octets_max); i++) {
1284 compressed_max.push_back(max[i]);
1285 }
1286
1287 into.start_sequence()
1290 .end_cons();
1291 }
1292}
1293
1294template <IPAddressBlocks::Version V>
1296 const ASN1_Type next_tag = from.peek_next_object().type_tag();
1297
1298 // this can either be a prefix or a single address
1299 if(next_tag == ASN1_Type::BitString) {
1300 // construct a min and a max address from the prefix
1301
1302 std::vector<uint8_t> prefix_min;
1304
1305 // copy because we modify the address in `decode_single_address`, but we need it twice for min and max
1306 std::vector<uint8_t> prefix_max(prefix_min);
1307
1308 // min address gets filled with 0's
1309 m_min = decode_single_address(std::move(prefix_min), true);
1310 // max address with 1's
1311 m_max = decode_single_address(std::move(prefix_max), false);
1312 } else if(next_tag == ASN1_Type::Sequence) {
1313 // this is a range
1314
1315 std::vector<uint8_t> addr_min;
1316 std::vector<uint8_t> addr_max;
1317
1318 from.start_sequence()
1321 .end_cons();
1322
1323 m_min = decode_single_address(std::move(addr_min), true);
1324 m_max = decode_single_address(std::move(addr_max), false);
1325
1326 if(m_min > m_max) {
1327 throw Decoding_Error("IP address ranges must be sorted.");
1328 }
1329 } else {
1330 throw Decoding_Error(fmt("Unexpected type for IPAddressOrRange {}", static_cast<uint32_t>(next_tag)));
1331 }
1332}
1333
1334template <IPAddressBlocks::Version V>
1335IPAddressBlocks::IPAddress<V> IPAddressBlocks::IPAddressOrRange<V>::decode_single_address(std::vector<uint8_t> decoded,
1336 bool min) {
1337 const size_t version_octets = static_cast<size_t>(V);
1338
1339 // decode a single address according to https://datatracker.ietf.org/doc/html/rfc3779#section-2.1.1 and following
1340
1341 // we have to account for the octet at the beginning that specifies how many bits are unused in the last octet
1342 if(decoded.empty() || decoded.size() > version_octets + 1) {
1343 throw Decoding_Error(fmt("IP address range entries must have a length between 1 and {} bytes.", version_octets));
1344 }
1345
1346 const uint8_t unused = decoded.front();
1347 const uint8_t discarded_octets = version_octets - (static_cast<uint8_t>(decoded.size()) - 1);
1348
1349 decoded.erase(decoded.begin());
1350
1351 if(decoded.empty() && unused != 0) {
1352 throw Decoding_Error("IP address range entry specified unused bits, but did not provide any octets.");
1353 }
1354
1355 // if they were 8, the entire octet should have been discarded
1356 if(unused > 7) {
1357 throw Decoding_Error("IP address range entry specified invalid number of unused bits.");
1358 }
1359
1360 // pad to version length with 0's for min addresses, 255's (0xff) for max addresses
1361 uint8_t fill_discarded = min ? 0 : 0xff;
1362 for(size_t i = 0; i < discarded_octets; i++) {
1363 decoded.push_back(fill_discarded);
1364 }
1365
1366 // for min addresses they should already be 0, but we set them to zero regardless
1367 // for max addresses this turns the unused bits to 1
1368 for(size_t i = 0; i < unused; i++) {
1369 if(min) {
1370 decoded[version_octets - 1 - discarded_octets] &= ~(1 << i);
1371 } else {
1372 decoded[version_octets - 1 - discarded_octets] |= (1 << i);
1373 }
1374 }
1375
1376 return IPAddressBlocks::IPAddress<V>(decoded);
1377}
1378
1379template <IPAddressBlocks::Version V>
1380IPAddressBlocks::IPAddress<V>::IPAddress(std::span<const uint8_t> v) {
1381 if(v.size() != Length) {
1382 throw Decoding_Error("number of bytes does not match IP version used");
1383 }
1384
1385 for(size_t i = 0; i < Length; i++) {
1386 m_value[i] = v[i];
1387 }
1388}
1389
1391 const X509_Certificate& /* unused */,
1392 const std::vector<X509_Certificate>& cert_path,
1393 std::vector<std::set<Certificate_Status_Code>>& cert_status,
1394 size_t pos) {
1395 // maps in the form of (s)afi -> (needs_checking, ranges)
1396 auto [v4_needs_check, v6_needs_check] = create_validation_map(m_ip_addr_blocks);
1397
1398 if(pos == cert_path.size() - 1) {
1399 // checks if any range / family has 'inherit' as a value somewhere, not allowed for the root cert
1400 auto validate_root_cert_ext = [&](const auto& map) {
1401 // check if any range has a value of 'false', indicating 'inherit'
1402 return std::any_of(map.begin(), map.end(), [&](const auto& it) {
1403 const auto& [_1, validation_info] = it;
1404 const auto& [needs_checking, _2] = validation_info;
1405 return !needs_checking;
1406 });
1407 };
1408 if(validate_root_cert_ext(v4_needs_check) || validate_root_cert_ext(v6_needs_check)) {
1409 cert_status.at(pos).insert(Certificate_Status_Code::IPADDR_BLOCKS_ERROR);
1410 }
1411 return;
1412 }
1413
1414 // traverse the chain until we find a cert with concrete values for the extension (so not 'inherit')
1415 for(auto cert_path_it = cert_path.begin() + pos + 1; cert_path_it != cert_path.end(); cert_path_it++) {
1416 const IPAddressBlocks* const parent_ip = cert_path_it->v3_extensions().get_extension_object_as<IPAddressBlocks>();
1417 // extension not present for parent
1418 if(parent_ip == nullptr) {
1419 cert_status.at(pos).insert(Certificate_Status_Code::IPADDR_BLOCKS_ERROR);
1420 return;
1421 }
1422 auto [issuer_v4, issuer_v6] = create_validation_map(parent_ip->addr_blocks());
1423
1424 auto validate_against_issuer = [&](auto& subject_map, const auto& issuer_map) {
1425 for(auto map_it = subject_map.begin(); map_it != subject_map.end(); map_it++) {
1426 auto& [afam, validation_info] = *map_it;
1427
1428 // the issuer does not have this combination of afi/safi
1429 if(issuer_map.count(afam) == 0) {
1430 cert_status.at(pos).insert(Certificate_Status_Code::IPADDR_BLOCKS_ERROR);
1431 return false;
1432 }
1433
1434 auto& [needs_check, subject_value] = validation_info;
1435 const auto& [issuer_has_value, issuer_value] = issuer_map.at(afam);
1436 BOTAN_ASSERT_NOMSG(!needs_check || subject_value != nullptr);
1437 BOTAN_ASSERT_NOMSG(!issuer_has_value || issuer_value != nullptr);
1438
1439 // we still need to check this range and the issuer has an actual value for it (so not 'inherit')
1440 if(needs_check && issuer_has_value) {
1441 if(!validate_subject_in_issuer(std::span(*subject_value), std::span(*issuer_value))) {
1442 cert_status.at(pos).insert(Certificate_Status_Code::IPADDR_BLOCKS_ERROR);
1443 return false;
1444 }
1445 needs_check = false;
1446 }
1447 }
1448 return true;
1449 };
1450
1451 if(!validate_against_issuer(v4_needs_check, issuer_v4) || !validate_against_issuer(v6_needs_check, issuer_v6)) {
1452 return;
1453 }
1454
1455 auto validate_no_checks_left = [&](const auto& map) {
1456 // check if all ranges have been checked, either by comparing their ranges if they have any,
1457 // or if they are inherit, their parent(s) will be validated later
1458 return std::all_of(map.begin(), map.end(), [&](const auto& it) {
1459 const auto& [_1, validation_info] = it;
1460 const auto& [needs_checking, _2] = validation_info;
1461 return !needs_checking;
1462 });
1463 };
1464
1465 if(validate_no_checks_left(v4_needs_check) && validate_no_checks_left(v6_needs_check)) {
1466 // we've validated what we need to and can stop traversing the cert chain
1467 return;
1468 }
1469 }
1470}
1471
1478
1479std::vector<uint8_t> ASBlocks::encode_inner() const {
1480 std::vector<uint8_t> output;
1481 DER_Encoder(output).encode(m_as_identifiers);
1482 return output;
1483}
1484
1485void ASBlocks::decode_inner(const std::vector<uint8_t>& in) {
1486 BER_Decoder(in).decode(m_as_identifiers).verify_end();
1487}
1488
1489ASBlocks::ASIdentifierChoice ASBlocks::add_new(const std::optional<ASIdentifierChoice>& old, asnum_t min, asnum_t max) {
1490 std::vector<ASIdOrRange> range;
1491 if(!old.has_value() || !old.value().ranges().has_value()) {
1492 range = {ASIdOrRange(min, max)};
1493 } else {
1494 range = old.value().ranges().value();
1495 range.push_back(ASIdOrRange(min, max));
1496 }
1497 return ASIdentifierChoice(range);
1498}
1499
1501 into.start_sequence();
1502
1503 if(!m_asnum.has_value() && !m_rdi.has_value()) {
1504 throw Encoding_Error("One of asnum, rdi must be present");
1505 }
1506
1507 if(m_asnum.has_value()) {
1508 into.start_explicit(0);
1509 into.encode(m_asnum.value());
1510 into.end_explicit();
1511 }
1512
1513 if(m_rdi.has_value()) {
1514 into.start_explicit(1);
1515 into.encode(m_rdi.value());
1516 into.end_explicit();
1517 }
1518
1519 into.end_cons();
1520}
1521
1523 const ASN1_Type next_tag = from.peek_next_object().type_tag();
1524 if(next_tag != ASN1_Type::Sequence) {
1525 throw Decoding_Error(fmt("Unexpected type for ASIdentifiers {}", static_cast<uint32_t>(next_tag)));
1526 }
1527
1528 BER_Decoder seq_dec = from.start_sequence();
1529
1530 const BER_Object elem_obj = seq_dec.get_next_object();
1531 const uint32_t elem_type_tag = static_cast<uint32_t>(elem_obj.type_tag());
1532
1533 // asnum, potentially followed by an rdi
1534 if(elem_type_tag == 0) {
1535 BER_Decoder as_obj_ber = BER_Decoder(elem_obj);
1537 as_obj_ber.decode(asnum);
1538 m_asnum = asnum;
1539
1540 const BER_Object rdi_obj = seq_dec.get_next_object();
1541 const ASN1_Type rdi_type_tag = rdi_obj.type_tag();
1542 if(static_cast<uint32_t>(rdi_type_tag) == 1) {
1543 BER_Decoder rdi_obj_ber = BER_Decoder(rdi_obj);
1545 rdi_obj_ber.decode(rdi);
1546 m_rdi = rdi;
1547 } else if(rdi_type_tag != ASN1_Type::NoObject) {
1548 throw Decoding_Error(fmt("Unexpected type for ASIdentifiers rdi: {}", static_cast<uint32_t>(rdi_type_tag)));
1549 }
1550 }
1551
1552 // just an rdi
1553 if(elem_type_tag == 1) {
1554 BER_Decoder rdi_obj_ber = BER_Decoder(elem_obj);
1556 rdi_obj_ber.decode(rdi);
1557 m_rdi = rdi;
1558 const BER_Object end = seq_dec.get_next_object();
1559 const ASN1_Type end_type_tag = end.type_tag();
1560 if(end_type_tag != ASN1_Type::NoObject) {
1561 throw Decoding_Error(
1562 fmt("Unexpected element with type {} in ASIdentifiers", static_cast<uint32_t>(end_type_tag)));
1563 }
1564 }
1565
1566 seq_dec.end_cons();
1567}
1568
1570 if(m_as_ranges.has_value()) {
1571 into.start_sequence().encode_list(m_as_ranges.value()).end_cons();
1572 } else {
1573 into.encode_null();
1574 }
1575}
1576
1577ASBlocks::ASIdentifierChoice::ASIdentifierChoice(const std::optional<std::vector<ASIdOrRange>>& ranges) {
1578 m_as_ranges = sort_and_merge_ranges<ASIdOrRange>(ranges);
1579}
1580
1582 const ASN1_Type next_tag = from.peek_next_object().type_tag();
1583
1584 if(next_tag == ASN1_Type::Null) {
1585 m_as_ranges = std::nullopt;
1586 } else if(next_tag == ASN1_Type::Sequence) {
1587 std::vector<ASIdOrRange> as_ranges;
1588 from.decode_list(as_ranges);
1589
1590 m_as_ranges = sort_and_merge_ranges<ASIdOrRange>(as_ranges);
1591 } else {
1592 throw Decoding_Error(fmt("Unexpected type for ASIdentifierChoice {}", static_cast<uint32_t>(next_tag)));
1593 }
1594}
1595
1597 if(m_min == m_max) {
1598 into.encode(static_cast<size_t>(m_min));
1599 } else {
1600 if(m_min >= m_max) {
1601 throw Encoding_Error("AS range numbers must be sorted");
1602 }
1603 into.start_sequence().encode(static_cast<size_t>(m_min)).encode(static_cast<size_t>(m_max)).end_cons();
1604 }
1605}
1606
1608 const ASN1_Type next_tag = from.peek_next_object().type_tag();
1609
1610 size_t min = 0;
1611 size_t max = 0;
1612
1613 if(next_tag == ASN1_Type::Integer) {
1614 from.decode(min);
1616 m_max = m_min;
1617 } else if(next_tag == ASN1_Type::Sequence) {
1621 } else {
1622 throw Decoding_Error(fmt("Unexpected type for ASIdOrRange {}", static_cast<uint32_t>(next_tag)));
1623 }
1624}
1625
1626void ASBlocks::validate(const X509_Certificate& /* unused */,
1627 const X509_Certificate& /* unused */,
1628 const std::vector<X509_Certificate>& cert_path,
1629 std::vector<std::set<Certificate_Status_Code>>& cert_status,
1630 size_t pos) {
1631 // the extension may not contain asnums or rdis, but one of them is always present
1632 const bool asnum_present = m_as_identifiers.asnum().has_value();
1633 const bool rdi_present = m_as_identifiers.rdi().has_value();
1634 bool asnum_needs_check = asnum_present ? m_as_identifiers.asnum().value().ranges().has_value() : false;
1635 bool rdi_needs_check = rdi_present ? m_as_identifiers.rdi().value().ranges().has_value() : false;
1636 BOTAN_ASSERT_NOMSG(asnum_present || rdi_present);
1637
1638 // we are at the (trusted) root cert, there is no parent to verify against
1639 if(pos == cert_path.size() - 1) {
1640 // asnum / rdi is present, but has 'inherit' value, but there is nothing to inherit from
1641 if((asnum_present && !asnum_needs_check) || (rdi_present && !rdi_needs_check)) {
1642 cert_status.at(pos).insert(Certificate_Status_Code::AS_BLOCKS_ERROR);
1643 }
1644 return;
1645 }
1646
1647 // traverse the chain until we find a cert with concrete values for the extension (so not 'inherit')
1648 for(auto it = cert_path.begin() + pos + 1; it != cert_path.end(); it++) {
1649 const ASBlocks* const parent_as = it->v3_extensions().get_extension_object_as<ASBlocks>();
1650 // no extension at all or no asnums or no rdis (if needed)
1651 if(parent_as == nullptr || (asnum_present && !parent_as->as_identifiers().asnum().has_value()) ||
1652 (rdi_present && !parent_as->as_identifiers().rdi().has_value())) {
1653 cert_status.at(pos).insert(Certificate_Status_Code::AS_BLOCKS_ERROR);
1654 return;
1655 }
1656 const auto as_identifiers = parent_as->as_identifiers();
1657
1658 // only something to validate if the subject does not have 'inherit' as a value
1659 if(asnum_needs_check && as_identifiers.asnum().value().ranges().has_value()) {
1660 const std::vector<ASBlocks::ASIdOrRange>& subject_asnums = m_as_identifiers.asnum()->ranges().value();
1661 const std::vector<ASBlocks::ASIdOrRange>& issuer_asnums = as_identifiers.asnum()->ranges().value();
1662
1663 if(!validate_subject_in_issuer<ASBlocks::ASIdOrRange>(subject_asnums, issuer_asnums)) {
1664 cert_status.at(pos).insert(Certificate_Status_Code::AS_BLOCKS_ERROR);
1665 return;
1666 }
1667 // successfully validated the asnums, but we may need to step further for rdis
1668 asnum_needs_check = false;
1669 }
1670
1671 if(rdi_needs_check && as_identifiers.rdi().value().ranges().has_value()) {
1672 const std::vector<ASBlocks::ASIdOrRange>& subject_rdis = m_as_identifiers.rdi()->ranges().value();
1673 const std::vector<ASBlocks::ASIdOrRange>& issuer_rdis = as_identifiers.rdi()->ranges().value();
1674
1675 if(!validate_subject_in_issuer<ASBlocks::ASIdOrRange>(subject_rdis, issuer_rdis)) {
1676 cert_status.at(pos).insert(Certificate_Status_Code::AS_BLOCKS_ERROR);
1677 return;
1678 }
1679 // successfully validated the rdis, but we may need to step further for asnums
1680 rdi_needs_check = false;
1681 }
1682
1683 if(!asnum_needs_check && !rdi_needs_check) {
1684 // we've validated what we need to and can stop traversing the cert chain
1685 return;
1686 }
1687 }
1688}
1689
1690void OCSP_NoCheck::decode_inner(const std::vector<uint8_t>& buf) {
1691 BER_Decoder(buf).verify_end();
1692}
1693
1694std::vector<uint8_t> Unknown_Extension::encode_inner() const {
1695 return m_bytes;
1696}
1697
1698void Unknown_Extension::decode_inner(const std::vector<uint8_t>& bytes) {
1699 // Just treat as an opaque blob at this level
1700 m_bytes = bytes;
1701}
1702
1703} // namespace Cert_Extension
1704
1705} // namespace Botan
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75
#define BOTAN_DEBUG_ASSERT(expr)
Definition assert.h:129
#define BOTAN_STATE_CHECK(expr)
Definition assert.h:49
#define BOTAN_ASSERT_NONNULL(ptr)
Definition assert.h:114
#define BOTAN_ASSERT(expr, assertion_made)
Definition assert.h:62
const std::string & value() const
Definition asn1_obj.h:437
const BER_Object & peek_next_object()
Definition ber_dec.cpp:237
BER_Object get_next_object()
Definition ber_dec.cpp:248
BER_Decoder & decode(bool &out)
Definition ber_dec.h:188
bool more_items() const
Definition ber_dec.cpp:204
BER_Decoder & verify_end()
Definition ber_dec.cpp:214
BER_Decoder & end_cons()
Definition ber_dec.cpp:312
BER_Decoder & decode_list(std::vector< T > &out, ASN1_Type type_tag=ASN1_Type::Sequence, ASN1_Class class_tag=ASN1_Class::Universal)
Definition ber_dec.h:393
BER_Decoder start_sequence()
Definition ber_dec.h:125
BER_Decoder start_context_specific(uint32_t tag)
Definition ber_dec.h:129
BER_Decoder & decode_optional(T &out, ASN1_Type type_tag, ASN1_Class class_tag, const T &default_value=T())
Definition ber_dec.h:253
BER_Decoder & decode_null()
Definition ber_dec.cpp:375
BER_Decoder & decode_optional_string(std::vector< uint8_t, Alloc > &out, ASN1_Type real_type, uint32_t expected_tag, ASN1_Class class_tag=ASN1_Class::ContextSpecific)
Definition ber_dec.h:297
BER_Decoder & decode_optional_implicit(T &out, ASN1_Type type_tag, ASN1_Class class_tag, ASN1_Type real_type, ASN1_Class real_class, const T &default_value=T())
Definition ber_dec.h:368
ASN1_Type type_tag() const
Definition asn1_obj.h:142
void encode_into(DER_Encoder &to) const override
void decode_from(BER_Decoder &from) override
void encode_into(DER_Encoder &to) const override
void decode_from(BER_Decoder &from) override
const std::optional< std::vector< ASIdOrRange > > & ranges() const
Definition x509_ext.h:826
const std::optional< ASIdentifierChoice > & asnum() const
Definition x509_ext.h:845
const std::optional< ASIdentifierChoice > & rdi() const
Definition x509_ext.h:847
void encode_into(DER_Encoder &to) const override
void decode_from(BER_Decoder &from) override
const ASIdentifiers & as_identifiers() const
Definition x509_ext.h:907
void validate(const X509_Certificate &subject, const X509_Certificate &issuer, const std::vector< X509_Certificate > &cert_path, std::vector< std::set< Certificate_Status_Code > > &cert_status, size_t pos) override
BOTAN_FUTURE_EXPLICIT Basic_Constraints(bool is_ca=false, size_t path_length_constraint=0)
Definition x509_ext.cpp:293
std::optional< size_t > path_length_constraint() const
Definition x509_ext.h:53
std::unique_ptr< Certificate_Extension > copy() const override
Definition x509_ext.cpp:697
void validate(const X509_Certificate &subject, const X509_Certificate &issuer, const std::vector< X509_Certificate > &cert_path, std::vector< std::set< Certificate_Status_Code > > &cert_status, size_t pos) override
Definition x509_ext.cpp:619
void encode_into(DER_Encoder &to) const override
void encode_into(DER_Encoder &to) const override
Definition x509_ext.cpp:888
std::variant< IPAddressChoice< Version::IPv4 >, IPAddressChoice< Version::IPv6 > > AddrChoice
Definition x509_ext.h:688
void encode_into(DER_Encoder &to) const override
void validate(const X509_Certificate &subject, const X509_Certificate &issuer, const std::vector< X509_Certificate > &cert_path, std::vector< std::set< Certificate_Status_Code > > &cert_status, size_t pos) override
const std::vector< IPAddressFamily > & addr_blocks() const
Definition x509_ext.h:766
void validate(const X509_Certificate &subject, const X509_Certificate &issuer, const std::vector< X509_Certificate > &cert_path, std::vector< std::set< Certificate_Status_Code > > &cert_status, size_t pos) override
Definition x509_ext.cpp:536
const std::string & service_provider_code() const
Definition x509_ext.cpp:862
const std::string & telephone_number() const
Definition x509_ext.cpp:872
std::vector< TelephoneNumberRangeData > RangeContainer
Definition x509_ext.h:540
void decode_from(class BER_Decoder &from) override
Definition x509_ext.cpp:803
void encode_into(DER_Encoder &to) const override
Definition x509_ext.cpp:799
const RangeContainer & telephone_number_range() const
Definition x509_ext.cpp:867
virtual void validate(const X509_Certificate &subject, const X509_Certificate &issuer, const std::vector< X509_Certificate > &cert_path, std::vector< std::set< Certificate_Status_Code > > &cert_status, size_t pos)
Definition x509_ext.cpp:134
virtual std::vector< uint8_t > encode_inner() const =0
DER_Encoder & add_object(ASN1_Type type_tag, ASN1_Class class_tag, const uint8_t rep[], size_t length)
Definition der_enc.cpp:224
DER_Encoder & end_explicit()
Definition der_enc.cpp:202
DER_Encoder & encode_optional(const T &value, const T &default_value)
Definition der_enc.h:125
DER_Encoder & encode_list(const std::vector< T > &values)
Definition der_enc.h:141
DER_Encoder & start_explicit(uint16_t type_tag)
Definition der_enc.cpp:188
DER_Encoder & start_sequence()
Definition der_enc.h:65
DER_Encoder & start_cons(ASN1_Type type_tag, ASN1_Class class_tag)
Definition der_enc.cpp:165
DER_Encoder & encode_null()
Definition der_enc.cpp:245
DER_Encoder & end_cons()
Definition der_enc.cpp:173
DER_Encoder & encode(bool b)
Definition der_enc.cpp:252
const Certificate_Extension * get_extension_object(const OID &oid) const
Definition x509_ext.cpp:209
std::map< OID, std::pair< std::vector< uint8_t >, bool > > extensions_raw() const
Definition x509_ext.cpp:234
std::unique_ptr< Certificate_Extension > get(const OID &oid) const
Definition x509_ext.cpp:218
void decode_from(BER_Decoder &from) override
Definition x509_ext.cpp:265
bool remove(const OID &oid)
Definition x509_ext.cpp:168
std::vector< uint8_t > get_extension_bits(const OID &oid) const
Definition x509_ext.cpp:200
bool critical_extension_set(const OID &oid) const
Definition x509_ext.cpp:192
std::vector< std::pair< std::unique_ptr< Certificate_Extension >, bool > > extensions() const
Definition x509_ext.cpp:225
void encode_into(DER_Encoder &to) const override
Definition x509_ext.cpp:245
void replace(std::unique_ptr< Certificate_Extension > extn, bool critical=false)
Definition x509_ext.cpp:178
bool add_new(std::unique_ptr< Certificate_Extension > extn, bool critical=false)
Definition x509_ext.cpp:156
bool extension_set(const OID &oid) const
Definition x509_ext.cpp:188
void add(std::unique_ptr< Certificate_Extension > extn, bool critical=false)
Definition x509_ext.cpp:143
static std::unique_ptr< HashFunction > create_or_throw(std::string_view algo_spec, std::string_view provider="")
Definition hash.cpp:298
static OID from_string(std::string_view str)
Definition asn1_oid.cpp:86
bool is_CA_cert() const
Definition x509cert.cpp:423
bool is_critical(std::string_view ex_name) const
Definition x509cert.cpp:534
std::string to_string(const BER_Object &obj)
Definition asn1_obj.cpp:185
constexpr uint8_t get_byte(T input)
Definition loadstor.h:79
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53
constexpr RT checked_cast_to(AT i)
Definition int_utils.h:74
ASN1_Type
Definition asn1_obj.h:43
std::optional< uint32_t > is_sub_element_of(const OID &oid, std::initializer_list< uint32_t > prefix)
Definition x509_utils.h:16
BOTAN_FORCE_INLINE constexpr size_t ctz(T n)
Definition bit_ops.h:96
constexpr uint16_t make_uint16(uint8_t i0, uint8_t i1)
Definition loadstor.h:92