Botan 3.13.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/pk_keys.h>
18#include <botan/x509cert.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 <span>
26
27namespace Botan {
28
29namespace {
30
31constexpr size_t MaximumKeyIdentifierLength = 64;
32
33/*
34* Encode an AlternativeName as `GeneralNames` but with an outer IMPLICIT
35* context-specific tag rather than the universal SEQUENCE tag. Used for
36* fullName [0] / cRLIssuer [2] / similar.
37*/
38void emit_general_names_implicit(DER_Encoder& der, const AlternativeName& names, uint32_t tag) {
39 // RFC 5280 4.2.1.6: GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
40 if(!names.has_items()) {
41 throw Encoding_Error("Cannot encode empty GeneralNames");
42 }
43 if(std::ranges::any_of(names.directory_names(), [](const X509_DN& dn) { return dn.empty(); })) {
44 throw Encoding_Error("GeneralNames must not contain an empty directoryName");
45 }
46 der.encode_implicit(names, ASN1_Type(tag));
47}
48
49template <std::derived_from<Certificate_Extension> T>
50auto make_extension([[maybe_unused]] const OID& oid) {
51 BOTAN_DEBUG_ASSERT(oid == T::static_oid());
52 return std::make_unique<T>();
53}
54
55std::unique_ptr<Certificate_Extension> extension_from_oid(const OID& oid) {
56 if(auto iso_ext = is_sub_element_of(oid, {2, 5, 29})) {
57 // NOLINTNEXTLINE(*-switch-missing-default-case)
58 switch(*iso_ext) {
59 case 14:
60 return make_extension<Cert_Extension::Subject_Key_ID>(oid);
61 case 15:
62 return make_extension<Cert_Extension::Key_Usage>(oid);
63 case 17:
64 return make_extension<Cert_Extension::Subject_Alternative_Name>(oid);
65 case 18:
66 return make_extension<Cert_Extension::Issuer_Alternative_Name>(oid);
67 case 19:
68 return make_extension<Cert_Extension::Basic_Constraints>(oid);
69 case 20:
70 return make_extension<Cert_Extension::CRL_Number>(oid);
71 case 21:
72 return make_extension<Cert_Extension::CRL_ReasonCode>(oid);
73 case 28:
74 return make_extension<Cert_Extension::CRL_Issuing_Distribution_Point>(oid);
75 case 30:
76 return make_extension<Cert_Extension::Name_Constraints>(oid);
77 case 31:
78 return make_extension<Cert_Extension::CRL_Distribution_Points>(oid);
79 case 32:
80 return make_extension<Cert_Extension::Certificate_Policies>(oid);
81 case 35:
82 return make_extension<Cert_Extension::Authority_Key_ID>(oid);
83 case 37:
84 return make_extension<Cert_Extension::Extended_Key_Usage>(oid);
85 case 56:
86 return make_extension<Cert_Extension::NoRevocationAvailable>(oid);
87 }
88 }
89
90 if(auto pkix_ext = is_sub_element_of(oid, {1, 3, 6, 1, 5, 5, 7, 1})) {
91 // NOLINTNEXTLINE(*-switch-missing-default-case)
92 switch(*pkix_ext) {
93 case 1:
94 return make_extension<Cert_Extension::Authority_Information_Access>(oid);
95 case 7:
96 return make_extension<Cert_Extension::IPAddressBlocks>(oid);
97 case 8:
98 return make_extension<Cert_Extension::ASBlocks>(oid);
99 case 26:
100 return make_extension<Cert_Extension::TNAuthList>(oid);
101 }
102 }
103
105 return make_extension<Cert_Extension::OCSP_NoCheck>(oid);
106 }
107
108 return nullptr; // unknown
109}
110
111bool is_valid_telephone_number(const ASN1_String& tn) {
112 //TelephoneNumber ::= IA5String (SIZE (1..15)) (FROM ("0123456789#*"))
113 const std::string valid_tn_chars("0123456789#*");
114
115 if(tn.empty() || (tn.size() > 15)) {
116 return false;
117 }
118
119 if(tn.value().find_first_not_of(valid_tn_chars) != std::string::npos) {
120 return false;
121 }
122
123 return true;
124}
125
126} // namespace
127
128std::vector<OID> Extensions::critical_extensions() const {
129 std::vector<OID> crit;
130
131 for(const auto& oid : m_extension_oids) {
132 auto ext_info = m_extension_info.find(oid);
133 BOTAN_ASSERT_NOMSG(ext_info != m_extension_info.end());
134 if(ext_info->second.is_critical()) {
135 crit.push_back(oid);
136 }
137 }
138
139 return crit;
140}
141
142/*
143* Create a Certificate_Extension object of some kind to handle
144*/
145std::unique_ptr<Certificate_Extension> Extensions::create_extn_obj(const OID& oid,
146 bool critical,
147 const std::vector<uint8_t>& body,
148 std::optional<Extension_Context> context) {
149 auto extn = extension_from_oid(oid);
150
151 if(!extn) {
152 // some other unknown extension type
153 extn = std::make_unique<Cert_Extension::Unknown_Extension>(oid, critical);
154 } else {
155 if(context.has_value() && !extn->is_appropriate_context(*context)) {
156 throw Decoding_Error(fmt("Extension {} is not allowed in this context", extn->oid_name()));
157 }
158
159 try {
160 extn->decode_inner(body);
161 return extn;
162 } catch(const Exception&) {
163 // OID was recognized but contents failed to decode
164 extn = std::make_unique<Cert_Extension::Unknown_Extension>(oid, critical, /*failed_to_decode=*/true);
165 }
166 }
167
168 // This is always Unknown_Extension:
169 extn->decode_inner(body);
170 return extn;
171}
172
173const Certificate_Extension& Extensions::Extensions_Info::obj() const {
174 BOTAN_ASSERT_NONNULL(m_obj.get());
175 return *m_obj;
176}
177
178/*
179* Validate the extension (the default implementation is a NOP)
180*/
182 const std::optional<X509_Certificate>& /*unused*/,
183 const std::vector<X509_Certificate>& /*unused*/,
184 std::vector<std::set<Certificate_Status_Code>>& /*unused*/,
185 size_t /*unused*/) const {}
186
187/*
188* Add a new cert
189*/
190void Extensions::add(std::unique_ptr<Certificate_Extension> extn, bool critical) {
191 // sanity check: we don't want to have the same extension more than once
192 if(m_extension_info.contains(extn->oid_of())) {
193 const std::string name = extn->oid_name();
194 throw Invalid_Argument("Extension " + name + " already present in Extensions::add");
195 }
196
197 const OID oid = extn->oid_of();
198 Extensions_Info info(critical, std::move(extn));
199 m_extension_oids.push_back(oid);
200 m_extension_info.emplace(oid, info);
201}
202
203bool Extensions::add_new(std::unique_ptr<Certificate_Extension> extn, bool critical) {
204 if(m_extension_info.contains(extn->oid_of())) {
205 return false; // already exists
206 }
207
208 const OID oid = extn->oid_of();
209 Extensions_Info info(critical, std::move(extn));
210 m_extension_oids.push_back(oid);
211 m_extension_info.emplace(oid, info);
212 return true;
213}
214
215bool Extensions::remove(const OID& oid) {
216 const bool erased = m_extension_info.erase(oid) > 0;
217
218 if(erased) {
219 m_extension_oids.erase(std::find(m_extension_oids.begin(), m_extension_oids.end(), oid));
220 }
221
222 return erased;
223}
224
225void Extensions::replace(std::unique_ptr<Certificate_Extension> extn, bool critical) {
226 // Remove it if it existed
227 remove(extn->oid_of());
228
229 const OID oid = extn->oid_of();
230 Extensions_Info info(critical, std::move(extn));
231 m_extension_oids.push_back(oid);
232 m_extension_info.emplace(oid, info);
233}
234
235bool Extensions::extension_set(const OID& oid) const {
236 return m_extension_info.contains(oid);
237}
238
240 auto i = m_extension_info.find(oid);
241 if(i != m_extension_info.end()) {
242 return i->second.is_critical();
243 }
244 return false;
245}
246
247std::vector<uint8_t> Extensions::get_extension_bits(const OID& oid) const {
248 auto i = m_extension_info.find(oid);
249 if(i == m_extension_info.end()) {
250 throw Invalid_Argument("Extensions::get_extension_bits no such extension set");
251 }
252
253 return i->second.bits();
254}
255
257 auto extn = m_extension_info.find(oid);
258 if(extn == m_extension_info.end()) {
259 return nullptr;
260 }
261
262 return &extn->second.obj();
263}
264
265std::unique_ptr<Certificate_Extension> Extensions::get(const OID& oid) const {
266 if(const Certificate_Extension* ext = this->get_extension_object(oid)) {
267 return ext->copy();
268 }
269 return nullptr;
270}
271
272std::vector<std::pair<std::unique_ptr<Certificate_Extension>, bool>> Extensions::extensions() const {
273 std::vector<std::pair<std::unique_ptr<Certificate_Extension>, bool>> exts;
274 exts.reserve(m_extension_info.size());
275 for(auto&& ext : m_extension_info) {
276 exts.push_back(std::make_pair(ext.second.obj().copy(), ext.second.is_critical()));
277 }
278 return exts;
279}
280
282 const std::optional<X509_Certificate>& issuer,
283 const std::vector<X509_Certificate>& cert_path,
284 std::vector<std::set<Certificate_Status_Code>>& cert_status,
285 size_t pos) const {
286 for(const auto& ext : m_extension_info) {
287 ext.second.obj().validate(subject, issuer, cert_path, cert_status, pos);
288 }
289}
290
291std::map<OID, std::pair<std::vector<uint8_t>, bool>> Extensions::extensions_raw() const {
292 std::map<OID, std::pair<std::vector<uint8_t>, bool>> out;
293 for(auto&& ext : m_extension_info) {
294 out.emplace(ext.first, std::make_pair(ext.second.bits(), ext.second.is_critical()));
295 }
296 return out;
297}
298
299/*
300* Encode an Extensions list
301*/
302void Extensions::encode_into(DER_Encoder& to_object) const {
303 for(const auto& [oid, extn] : m_extension_info) {
304 const bool should_encode = extn.obj().should_encode();
305
306 if(should_encode) {
307 const auto is_critical = extn.is_critical() ? std::optional<bool>{true} : std::nullopt;
308 const std::vector<uint8_t>& ext_value = extn.bits();
309
310 to_object.start_sequence()
311 .encode(oid)
312 .encode_optional(is_critical)
313 .encode(ext_value, ASN1_Type::OctetString)
314 .end_cons();
315 }
316 }
317}
318
319/*
320* Decode a list of Extensions
321*/
323 decode_from(from_source, std::nullopt);
324}
325
326void Extensions::decode_from(BER_Decoder& from_source, std::optional<Extension_Context> context) {
327 m_extension_oids.clear();
328 m_extension_info.clear();
329 m_has_unknown_critical_extension = false;
330
331 BER_Decoder sequence = from_source.start_sequence();
332
333 while(sequence.more_items()) {
334 OID oid;
335 bool critical = false;
336 std::vector<uint8_t> bits;
337
338 sequence.start_sequence()
339 .decode(oid)
342 .end_cons();
343
344 auto obj = create_extn_obj(oid, critical, bits, context);
345 // Unknown_Extension is the only Certificate_Extension with an empty oid_name
346 if(critical && obj->oid_name().empty()) {
347 m_has_unknown_critical_extension = true;
348 }
349 Extensions_Info info(critical, bits, std::move(obj));
350
351 // RFC 5280 4.2: "A certificate MUST NOT include more than one
352 // instance of a particular extension."
353 if(!m_extension_info.emplace(oid, info).second) {
354 throw Decoding_Error("Duplicate certificate extension encountered");
355 }
356 m_extension_oids.push_back(oid);
357 }
358 sequence.verify_end();
359}
360
361namespace Cert_Extension {
362
363bool Basic_Constraints::is_appropriate_context(Extension_Context context) const {
364 return context == Extension_Context::Certificate;
365}
366
367bool Key_Usage::is_appropriate_context(Extension_Context context) const {
368 return context == Extension_Context::Certificate;
369}
370
371bool Subject_Key_ID::is_appropriate_context(Extension_Context context) const {
372 return context == Extension_Context::Certificate;
373}
374
375bool Authority_Key_ID::is_appropriate_context(Extension_Context context) const {
376 return context == Extension_Context::Certificate || context == Extension_Context::CRL;
377}
378
379bool Subject_Alternative_Name::is_appropriate_context(Extension_Context context) const {
380 return context == Extension_Context::Certificate;
381}
382
383bool Issuer_Alternative_Name::is_appropriate_context(Extension_Context context) const {
384 return context == Extension_Context::Certificate || context == Extension_Context::CRL;
385}
386
387bool Extended_Key_Usage::is_appropriate_context(Extension_Context context) const {
388 return context == Extension_Context::Certificate;
389}
390
391bool Name_Constraints::is_appropriate_context(Extension_Context context) const {
392 return context == Extension_Context::Certificate;
393}
394
395bool Certificate_Policies::is_appropriate_context(Extension_Context context) const {
396 return context == Extension_Context::Certificate;
397}
398
399bool Authority_Information_Access::is_appropriate_context(Extension_Context context) const {
400 return context == Extension_Context::Certificate || context == Extension_Context::CRL;
401}
402
403bool CRL_Number::is_appropriate_context(Extension_Context context) const {
404 return context == Extension_Context::CRL;
405}
406
407bool CRL_ReasonCode::is_appropriate_context(Extension_Context context) const {
408 // RFC 6960 4.4.5: "All the extensions specified as CRL entry extensions
409 // -- in Section 5.3 of [RFC5280] -- are also supported as singleExtensions."
411}
412
413bool CRL_Distribution_Points::is_appropriate_context(Extension_Context context) const {
414 return context == Extension_Context::Certificate;
415}
416
417bool CRL_Issuing_Distribution_Point::is_appropriate_context(Extension_Context context) const {
418 return context == Extension_Context::CRL;
419}
420
421bool OCSP_NoCheck::is_appropriate_context(Extension_Context context) const {
422 return context == Extension_Context::Certificate;
423}
424
425bool NoRevocationAvailable::is_appropriate_context(Extension_Context context) const {
426 return context == Extension_Context::Certificate;
427}
428
429bool TNAuthList::is_appropriate_context(Extension_Context context) const {
430 return context == Extension_Context::Certificate;
431}
432
433bool IPAddressBlocks::is_appropriate_context(Extension_Context context) const {
434 return context == Extension_Context::Certificate;
435}
436
437bool ASBlocks::is_appropriate_context(Extension_Context context) const {
438 return context == Extension_Context::Certificate;
439}
440
441bool Unknown_Extension::is_appropriate_context(Extension_Context /*context*/) const {
442 return true;
443}
444
447
449 m_is_ca(is_ca), m_path_length_constraint(path_length_constraint) {
450 if(!m_is_ca && m_path_length_constraint.has_value()) {
451 // RFC 5280 Sec 4.2.1.9 "CAs MUST NOT include the pathLenConstraint field unless the cA boolean is asserted"
452 throw Invalid_Argument(
453 "Basic_Constraints nonsensical to set a path length constraint for a non-CA basicConstraints");
454 }
455}
456
457/*
458* Checked accessor for the path_length_constraint member
459*/
461 if(m_is_ca) {
462 return m_path_length_constraint.value_or(NO_CERT_PATH_LIMIT);
463 } else {
464 throw Invalid_State("Basic_Constraints::get_path_limit: Not a CA");
465 }
466}
467
468/*
469* Encode the extension
470*/
471std::vector<uint8_t> Basic_Constraints::encode_inner() const {
472 std::vector<uint8_t> output;
473
474 if(m_is_ca) {
475 DER_Encoder(output).start_sequence().encode(m_is_ca).encode_optional(m_path_length_constraint).end_cons();
476 } else {
478 }
479
480 return output;
481}
482
483/*
484* Decode the extension
485*/
486void Basic_Constraints::decode_inner(const std::vector<uint8_t>& in) {
487 /*
488 * RFC 5280 Section 4.2.1.9
489 *
490 * BasicConstraints ::= SEQUENCE {
491 * cA BOOLEAN DEFAULT FALSE,
492 * pathLenConstraint INTEGER (0..MAX) OPTIONAL }
493 */
494 BER_Decoder(in, BER_Decoder::Limits::DER())
495 .start_sequence()
496 .decode_optional(m_is_ca, ASN1_Type::Boolean, ASN1_Class::Universal, false)
497 .decode_optional(m_path_length_constraint, ASN1_Type::Integer, ASN1_Class::Universal)
498 .end_cons()
499 .verify_end();
500
501 /* RFC 5280 Section 4.2.1.9:
502 * "CAs MUST NOT include the pathLenConstraint field unless the cA boolean
503 * is asserted and the key usage extension asserts the keyCertSign bit" */
504 if(!m_is_ca && m_path_length_constraint.has_value()) {
505 throw Decoding_Error("BasicConstraints pathLenConstraint must not be present when cA is FALSE");
506 }
507}
508
509/*
510* Encode the extension
511*/
512std::vector<uint8_t> Key_Usage::encode_inner() const {
513 if(m_constraints.empty()) {
514 throw Encoding_Error("Cannot encode empty PKIX key constraints");
515 }
516
517 std::vector<uint8_t> der;
518 DER_Encoder(der).encode_named_bitstring(m_constraints.value(), 16);
519 return der;
520}
521
522/*
523* Decode the extension
524*/
525void Key_Usage::decode_inner(const std::vector<uint8_t>& in) {
526 /* RFC 5280 Section 4.2.1.3 - KeyUsage ::= BIT STRING */
527 uint64_t usage = 0;
528 BER_Decoder(in, BER_Decoder::Limits::DER())
529 .decode_named_bitstring(usage, 16, ASN1_Type::BitString, ASN1_Class::Universal)
530 .verify_end();
531
532 /* RFC 5280 Section 4.2.1.3:
533 * "When the keyUsage extension appears in a certificate, at least one of
534 * the bits MUST be set to 1." */
535 if(usage == 0) {
536 throw Decoding_Error("KeyUsage extension must have at least one bit set");
537 }
538
539 m_constraints = Key_Constraints(static_cast<uint32_t>(usage));
540}
541
542/*
543* Encode the extension
544*/
545std::vector<uint8_t> Subject_Key_ID::encode_inner() const {
546 std::vector<uint8_t> output;
547 DER_Encoder(output).encode(m_key_id, ASN1_Type::OctetString);
548 return output;
549}
550
551/*
552* Decode the extension
553*/
554void Subject_Key_ID::decode_inner(const std::vector<uint8_t>& in) {
555 /* RFC 5280 Section 4.2.1.2 - SubjectKeyIdentifier ::= KeyIdentifier */
556 BER_Decoder(in, BER_Decoder::Limits::DER()).decode(m_key_id, ASN1_Type::OctetString).verify_end();
557
558 if(m_key_id.empty()) {
559 throw Decoding_Error("SubjectKeyIdentifier must not be empty");
560 }
561 if(m_key_id.size() > MaximumKeyIdentifierLength) {
562 throw Decoding_Error(
563 fmt("SubjectKeyIdentifier length {} exceeds limit of {} bytes", m_key_id.size(), MaximumKeyIdentifierLength));
564 }
565}
566
567/*
568* Subject_Key_ID Constructor
569*/
571 /*
572 * RFC 5280 4.2.1.2:
573 * (1) The keyIdentifier is composed of the 160-bit SHA-1 hash of the
574 * value of the BIT STRING subjectPublicKey (excluding the tag, length,
575 * and number of unused bits).
576 */
577 auto hash = HashFunction::create_or_throw("SHA-1");
578
579 m_key_id.resize(hash->output_length());
580
581 hash->update(pub_key.public_key_bits());
582 hash->final(m_key_id.data());
583}
584
585/*
586* Subject_Key_ID Constructor
587*/
588Subject_Key_ID::Subject_Key_ID(const std::vector<uint8_t>& pub_key, std::string_view hash_name) {
589 auto hash = HashFunction::create_or_throw(hash_name);
590
591 m_key_id.resize(hash->output_length());
592
593 hash->update(pub_key);
594 hash->final(m_key_id.data());
595
596 // Truncate longer hashes, 192 bits here seems plenty
597 const size_t max_skid_len = (192 / 8);
598 if(m_key_id.size() > max_skid_len) {
599 m_key_id.resize(max_skid_len);
600 }
601}
602
603/*
604* Encode the extension
605*/
606std::vector<uint8_t> Authority_Key_ID::encode_inner() const {
607 std::vector<uint8_t> output;
608 DER_Encoder der(output);
609 der.start_sequence();
610 if(!m_key_id.empty()) {
612 }
613 if(m_authority_cert.has_value()) {
614 emit_general_names_implicit(der, m_authority_cert->issuer, 1);
615 der.encode(m_authority_cert->serial_number.to_bigint(), ASN1_Type(2), ASN1_Class::ContextSpecific);
616 }
617 der.end_cons();
618 return output;
619}
620
621/*
622* Decode the extension
623*/
624void Authority_Key_ID::decode_inner(const std::vector<uint8_t>& in) {
625 /*
626 * RFC 5280 Section 4.2.1.1
627 *
628 * AuthorityKeyIdentifier ::= SEQUENCE {
629 * keyIdentifier [0] KeyIdentifier OPTIONAL,
630 * authorityCertIssuer [1] GeneralNames OPTIONAL,
631 * authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL }
632 */
633 BER_Decoder ber(in, BER_Decoder::Limits::DER());
634 BER_Decoder seq = ber.start_sequence();
635
636 m_key_id.clear();
637 m_authority_cert.reset();
638
639 bool key_id_present = false;
640 std::optional<AlternativeName> authority_cert_issuer;
641 std::optional<X509_Serial_Number> authority_cert_serial;
642
643 seq.decode_optional_field(0,
645 [&](BER_Decoder& d) {
647 key_id_present = true;
648 })
649 .decode_optional_field(1,
651 [&](BER_Decoder& d) {
652 AlternativeName names;
653 d.decode_implicit(names,
654 ASN1_Type(1),
658 authority_cert_issuer = std::move(names);
659 })
660 .decode_optional_field(2, ASN1_Class::ContextSpecific, [&](BER_Decoder& d) {
661 X509_Serial_Number serial;
662 d.decode_implicit(
664 authority_cert_serial = std::move(serial);
665 });
666
667 seq.end_cons();
668 ber.verify_end();
669
670 if(key_id_present) {
671 if(m_key_id.empty()) {
672 throw Decoding_Error("AuthorityKeyIdentifier keyIdentifier must not be empty");
673 }
674 if(m_key_id.size() > MaximumKeyIdentifierLength) {
675 throw Decoding_Error(fmt("AuthorityKeyIdentifier keyIdentifier length {} exceeds limit of {} bytes",
676 m_key_id.size(),
677 MaximumKeyIdentifierLength));
678 }
679 }
680
681 // RFC 5280 4.2.1.6: GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
682 if(authority_cert_issuer.has_value() && authority_cert_issuer->is_empty()) {
683 throw Decoding_Error("AuthorityKeyIdentifier authorityCertIssuer must contain at least one GeneralName");
684 }
685
686 /*
687 * RFC 5280 Appendix A.2:
688 *
689 * authorityCertIssuer and authorityCertSerialNumber MUST both be
690 * present or both be absent
691 */
692 if(authority_cert_issuer.has_value() != authority_cert_serial.has_value()) {
693 throw Decoding_Error(
694 "AuthorityKeyIdentifier authorityCertIssuer and authorityCertSerialNumber must both be present or absent");
695 }
696
697 if(authority_cert_issuer.has_value()) {
698 m_authority_cert =
699 Authority_Cert_Identifier{std::move(*authority_cert_issuer), std::move(*authority_cert_serial)};
700 }
701}
702
703/*
704* Encode the extension
705*/
706std::vector<uint8_t> Subject_Alternative_Name::encode_inner() const {
707 std::vector<uint8_t> output;
708 DER_Encoder(output).encode(m_alt_name);
709 return output;
710}
711
712/*
713* Encode the extension
714*/
715std::vector<uint8_t> Issuer_Alternative_Name::encode_inner() const {
716 std::vector<uint8_t> output;
717 DER_Encoder(output).encode(m_alt_name);
718 return output;
719}
720
721/*
722* Decode the extension
723*/
724void Subject_Alternative_Name::decode_inner(const std::vector<uint8_t>& in) {
725 /* RFC 5280 Section 4.2.1.6 - SubjectAltName ::= GeneralNames
726 * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName */
727 BER_Decoder(in, BER_Decoder::Limits::DER()).decode(m_alt_name).verify_end();
728 if(!m_alt_name.has_items()) {
729 throw Decoding_Error("SubjectAlternativeName extension must contain at least one GeneralName");
730 }
731}
732
733/*
734* Decode the extension
735*/
736void Issuer_Alternative_Name::decode_inner(const std::vector<uint8_t>& in) {
737 /* RFC 5280 Section 4.2.1.7 - IssuerAltName ::= GeneralNames
738 * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName */
739 BER_Decoder(in, BER_Decoder::Limits::DER()).decode(m_alt_name).verify_end();
740 if(!m_alt_name.has_items()) {
741 throw Decoding_Error("IssuerAlternativeName extension must contain at least one GeneralName");
742 }
743}
744
745/*
746* Encode the extension
747*/
748std::vector<uint8_t> Extended_Key_Usage::encode_inner() const {
749 std::vector<uint8_t> output;
750 DER_Encoder(output).start_sequence().encode_list(m_oids).end_cons();
751 return output;
752}
753
754/*
755* Decode the extension
756*/
757void Extended_Key_Usage::decode_inner(const std::vector<uint8_t>& in) {
758 /* RFC 5280 Section 4.2.1.12 - ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId */
759 BER_Decoder(in, BER_Decoder::Limits::DER()).decode_list(m_oids).verify_end();
760 if(m_oids.empty()) {
761 throw Decoding_Error("ExtendedKeyUsage extension must contain at least one KeyPurposeId");
762 }
763}
764
765/*
766* Encode the extension
767*/
768std::vector<uint8_t> Name_Constraints::encode_inner() const {
769 const auto& permitted = m_name_constraints.permitted();
770 const auto& excluded = m_name_constraints.excluded();
771
772 if(permitted.empty() && excluded.empty()) {
773 throw Encoding_Error("Refusing to encode empty NameConstraints");
774 }
775
776 std::vector<uint8_t> output;
777 DER_Encoder der(output);
778 der.start_sequence();
779 if(!permitted.empty()) {
780 der.start_explicit_context_specific(0).encode_list(permitted).end_cons();
781 }
782 if(!excluded.empty()) {
783 der.start_explicit_context_specific(1).encode_list(excluded).end_cons();
784 }
785 der.end_cons();
786 return output;
787}
788
789/*
790* Decode the extension
791*/
792void Name_Constraints::decode_inner(const std::vector<uint8_t>& in) {
793 /*
794 * RFC 5280 Section 4.2.1.10
795 *
796 * NameConstraints ::= SEQUENCE {
797 * permittedSubtrees [0] GeneralSubtrees OPTIONAL,
798 * excludedSubtrees [1] GeneralSubtrees OPTIONAL }
799 */
800 BER_Decoder ber(in, BER_Decoder::Limits::DER());
801 BER_Decoder inner = ber.start_sequence();
802
803 std::vector<GeneralSubtree> permitted;
804 if(inner.decode_optional_list(permitted, ASN1_Type(0), ASN1_Class::ExplicitContextSpecific)) {
805 if(permitted.empty()) {
806 throw Decoding_Error("Empty NameConstraint permitted list");
807 }
808 }
809
810 std::vector<GeneralSubtree> excluded;
811 if(inner.decode_optional_list(excluded, ASN1_Type(1), ASN1_Class::ExplicitContextSpecific)) {
812 if(excluded.empty()) {
813 throw Decoding_Error("Empty NameConstraint excluded list");
814 }
815 }
816
817 inner.end_cons();
818 ber.verify_end();
819
820 if(permitted.empty() && excluded.empty()) {
821 throw Decoding_Error("Empty NameConstraint extension");
822 }
823
824 m_name_constraints = NameConstraints(std::move(permitted), std::move(excluded));
825}
826
828 const std::optional<X509_Certificate>& /*issuer*/,
829 const std::vector<X509_Certificate>& cert_path,
830 std::vector<std::set<Certificate_Status_Code>>& cert_status,
831 size_t pos) const {
832 if(!m_name_constraints.permitted().empty() || !m_name_constraints.excluded().empty()) {
833 if(!subject.is_CA_cert()) {
834 cert_status.at(pos).insert(Certificate_Status_Code::NAME_CONSTRAINT_ERROR);
835 }
836
837 const bool issuer_name_constraint_critical = subject.is_critical("X509v3.NameConstraints");
838
839 // Check that all subordinate certs pass the name constraint
840 for(size_t j = 0; j < pos; ++j) {
841 const auto& cert = cert_path.at(j);
842
843 // RFC 5280 6.1.4(b): "Name constraints are not applied to self-issued
844 // certificates (unless the certificate is the final certificate in the path)"
845 // Position 0 is the end entity (final certificate); skip self-issued intermediates.
846 if(j > 0 && cert.issuer_dn() == cert.subject_dn()) {
847 continue;
848 }
849
850 if(!m_name_constraints.is_permitted(cert, issuer_name_constraint_critical)) {
851 cert_status.at(j).insert(Certificate_Status_Code::NAME_CONSTRAINT_ERROR);
852 continue;
853 }
854
855 if(m_name_constraints.is_excluded(cert, issuer_name_constraint_critical)) {
856 cert_status.at(j).insert(Certificate_Status_Code::NAME_CONSTRAINT_ERROR);
857 continue;
858 }
859 }
860 }
861}
862
863namespace {
864
865/*
866* A policy specifier
867*/
868class Policy_Information final : public ASN1_Object {
869 public:
870 Policy_Information() = default;
871
872 explicit Policy_Information(const OID& oid) : m_oid(oid) {}
873
874 const OID& oid() const { return m_oid; }
875
876 void encode_into(DER_Encoder& codec) const override { codec.start_sequence().encode(m_oid).end_cons(); }
877
878 void decode_from(BER_Decoder& codec) override {
879 codec.start_sequence().decode(m_oid).discard_remaining().end_cons();
880 }
881
882 private:
883 OID m_oid;
884};
885
886bool policy_oids_have_duplicate(const std::vector<OID>& oids) {
887 std::set<OID> seen;
888 for(const auto& oid : oids) {
889 if(!seen.insert(oid).second) {
890 return true;
891 }
892 }
893 return false;
894}
895
896} // namespace
897
898Certificate_Policies::Certificate_Policies(const std::vector<OID>& oids) :
899 m_oids(oids), m_has_duplicate(policy_oids_have_duplicate(m_oids)) {}
900
901/*
902* Encode the extension
903*/
904std::vector<uint8_t> Certificate_Policies::encode_inner() const {
905 std::vector<Policy_Information> policies;
906
907 policies.reserve(m_oids.size());
908 for(const auto& oid : m_oids) {
909 policies.push_back(Policy_Information(oid));
910 }
911
912 std::vector<uint8_t> output;
913 DER_Encoder(output).start_sequence().encode_list(policies).end_cons();
914 return output;
915}
916
917/*
918* Decode the extension
919*/
920void Certificate_Policies::decode_inner(const std::vector<uint8_t>& in) {
921 /* RFC 5280 Section 4.2.1.4 - CertificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation */
922 std::vector<Policy_Information> policies;
923
924 BER_Decoder(in, BER_Decoder::Limits::DER()).decode_list(policies).verify_end();
925 if(policies.empty()) {
926 throw Decoding_Error("CertificatePolicies extension must contain at least one PolicyInformation");
927 }
928 m_oids.clear();
929 for(const auto& policy : policies) {
930 m_oids.push_back(policy.oid());
931 }
932 m_has_duplicate = policy_oids_have_duplicate(m_oids);
933}
934
936 const std::optional<X509_Certificate>& /*issuer*/,
937 const std::vector<X509_Certificate>& /*cert_path*/,
938 std::vector<std::set<Certificate_Status_Code>>& cert_status,
939 size_t pos) const {
940 if(m_has_duplicate) {
941 cert_status.at(pos).insert(Certificate_Status_Code::DUPLICATE_CERT_POLICY);
942 }
943}
944
945namespace {
946
947std::vector<URI> parse_aia_uris(const std::vector<std::string>& uris, const char* context) {
948 std::vector<URI> out;
949 out.reserve(uris.size());
950 for(const auto& uri : uris) {
951 if(auto parsed = URI::from_string(uri)) {
952 out.push_back(std::move(*parsed));
953 } else {
954 throw Invalid_Argument(fmt("Invalid URI in {}", context));
955 }
956 }
957 return out;
958}
959
960// Convert the application provided URIs into AccessDescription entries
961std::vector<Authority_Information_Access::AccessDescription> uri_access_descriptions(
962 const std::vector<URI>& ocsp_responders, const std::vector<URI>& ca_issuers) {
963 std::vector<Authority_Information_Access::AccessDescription> out;
964 out.reserve(ocsp_responders.size() + ca_issuers.size());
965
966 const auto append = [&](const OID& method, const std::vector<URI>& uris) {
967 for(const auto& uri : uris) {
968 const ASN1_String value(uri.original_input(), ASN1_Type::Ia5String);
969 out.emplace_back(method,
970 ASN1_Type(6),
972 std::vector<uint8_t>(value.value().begin(), value.value().end()));
973 }
974 };
975
976 append(OID::from_string("PKIX.OCSP"), ocsp_responders);
977 append(OID::from_string("PKIX.CertificateAuthorityIssuers"), ca_issuers);
978 return out;
979}
980
981} // namespace
982
984 const std::vector<std::string>& ca_issuers) :
985 m_ca_issuers(parse_aia_uris(ca_issuers, "AuthorityInformationAccess CA issuers")) {
986 if(!ocsp.empty()) {
987 if(auto parsed = URI::from_string(ocsp)) {
988 m_ocsp_responders.push_back(std::move(*parsed));
989 } else {
990 throw Invalid_Argument("Invalid URI in AuthorityInformationAccess OCSP responder");
991 }
992 }
993 m_access_descriptions = uri_access_descriptions(m_ocsp_responders, m_ca_issuers);
994}
995
997 const std::vector<std::string>& ca_issuers) :
998 m_ocsp_responders(parse_aia_uris(ocsp_responders, "AuthorityInformationAccess OCSP responders")),
999 m_ca_issuers(parse_aia_uris(ca_issuers, "AuthorityInformationAccess CA issuers")),
1000 m_access_descriptions(uri_access_descriptions(m_ocsp_responders, m_ca_issuers)) {}
1001
1003 std::vector<URI> ca_issuers) :
1004 m_ocsp_responders(std::move(ocsp_responders)),
1005 m_ca_issuers(std::move(ca_issuers)),
1006 m_access_descriptions(uri_access_descriptions(m_ocsp_responders, m_ca_issuers)) {}
1007
1008std::vector<std::string> Authority_Information_Access::ocsp_responders() const {
1009 std::vector<std::string> out;
1010 out.reserve(m_ocsp_responders.size());
1011 for(const auto& uri : m_ocsp_responders) {
1012 out.push_back(uri.original_input());
1013 }
1014 return out;
1015}
1016
1017std::unique_ptr<Certificate_Extension> Authority_Information_Access::copy() const {
1018 return std::make_unique<Authority_Information_Access>(*this);
1019}
1020
1021namespace {
1022
1023void validate_general_name_encoding(ASN1_Type tag, ASN1_Class cls, std::span<const uint8_t> value) {
1024 // AlternativeName decodes GeneralNames; AIA accessLocation is a single GeneralName.
1025 std::vector<uint8_t> wrapped_name;
1026 DER_Encoder(wrapped_name).start_sequence().add_object(tag, cls, value).end_cons();
1027
1028 AlternativeName decoded_name;
1029 BER_Decoder(wrapped_name, BER_Decoder::Limits::DER()).decode(decoded_name).verify_end();
1030
1031 if((tag == ASN1_Type(1) || tag == ASN1_Type(2) || tag == ASN1_Type(6)) && value.empty()) {
1032 throw Decoding_Error("GeneralName IA5String value must not be empty");
1033 }
1034 if(tag == ASN1_Type(4) &&
1035 std::ranges::any_of(decoded_name.directory_names(), [](const X509_DN& dn) { return dn.empty(); })) {
1036 throw Decoding_Error("GeneralName directoryName must not be empty");
1037 }
1038}
1039
1040// Construction-time validation for an AccessDescription entering
1041// m_access_descriptions. encode_inner repeats this as a safety net; doing it
1042// here means the throw lands where the caller is building the AIA.
1043void validate_access_description(const Authority_Information_Access::AccessDescription& ad) {
1044 try {
1045 validate_general_name_encoding(ad.location_tag(), ad.location_class(), ad.location_value());
1046 } catch(const Exception&) {
1047 throw Invalid_Argument("AccessDescription accessLocation is not a valid GeneralName");
1048 }
1049}
1050
1051// Mirror the decode-time logic that populates the typed URI accessors from
1052// id-ad-ocsp / id-ad-caIssuers entries. Used by the AccessDescription-based
1053// constructor and add_access_description so the two views stay consistent.
1054// An id-ad-ocsp / id-ad-caIssuers entry whose URI fails to parse is rejected
1055// here (mirroring decode_inner) so the typed accessors and m_access_descriptions
1056// cannot disagree, and so the AIA cannot re-encode bytes that its own decoder
1057// would reject.
1058void populate_uri_view_from_access_description(const Authority_Information_Access::AccessDescription& ad,
1059 std::vector<URI>& ocsp_responders,
1060 std::vector<URI>& ca_issuers) {
1061 const auto oid_ocsp_responders = OID::from_string("PKIX.OCSP");
1062 const auto oid_ca_issuers = OID::from_string("PKIX.CertificateAuthorityIssuers");
1063 if(const auto uri_str = ad.location_as_uri_string()) {
1064 if(ad.access_method() == oid_ocsp_responders) {
1065 if(auto uri = URI::from_string(*uri_str)) {
1066 ocsp_responders.push_back(std::move(*uri));
1067 } else {
1068 throw Invalid_Argument("Invalid URI in AuthorityInformationAccess OCSP responder");
1069 }
1070 } else if(ad.access_method() == oid_ca_issuers) {
1071 if(auto uri = URI::from_string(*uri_str)) {
1072 ca_issuers.push_back(std::move(*uri));
1073 } else {
1074 throw Invalid_Argument("Invalid URI in AuthorityInformationAccess CA issuers");
1075 }
1076 }
1077 }
1078}
1079
1080} // namespace
1081
1083 m_access_descriptions(std::move(access_descriptions)) {
1084 for(const auto& ad : m_access_descriptions) {
1085 validate_access_description(ad);
1086 populate_uri_view_from_access_description(ad, m_ocsp_responders, m_ca_issuers);
1087 }
1088}
1089
1091 validate_access_description(ad);
1092 populate_uri_view_from_access_description(ad, m_ocsp_responders, m_ca_issuers);
1093 m_access_descriptions.push_back(std::move(ad));
1094}
1095
1096std::vector<std::string> Authority_Information_Access::ca_issuers() const {
1097 std::vector<std::string> out;
1098 out.reserve(m_ca_issuers.size());
1099 for(const auto& uri : m_ca_issuers) {
1100 out.push_back(uri.original_input());
1101 }
1102 return out;
1103}
1104
1106 if(m_location_class == ASN1_Class::ContextSpecific && m_location_tag == ASN1_Type(6)) {
1107 return std::string(m_location_value.begin(), m_location_value.end());
1108 }
1109 return std::nullopt;
1110}
1111
1112std::vector<uint8_t> Authority_Information_Access::encode_inner() const {
1113 std::vector<uint8_t> output;
1114 DER_Encoder der(output);
1115
1116 der.start_sequence();
1117
1118 for(const auto& ad : m_access_descriptions) {
1119 try {
1120 validate_general_name_encoding(ad.location_tag(), ad.location_class(), ad.location_value());
1121 } catch(const Exception&) {
1122 throw Encoding_Error("AccessDescription accessLocation is not a valid GeneralName");
1123 }
1124 der.start_sequence()
1125 .encode(ad.access_method())
1126 .add_object(ad.location_tag(), ad.location_class(), ad.location_value())
1127 .end_cons();
1128 }
1129
1130 der.end_cons();
1131 return output;
1132}
1133
1134void Authority_Information_Access::decode_inner(const std::vector<uint8_t>& in) {
1135 /*
1136 * RFC 5280 Section 4.2.2.1
1137 *
1138 * AuthorityInfoAccessSyntax ::= SEQUENCE SIZE (1..MAX) OF AccessDescription
1139 * AccessDescription ::= SEQUENCE {
1140 * accessMethod OBJECT IDENTIFIER,
1141 * accessLocation GeneralName }
1142 */
1143 BER_Decoder outer(in, BER_Decoder::Limits::DER());
1144 BER_Decoder ber = outer.start_sequence();
1145
1146 const OID ocsp_responder = OID::from_string("PKIX.OCSP");
1147 const OID ca_issuer = OID::from_string("PKIX.CertificateAuthorityIssuers");
1148
1149 m_access_descriptions.clear();
1150 m_ocsp_responders.clear();
1151 m_ca_issuers.clear();
1152
1153 while(ber.more_items()) {
1154 OID oid;
1155
1156 BER_Decoder info = ber.start_sequence();
1157
1158 info.decode(oid);
1159 const BER_Object name = info.get_next_object();
1160
1161 /* RFC 5280 4.2.2.1:
1162 * AccessDescription ::= SEQUENCE {
1163 * accessMethod OBJECT IDENTIFIER,
1164 * accessLocation GeneralName }
1165 */
1166 if(!name.is_set()) {
1167 throw Decoding_Error("AuthorityInformationAccess AccessDescription missing accessLocation");
1168 }
1169 validate_general_name_encoding(name.type_tag(), name.get_class(), name.data());
1170 info.end_cons();
1171
1172 m_access_descriptions.emplace_back(
1173 oid, name.type_tag(), name.get_class(), std::vector<uint8_t>(name.data().begin(), name.data().end()));
1174
1175 if(name.is_a(6, ASN1_Class::ContextSpecific)) {
1176 if(oid == ocsp_responder) {
1177 if(auto parsed = URI::from_string(ASN1::to_string(name))) {
1178 m_ocsp_responders.push_back(std::move(*parsed));
1179 } else {
1180 throw Decoding_Error("Invalid URI in AuthorityInformationAccess OCSP responder");
1181 }
1182 } else if(oid == ca_issuer) {
1183 if(auto parsed = URI::from_string(ASN1::to_string(name))) {
1184 m_ca_issuers.push_back(std::move(*parsed));
1185 } else {
1186 throw Decoding_Error("Invalid URI in AuthorityInformationAccess CA issuers");
1187 }
1188 }
1189 }
1190 }
1191
1192 ber.end_cons();
1193 outer.verify_end();
1194
1195 if(m_access_descriptions.empty()) {
1196 throw Decoding_Error("AuthorityInformationAccess extension must contain at least one AccessDescription");
1197 }
1198}
1199
1200CRL_Number::CRL_Number(BigInt n) : m_has_value(true), m_crl_number(std::move(n)) {
1201 BOTAN_ARG_CHECK(m_crl_number.signum() >= 0, "CRL number cannot be negative");
1202}
1203
1205 // This can only happen via a misuse of the CRL_Number default constructor
1206 BOTAN_STATE_CHECK(m_has_value);
1207 return m_crl_number;
1208}
1209
1210/*
1211* Checked accessor for the crl_number member
1212*/
1214 // This can only happen via a misuse of the CRL_Number default constructor
1215 BOTAN_STATE_CHECK(m_has_value);
1216 return m_crl_number.to_u32bit();
1217}
1218
1219/*
1220* Copy a CRL_Number extension
1221*/
1222std::unique_ptr<Certificate_Extension> CRL_Number::copy() const {
1223 return std::make_unique<CRL_Number>(*this);
1224}
1225
1226/*
1227* Encode the extension
1228*/
1229std::vector<uint8_t> CRL_Number::encode_inner() const {
1230 std::vector<uint8_t> output;
1231 DER_Encoder(output).encode(m_crl_number);
1232 return output;
1233}
1234
1235/*
1236* Decode the extension
1237*/
1238void CRL_Number::decode_inner(const std::vector<uint8_t>& in) {
1239 /* RFC 5280 Section 5.2.3 - CRLNumber ::= INTEGER (0..MAX) */
1241 if(m_crl_number.signum() < 0) {
1242 throw Decoding_Error("CRL number cannot be negative");
1243 }
1244 m_has_value = true;
1245}
1246
1247/*
1248* Encode the extension
1249*/
1250std::vector<uint8_t> CRL_ReasonCode::encode_inner() const {
1251 std::vector<uint8_t> output;
1252 DER_Encoder(output).encode(static_cast<size_t>(m_reason), ASN1_Type::Enumerated, ASN1_Class::Universal);
1253 return output;
1254}
1255
1256/*
1257* Decode the extension
1258*/
1259void CRL_ReasonCode::decode_inner(const std::vector<uint8_t>& in) {
1260 /*
1261 * RFC 5280 Section 5.3.1
1262 *
1263 * CRLReason ::= ENUMERATED {
1264 * unspecified (0),
1265 * keyCompromise (1),
1266 * cACompromise (2),
1267 * affiliationChanged (3),
1268 * superseded (4),
1269 * cessationOfOperation (5),
1270 * certificateHold (6),
1271 * -- value 7 is not used
1272 * removeFromCRL (8),
1273 * privilegeWithdrawn (9),
1274 * aACompromise (10) }
1275 */
1276 size_t reason_code = 0;
1277 BER_Decoder(in, BER_Decoder::Limits::DER())
1278 .decode(reason_code, ASN1_Type::Enumerated, ASN1_Class::Universal)
1279 .verify_end();
1280
1281 if(reason_code == 7 || reason_code > 10) {
1282 throw Decoding_Error(fmt("CRLReason has unknown enumeration value {}", reason_code));
1283 }
1284
1285 m_reason = static_cast<CRL_Code>(reason_code);
1286}
1287
1288namespace {
1289
1290constexpr size_t ReasonFlagsNamedBitWidth = 9;
1291
1292void emit_reason_flags_implicit(DER_Encoder& der, uint32_t tag, ReasonFlags reasons) {
1293 der.encode_named_bitstring(reasons.value(), ReasonFlagsNamedBitWidth, ASN1_Type(tag), ASN1_Class::ContextSpecific);
1294}
1295
1296ReasonFlags decode_reason_flags_implicit(BER_Decoder& decoder, uint32_t tag) {
1297 uint64_t bits = 0;
1298 decoder.decode_named_bitstring(bits, ReasonFlagsNamedBitWidth, ASN1_Type(tag), ASN1_Class::ContextSpecific);
1299 return ReasonFlags(checked_cast_to<uint16_t>(bits));
1300}
1301
1302/*
1303* RFC 5280 4.2.1.13: "If present, the cRLIssuer MUST only contain the
1304* distinguished name (DN) from the issuer field of the CRL to which the
1305* DistributionPoint is pointing."
1306*
1307* We don't know the value of the CRL issuer at this point so we can only
1308* enforce that the cRLIssuer name is exactly one non-empty DN.
1309*/
1310bool crl_issuer_is_well_formed(const AlternativeName& crl_issuer) {
1311 const auto& dn = crl_issuer.directory_names();
1312 return crl_issuer.count() == 1 && dn.size() == 1 && !dn.begin()->empty();
1313}
1314
1315std::vector<URI> crl_distribution_point_uris_from_distribution_points(
1316 const std::vector<CRL_Distribution_Points::Distribution_Point>& dps) {
1317 std::vector<URI> out;
1318 for(const auto& dp : dps) {
1319 const auto& dpn = dp.distribution_point_name();
1320 if(dpn.has_value() && dpn->full_name().has_value()) {
1321 for(const auto& uri : dpn->full_name()->uri_names()) {
1322 out.push_back(uri);
1323 }
1324 }
1325 }
1326 return out;
1327}
1328
1329} // namespace
1330
1332 BOTAN_STATE_CHECK(m_dp_name.has_value() && m_dp_name->full_name().has_value());
1333 return *m_dp_name->full_name();
1334}
1335
1336CRL_Distribution_Points::CRL_Distribution_Points(const std::vector<Distribution_Point>& points) :
1337 m_distribution_points(points),
1338 m_crl_distribution_urls(crl_distribution_point_uris_from_distribution_points(m_distribution_points)) {}
1339
1341 BOTAN_STATE_CHECK(m_dp_name.has_value() && m_dp_name->full_name().has_value());
1342 return *m_dp_name->full_name();
1343}
1344
1346 if(!m_full_name.has_value()) {
1347 throw Encoding_Error("DistributionPointName has no fullName to encode");
1348 }
1349 // fullName [0] IMPLICIT GeneralNames. emit_general_names_implicit rejects
1350 // empty AlternativeNames per RFC 5280 4.2.1.6: GeneralNames ::= SEQUENCE
1351 // SIZE (1..MAX).
1352 emit_general_names_implicit(der, *m_full_name, 0);
1353}
1354
1356 const BER_Object& obj = ber.peek_next_object();
1360 ASN1_Type(0),
1364 // RFC 5280 4.2.1.6: GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
1365 if(!full_name.has_items()) {
1366 throw Decoding_Error("DistributionPointName fullName must contain at least one GeneralName");
1367 }
1368 if(std::ranges::any_of(full_name.directory_names(), [](const X509_DN& dn) { return dn.empty(); })) {
1369 throw Decoding_Error("DistributionPointName fullName must not contain an empty directoryName");
1370 }
1371 m_full_name = std::move(full_name);
1373 throw Decoding_Error("nameRelativeToCrlIssuer not supported in DistributionPointName");
1374 } else {
1375 throw Decoding_Error("DistributionPointName CHOICE is neither fullName nor nameRelativeToCRLIssuer");
1376 }
1377}
1378
1379std::vector<uint8_t> CRL_Distribution_Points::encode_inner() const {
1380 std::vector<uint8_t> output;
1381 DER_Encoder(output).start_sequence().encode_list(m_distribution_points).end_cons();
1382 return output;
1383}
1384
1385void CRL_Distribution_Points::decode_inner(const std::vector<uint8_t>& buf) {
1386 /*
1387 * RFC 5280 Section 4.2.1.13
1388 *
1389 * CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
1390 */
1391 BER_Decoder(buf, BER_Decoder::Limits::DER()).decode_list(m_distribution_points).verify_end();
1392
1393 if(m_distribution_points.empty()) {
1394 throw Decoding_Error("CRLDistributionPoints extension must contain at least one DistributionPoint");
1395 }
1396
1397 m_crl_distribution_urls = crl_distribution_point_uris_from_distribution_points(m_distribution_points);
1398}
1399
1400std::vector<std::string> CRL_Distribution_Points::crl_distribution_urls() const {
1401 std::vector<std::string> out;
1402 out.reserve(m_crl_distribution_urls.size());
1403 for(const auto& uri : m_crl_distribution_urls) {
1404 out.push_back(uri.original_input());
1405 }
1406 return out;
1407}
1408
1410 /*
1411 * DistributionPoint ::= SEQUENCE {
1412 * distributionPoint [0] DistributionPointName OPTIONAL,
1413 * reasons [1] ReasonFlags OPTIONAL,
1414 * cRLIssuer [2] GeneralNames OPTIONAL }
1415 *
1416 * RFC 5280 4.2.1.13: "either distributionPoint or cRLIssuer MUST be present".
1417 */
1418 const bool has_dp_name = m_dp_name.has_value();
1419 const bool has_crl_issuer = m_crl_issuer.has_value();
1420 if(!has_dp_name && !has_crl_issuer) {
1421 throw Encoding_Error("DistributionPoint must contain either distributionPoint or cRLIssuer");
1422 }
1423 if(has_crl_issuer && !crl_issuer_is_well_formed(*m_crl_issuer)) {
1424 /* RFC 5280 4.2.1.13: "If present, the cRLIssuer MUST only contain the
1425 * distinguished name (DN) from the issuer field of the CRL". */
1426 throw Encoding_Error("cRLIssuer must contain exactly one non-empty directoryName GeneralName");
1427 }
1428
1429 der.start_sequence();
1430
1431 if(has_dp_name) {
1432 // distributionPoint [0] EXPLICIT DistributionPointName
1433 der.start_explicit_context_specific(0).encode(*m_dp_name).end_cons();
1434 }
1435
1436 if(m_reasons) {
1437 emit_reason_flags_implicit(der, 1, *m_reasons);
1438 }
1439
1440 if(has_crl_issuer) {
1441 emit_general_names_implicit(der, *m_crl_issuer, 2);
1442 }
1443
1444 der.end_cons();
1445}
1446
1448 /*
1449 * DistributionPoint ::= SEQUENCE {
1450 * distributionPoint [0] DistributionPointName OPTIONAL,
1451 * reasons [1] ReasonFlags OPTIONAL,
1452 * cRLIssuer [2] GeneralNames OPTIONAL }
1453 */
1454 BER_Decoder dp = ber.start_sequence();
1455
1456 m_dp_name.reset();
1457 m_reasons.reset();
1458 m_crl_issuer.reset();
1459
1460 // DER: these optional fields appear at most once and in increasing tag
1461 // order. Decoding them in tag order and then rejecting anything left over
1462 // (see end_cons below) catches out-of-order, duplicate, and unknown fields.
1465 [&](BER_Decoder& d) {
1468 m_dp_name = std::move(name);
1469 })
1470 .decode_optional_field(
1471 1, ASN1_Class::ContextSpecific, [&](BER_Decoder& d) { m_reasons = decode_reason_flags_implicit(d, 1); })
1472 .decode_optional_field(2, ASN1_Class::ContextSpecific | ASN1_Class::Constructed, [&](BER_Decoder& d) {
1475 ASN1_Type(2),
1479 m_crl_issuer = std::move(crl_issuer);
1480 });
1481
1482 dp.end_cons();
1483
1484 // RFC 5280 4.2.1.6: GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
1485 if(m_crl_issuer.has_value() && m_crl_issuer->is_empty()) {
1486 throw Decoding_Error("cRLIssuer GeneralNames must contain at least one GeneralName");
1487 }
1488
1489 if(m_crl_issuer.has_value() && !crl_issuer_is_well_formed(*m_crl_issuer)) {
1490 /* RFC 5280 4.2.1.13: "If present, the cRLIssuer MUST only contain the
1491 * distinguished name (DN) from the issuer field of the CRL". */
1492 throw Decoding_Error("cRLIssuer must contain exactly one non-empty directoryName GeneralName");
1493 }
1494
1495 if(!m_dp_name.has_value() && !m_crl_issuer.has_value()) {
1496 throw Decoding_Error("DistributionPoint must contain either distributionPoint or cRLIssuer");
1497 }
1498}
1499
1500std::vector<uint8_t> CRL_Issuing_Distribution_Point::encode_inner() const {
1501 /* RFC 5280 Section 5.2.5
1502 *
1503 * Conforming CRL issuers MUST NOT issue CRLs where the DER encoding of the
1504 * issuing distribution point extension is an empty sequence. [...] at most one
1505 * of onlyContainsUserCerts, onlyContainsCACerts, and onlyContainsAttributeCerts
1506 * may be set to TRUE
1507 */
1508 if(!should_encode()) {
1509 throw Encoding_Error("Refusing to encode empty IssuingDistributionPoint");
1510 }
1511
1512 const size_t scope_set = static_cast<size_t>(m_only_contains_user_certs) +
1513 static_cast<size_t>(m_only_contains_ca_certs) +
1514 static_cast<size_t>(m_only_contains_attribute_certs);
1515 if(scope_set > 1) {
1516 throw Encoding_Error(
1517 "At most one of onlyContainsUserCerts, onlyContainsCACerts, onlyContainsAttributeCerts may be TRUE");
1518 }
1519
1520 auto emit_optional_boolean_implicit = [](DER_Encoder& der, uint32_t tag, bool value) {
1521 // All of the values encoded here are DEFAULT FALSE so skip encoding if false
1522 if(value == true) {
1523 // Encode a BOOLEAN TRUE (0xFF) as [tag] IMPLICIT BOOLEAN
1524 const uint8_t val = 0xFF;
1526 }
1527 };
1528
1529 std::vector<uint8_t> output;
1530 DER_Encoder der(output);
1531 der.start_sequence();
1532
1533 if(m_dp_name.has_value()) {
1534 der.start_explicit_context_specific(0).encode(*m_dp_name).end_cons();
1535 }
1536
1537 emit_optional_boolean_implicit(der, 1, m_only_contains_user_certs);
1538 emit_optional_boolean_implicit(der, 2, m_only_contains_ca_certs);
1539
1540 if(m_only_some_reasons) {
1541 emit_reason_flags_implicit(der, 3, *m_only_some_reasons);
1542 }
1543
1544 emit_optional_boolean_implicit(der, 4, m_indirect_crl);
1545 emit_optional_boolean_implicit(der, 5, m_only_contains_attribute_certs);
1546
1547 der.end_cons();
1548 return output;
1549}
1550
1551void CRL_Issuing_Distribution_Point::decode_inner(const std::vector<uint8_t>& buf) {
1552 /*
1553 * RFC 5280 Section 5.2.5
1554 *
1555 * IssuingDistributionPoint ::= SEQUENCE {
1556 * distributionPoint [0] DistributionPointName OPTIONAL,
1557 * onlyContainsUserCerts [1] BOOLEAN DEFAULT FALSE,
1558 * onlyContainsCACerts [2] BOOLEAN DEFAULT FALSE,
1559 * onlySomeReasons [3] ReasonFlags OPTIONAL,
1560 * indirectCRL [4] BOOLEAN DEFAULT FALSE,
1561 * onlyContainsAttributeCerts [5] BOOLEAN DEFAULT FALSE }
1562 */
1563 BER_Decoder outer(buf, BER_Decoder::Limits::DER());
1564 BER_Decoder seq = outer.start_sequence();
1565
1566 m_dp_name.reset();
1567 m_only_contains_user_certs = false;
1568 m_only_contains_ca_certs = false;
1569 m_only_some_reasons = {};
1570 m_indirect_crl = false;
1571 m_only_contains_attribute_certs = false;
1572
1573 auto decode_implicit_bool = [&](BER_Decoder& dec, uint32_t tag) -> bool {
1574 bool value = false;
1575 dec.decode(value, ASN1_Type(tag), ASN1_Class::ContextSpecific);
1576 return value;
1577 };
1578
1579 // DER: these optional fields appear at most once and in increasing tag
1580 // order. Decoding them in tag order and then rejecting anything left over
1581 // (see end_cons below) catches out-of-order, duplicate, and unknown fields.
1582 seq.decode_optional_field(0,
1584 [&](BER_Decoder& d) {
1585 DistributionPointName name;
1586 d.start_context_specific(0).decode(name).verify_end();
1587 m_dp_name = std::move(name);
1588 })
1589 .decode_optional_field(1,
1591 [&](BER_Decoder& d) { m_only_contains_user_certs = decode_implicit_bool(d, 1); })
1592 .decode_optional_field(
1593 2, ASN1_Class::ContextSpecific, [&](BER_Decoder& d) { m_only_contains_ca_certs = decode_implicit_bool(d, 2); })
1594 .decode_optional_field(3,
1596 [&](BER_Decoder& d) { m_only_some_reasons = decode_reason_flags_implicit(d, 3); })
1597 .decode_optional_field(
1598 4, ASN1_Class::ContextSpecific, [&](BER_Decoder& d) { m_indirect_crl = decode_implicit_bool(d, 4); })
1599 .decode_optional_field(5, ASN1_Class::ContextSpecific, [&](BER_Decoder& d) {
1600 m_only_contains_attribute_certs = decode_implicit_bool(d, 5);
1601 });
1602
1603 seq.end_cons();
1604 outer.verify_end();
1605
1606 /* RFC 5280 5.2.5: "Conforming CRLs issuers MUST NOT issue CRLs where the
1607 * DER encoding of the issuing distribution point extension is an empty
1608 * sequence." Empty here means none of the fields above were present. */
1609 if(!m_dp_name.has_value() && !m_only_contains_user_certs && !m_only_contains_ca_certs &&
1610 !m_only_some_reasons.has_value() && !m_indirect_crl && !m_only_contains_attribute_certs) {
1611 throw Decoding_Error("IssuingDistributionPoint must contain at least one field");
1612 }
1613
1614 /* RFC 5280 5.2.5: "at most one of onlyContainsUserCerts,
1615 * onlyContainsCACerts, and onlyContainsAttributeCerts may be set to TRUE." */
1616 const size_t scope_set = static_cast<size_t>(m_only_contains_user_certs) +
1617 static_cast<size_t>(m_only_contains_ca_certs) +
1618 static_cast<size_t>(m_only_contains_attribute_certs);
1619 if(scope_set > 1) {
1620 throw Decoding_Error(
1621 "IssuingDistributionPoint sets more than one of onlyContainsUserCerts/CACerts/AttributeCerts");
1622 }
1623}
1624
1626 throw Not_Implemented("TNAuthList extension entry serialization is not supported");
1627}
1628
1630 const BER_Object obj = ber.get_next_object();
1631
1633 throw Decoding_Error(fmt("Unexpected TNEntry class tag {}", static_cast<uint32_t>(obj.get_class())));
1634 }
1635
1636 const uint32_t type_tag = static_cast<uint32_t>(obj.type_tag());
1637
1638 if(type_tag == ServiceProviderCode) {
1639 m_type = ServiceProviderCode;
1640 ASN1_String spc_string;
1641 BER_Decoder(obj, ber.limits()).decode(spc_string).verify_end();
1642 m_data = std::move(spc_string);
1643 } else if(type_tag == TelephoneNumberRange) {
1644 m_type = TelephoneNumberRange;
1645 m_data = RangeContainer();
1646 auto& range_items = std::get<RangeContainer>(m_data);
1647 BER_Decoder outer(obj, ber.limits());
1648 BER_Decoder list = outer.start_sequence();
1649 while(list.more_items()) {
1651
1652 list.decode(entry.start);
1653 if(!is_valid_telephone_number(entry.start)) {
1654 throw Decoding_Error(fmt("Invalid TelephoneNumberRange start {}", entry.start.value()));
1655 }
1656
1657 list.decode(entry.count);
1658 if(entry.count < 2) {
1659 throw Decoding_Error(fmt("Invalid TelephoneNumberRange count {}", entry.count));
1660 }
1661
1662 range_items.emplace_back(std::move(entry));
1663 }
1664 list.end_cons();
1665 outer.verify_end();
1666
1667 if(range_items.empty()) {
1668 throw Decoding_Error("TelephoneNumberRange is empty");
1669 }
1670 } else if(type_tag == TelephoneNumber) {
1671 m_type = TelephoneNumber;
1672 ASN1_String one_string;
1673 BER_Decoder(obj, ber.limits()).decode(one_string).verify_end();
1674 if(!is_valid_telephone_number(one_string)) {
1675 throw Decoding_Error(fmt("Invalid TelephoneNumber {}", one_string.value()));
1676 }
1677 m_data = std::move(one_string);
1678 } else {
1679 throw Decoding_Error(fmt("Unexpected TNEntry type code {}", type_tag));
1680 };
1681}
1682
1683std::vector<uint8_t> TNAuthList::encode_inner() const {
1684 throw Not_Implemented("TNAuthList extension serialization is not supported");
1685}
1686
1687void TNAuthList::decode_inner(const std::vector<uint8_t>& in) {
1688 /* RFC 8226 Section 9 - TNAuthorizationList ::= SEQUENCE SIZE (1..MAX) OF TNEntry */
1690 if(m_tn_entries.empty()) {
1691 throw Decoding_Error("TNAuthorizationList is empty");
1692 }
1693}
1694
1697 return std::get<ASN1_String>(m_data).value();
1698}
1699
1702 return std::get<RangeContainer>(m_data);
1703}
1704
1705const std::string& TNAuthList::Entry::telephone_number() const {
1707 return std::get<ASN1_String>(m_data).value();
1708}
1709
1710std::vector<uint8_t> IPAddressBlocks::encode_inner() const {
1711 std::vector<uint8_t> output;
1712 DER_Encoder(output).start_sequence().encode_list(m_ip_addr_blocks).end_cons();
1713 return output;
1714}
1715
1716void IPAddressBlocks::decode_inner(const std::vector<uint8_t>& in) {
1717 /* RFC 3779 Section 2.2.3.1 - IPAddrBlocks ::= SEQUENCE OF IPAddressFamily */
1719 sort_and_merge();
1720}
1721
1723 into.start_sequence();
1724
1725 std::vector<uint8_t> afam = {get_byte<0>(m_afi), get_byte<1>(m_afi)};
1726
1727 if(m_safi.has_value()) {
1728 afam.push_back(m_safi.value());
1729 }
1730
1732
1733 if(std::holds_alternative<IPAddressChoice<Version::IPv4>>(m_ip_addr_choice)) {
1734 into.encode(std::get<IPAddressChoice<Version::IPv4>>(m_ip_addr_choice));
1735 } else {
1736 into.encode(std::get<IPAddressChoice<Version::IPv6>>(m_ip_addr_choice));
1737 }
1738 into.end_cons();
1739}
1740
1742 const ASN1_Type next_tag = from.peek_next_object().type_tag();
1743 if(next_tag != ASN1_Type::Sequence) {
1744 throw Decoding_Error(fmt("Unexpected type for IPAddressFamily {}", static_cast<uint32_t>(next_tag)));
1745 }
1746
1747 BER_Decoder seq_dec = from.start_sequence();
1748
1749 std::vector<uint8_t> addr_family;
1750 seq_dec.decode(addr_family, ASN1_Type::OctetString);
1751 const size_t addr_family_length = addr_family.size();
1752
1753 if(addr_family_length != 2 && addr_family_length != 3) {
1754 throw Decoding_Error("(S)AFI can only contain 2 or 3 bytes");
1755 }
1756
1757 m_afi = (addr_family[0] << 8) | addr_family[1];
1758
1759 if(addr_family_length == 3) {
1760 m_safi = addr_family[2];
1761 }
1762
1763 if(m_afi == 1) {
1765 seq_dec.decode(addr_choice);
1766 m_ip_addr_choice = addr_choice;
1767 } else if(m_afi == 2) {
1769 seq_dec.decode(addr_choice);
1770 m_ip_addr_choice = addr_choice;
1771 } else {
1772 throw Decoding_Error("Only AFI IPv4 and IPv6 are supported.");
1773 }
1774
1775 seq_dec.end_cons();
1776}
1777
1778void IPAddressBlocks::sort_and_merge() {
1779 // Sort IPAddressFamilies by afi/safi values
1780 //
1781 // see: https://www.rfc-editor.org/rfc/rfc3779.html#section-2.2.3.3
1782 //
1783 // v4 families are ordered before v6 families (i.e. they are sorted by afis, primarily),
1784 // families with no safis are ordered before families with safis
1785 //
1786 // families with the same afi/safi combination are then merged
1787
1788 // std::map is ordered, so using a pair (afi, optional(safi)) here works - std::nullopt is sorted before any actual values
1789 std::map<std::pair<uint16_t, std::optional<uint8_t>>, std::vector<IPAddressFamily>> afam_map;
1790 for(const IPAddressFamily& block : m_ip_addr_blocks) {
1791 auto key = std::make_pair(block.afi(), block.safi());
1792 std::vector<IPAddressFamily>& fams = afam_map[key];
1793 fams.push_back(block);
1794 }
1795
1796 std::vector<IPAddressFamily> merged_blocks;
1797 size_t v4_count = 0;
1798 size_t v6_count = 0;
1799 for(auto& it : afam_map) {
1800 // fams consists of families with the same afi/safi combination
1801 std::vector<IPAddressFamily>& fams = it.second;
1802 // since at least 1 block has to belong to a afi/safi combination for it to appear in the map,
1803 // fams cannot be empty
1804 BOTAN_ASSERT_NOMSG(!fams.empty());
1805
1806 // fams[0] has to have the same choice type as the fams in the same bucket
1807 if(std::holds_alternative<IPAddressChoice<Version::IPv4>>(fams[0].addr_choice())) {
1808 merged_blocks.push_back(merge<Version::IPv4>(fams));
1809 v4_count++;
1810 } else {
1811 merged_blocks.push_back(merge<Version::IPv6>(fams));
1812 v6_count++;
1813 }
1814 }
1815 BOTAN_ASSERT_NOMSG(v4_count + v6_count == merged_blocks.size());
1816 m_ip_addr_blocks = merged_blocks;
1817 m_v4_count = v4_count;
1818 m_v6_count = v6_count;
1819}
1820
1821template <IPAddressBlocks::Version V>
1822IPAddressBlocks::IPAddressFamily IPAddressBlocks::merge(std::vector<IPAddressFamily>& blocks) {
1823 // Merge IPAddressFamilies that have the same afi/safi combination
1824 //
1825 // see: https://www.rfc-editor.org/rfc/rfc3779.html#section-2.2.3.3
1826
1827 BOTAN_ASSERT(!blocks.empty(), "Cannot merge an empty set of IP address blocks into a single family");
1828
1829 // nothing to merge
1830 if(blocks.size() == 1) {
1831 return blocks[0];
1832 }
1833
1834 bool all_inherit = true;
1835 bool none_inherit = true;
1836 for(const IPAddressFamily& block : blocks) {
1837 const IPAddressChoice<V> choice = std::get<IPAddressChoice<V>>(block.addr_choice());
1838 all_inherit = !choice.ranges().has_value() && all_inherit; // all the blocks have the 'inherit' value
1839 none_inherit = choice.ranges().has_value() && none_inherit;
1840 }
1841
1842 // they are all 'inherit', short-circuit using default constructor for nullopt
1843 if(all_inherit) {
1844 return IPAddressFamily(IPAddressChoice<V>(), blocks[0].safi());
1845 }
1846
1847 // some are inherit, and some have values - no sensible way to merge them
1848 if(!all_inherit && !none_inherit) {
1849 throw Decoding_Error("Invalid IPAddressBlocks: Only one of 'inherit' or 'do not inherit' is allowed per family");
1850 }
1851
1852 std::vector<IPAddressOrRange<V>> merged_ranges;
1853 for(const IPAddressFamily& block : blocks) {
1854 const IPAddressChoice<V> choice = std::get<IPAddressChoice<V>>(block.addr_choice());
1855 const std::vector<IPAddressOrRange<V>> ranges = choice.ranges().value();
1856 for(const IPAddressOrRange<V>& r : ranges) {
1857 merged_ranges.push_back(r);
1858 }
1859 }
1860
1861 // we have extracted all the ranges, and now rely on the constructor of IPAddressChoice to merge them
1862 IPAddressChoice<V> choice(merged_ranges);
1863 IPAddressFamily fam(choice, blocks[0].safi());
1864 return fam;
1865}
1866
1867namespace {
1868
1869constexpr auto IPv4 = IPAddressBlocks::Version::IPv4;
1870constexpr auto IPv6 = IPAddressBlocks::Version::IPv6;
1871
1872template <IPAddressBlocks::Version V>
1873using IPRangeVec = std::vector<IPAddressBlocks::IPAddressOrRange<V>>;
1874
1875// (S)AFI -> (needs_check, ptr to IPRangeVec)
1876// the pointer can be null, in which case the boolean will be false, as such the pointer's value will never be looked at
1877template <IPAddressBlocks::Version V>
1878using IPValidationMap = std::map<uint32_t, std::pair<bool, const IPRangeVec<V>*>>;
1879
1880template <typename T>
1881std::optional<std::vector<T>> sort_and_merge_ranges(std::optional<std::span<const T>> ranges) {
1882 // Sort and merge overlapping/adjacent IPAddressOrRange or ASIdOrRange objects.
1883 // 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
1884 // This implementation uses only min-max ranges internally, so sorting by the prefix length is not necessary / impossible here.
1885
1886 if(!ranges.has_value()) {
1887 return std::nullopt;
1888 }
1889
1890 std::vector<T> sorted(ranges.value().begin(), ranges.value().end());
1891
1892 if(sorted.empty()) {
1893 return sorted;
1894 }
1895
1896 // sort by the min value
1897 std::sort(sorted.begin(), sorted.end(), [](T& a, T& b) { return a.min() < b.min(); });
1898
1899 // Single-pass merge: extend the last merged range or start a new one
1900 std::vector<T> merged;
1901 merged.reserve(sorted.size());
1902 merged.push_back(sorted[0]);
1903
1904 for(size_t i = 1; i < sorted.size(); ++i) {
1905 auto& back = merged.back();
1906 // they either overlap or are adjacent
1907 if(sorted[i].min() <= back.max() || sorted[i].min() == (back.max() + 1)) {
1908 back = T(back.min(), std::max(back.max(), sorted[i].max()));
1909 } else {
1910 merged.push_back(sorted[i]);
1911 }
1912 }
1913
1914 return merged;
1915}
1916
1917template <typename T>
1918bool validate_subject_in_issuer(std::span<const T> subject, std::span<const T> issuer) {
1919 // ensures that the subject ranges are enclosed by the issuer ranges
1920 // both vectors are already sorted, so we can do this in O(n+m)
1921
1922 // the issuer has 0 ranges to validate against, so this can only work if the subject also has none
1923 if(issuer.empty()) {
1924 return subject.empty();
1925 }
1926 for(auto subj = subject.begin(), issu = issuer.begin(); subj != subject.end();) {
1927 // the issuer range is smaller than the subject range, step to the next issuer range to check next round
1928 if(subj->min() > issu->max()) {
1929 issu++;
1930 // we have run out of issuer ranges, but still have subject ranges left to validate
1931 if(issu == issuer.end() && subj != subject.end()) {
1932 return false;
1933 }
1934 } else {
1935 // the subject is outside of the closest issuer range on the left (min) side
1936 if(subj->min() < issu->min()) {
1937 return false;
1938 }
1939 // the subject is outside of the closest issuer range on the right (max) side
1940 if(subj->max() > issu->max()) {
1941 return false;
1942 }
1943 // this range is contained within the issuer, advance to the next subject range
1944 subj++;
1945 }
1946 }
1947 return true;
1948}
1949
1950template <IPAddressBlocks::Version V>
1951void populate_validation_map(uint32_t afam,
1953 IPValidationMap<V>& map) {
1954 const std::optional<IPRangeVec<V>>& ranges = std::get<IPAddressBlocks::IPAddressChoice<V>>(choice).ranges();
1955 const bool has_value = ranges.has_value();
1956 const IPRangeVec<V>* value = has_value ? &ranges.value() : nullptr;
1957 map.emplace(afam, std::make_pair(has_value, std::move(value)));
1958}
1959
1960std::pair<IPValidationMap<IPv4>, IPValidationMap<IPv6>> create_validation_map(
1961 const std::vector<IPAddressBlocks::IPAddressFamily>& addr_blocks) {
1962 IPValidationMap<IPv4> v4_map;
1963 IPValidationMap<IPv6> v6_map;
1964
1965 for(const IPAddressBlocks::IPAddressFamily& block : addr_blocks) {
1966 uint32_t afam = block.afi();
1967 if(block.safi().has_value()) {
1968 afam = static_cast<uint32_t>(afam << 8) | block.safi().value();
1969 }
1970
1971 const IPAddressBlocks::IPAddressFamily::AddrChoice& a_choice = block.addr_choice();
1972 if(std::holds_alternative<IPAddressBlocks::IPAddressChoice<IPv4>>(a_choice)) {
1973 populate_validation_map(afam, a_choice, v4_map);
1974 } else {
1975 populate_validation_map(afam, a_choice, v6_map);
1976 }
1977 }
1978
1979 return std::make_pair(v4_map, v6_map);
1980}
1981
1982} // namespace
1983
1984template <IPAddressBlocks::Version V>
1986 std::optional<std::span<const IPAddressBlocks::IPAddressOrRange<V>>> ranges) {
1987 // NOLINTNEXTLINE(*-prefer-member-initializer)
1988 m_ip_addr_ranges = sort_and_merge_ranges<IPAddressOrRange<V>>(ranges);
1989}
1990
1991template <IPAddressBlocks::Version V>
1993 if(m_ip_addr_ranges.has_value()) {
1994 into.start_sequence().encode_list(m_ip_addr_ranges.value()).end_cons();
1995 } else {
1996 into.encode_null();
1997 }
1998}
1999
2000template <IPAddressBlocks::Version V>
2002 const ASN1_Type next_tag = from.peek_next_object().type_tag();
2003
2004 if(next_tag == ASN1_Type::Null) {
2005 from.decode_null();
2006 m_ip_addr_ranges = std::nullopt;
2007 } else if(next_tag == ASN1_Type::Sequence) {
2008 std::vector<IPAddressOrRange<V>> ip_ranges;
2009 from.decode_list(ip_ranges);
2010 m_ip_addr_ranges = sort_and_merge_ranges<IPAddressOrRange<V>>(ip_ranges);
2011 } else {
2012 throw Decoding_Error(fmt("Unexpected type for IPAddressChoice {}", static_cast<uint32_t>(next_tag)));
2013 }
2014}
2015
2016template <IPAddressBlocks::Version V>
2018 // Compress IPAddressOrRange as much as possible
2019 // 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
2020 //
2021 // If possible encode as a prefix x.x.x.x/x, else encode as a range of min-max.
2022 // Single addresses are encoded as is (technically a /32 or /128 prefix).
2023 //
2024 // A range can be encoded as a prefix if the lowest n bits of the min address are 0
2025 // and the highest n bits of the max address are 1, or in other words, contiguous sequences of 0s and 1s are omitted.
2026 // To make reconstruction possible, an 'unused' octet is included at the start, since in the case of e.g. /25 only
2027 // the highest bit of the last octet is actually meaningful.
2028 //
2029 // If encoding requires a range, the individual elements can still be compressed using the above method,
2030 // but the number of used bits varies between them.
2031
2032 const size_t version_octets = static_cast<size_t>(V);
2033
2034 std::array<uint8_t, version_octets> min = m_min.value();
2035 std::array<uint8_t, version_octets> max = m_max.value();
2036
2037 uint8_t zeros = 0;
2038 uint8_t ones = 0;
2039
2040 bool zeros_done = false;
2041 bool ones_done = false;
2042
2043 // count contiguous 0s/1s from the right of the min/max addresses
2044 for(size_t i = version_octets; i > 0; i--) {
2045 if(!zeros_done) {
2046 const uint8_t local_zeros = static_cast<uint8_t>(std::countr_zero(min[i - 1]));
2047 zeros += local_zeros;
2048 zeros_done = (local_zeros != 8);
2049 }
2050
2051 if(!ones_done) {
2052 const uint8_t local_ones = static_cast<uint8_t>(std::countr_one(max[i - 1]));
2053 ones += local_ones;
2054 ones_done = (local_ones != 8);
2055 }
2056
2057 if(zeros_done && ones_done) {
2058 break;
2059 }
2060 }
2061
2062 // the part we want to compress
2063 const uint8_t host = std::min(zeros, ones);
2064
2065 // these we can outright drop
2066 const uint8_t discarded_octets = host / 8;
2067 // in a partially used octet
2068 const uint8_t unused_bits = host % 8;
2069
2070 bool octets_match = true;
2071 bool used_bits_match = true;
2072
2073 // we have octets to check
2074 if(discarded_octets < version_octets) {
2075 // check all but the last octet
2076 for(size_t i = 0; i < static_cast<uint8_t>(version_octets - discarded_octets - 1); i++) {
2077 if(min[i] != max[i]) {
2078 octets_match = false;
2079 break;
2080 }
2081 }
2082 // check the last significant octet if we have matched so far
2083 if(octets_match) {
2084 const uint8_t shifted_min = (min[version_octets - 1 - discarded_octets] >> unused_bits);
2085 const uint8_t shifted_max = (max[version_octets - 1 - discarded_octets] >> unused_bits);
2086 used_bits_match = (shifted_min == shifted_max);
2087 }
2088 }
2089
2090 // both the full octets and the partially used one match
2091 if(octets_match && used_bits_match) {
2092 // at this point the range can be encoded as a prefix
2093 into.encode_bitstring(std::span{min}.first(version_octets - discarded_octets), unused_bits);
2094 } else {
2095 const uint8_t discarded_octets_min = zeros / 8;
2096 const uint8_t unused_bits_min = zeros % 8;
2097
2098 const uint8_t discarded_octets_max = ones / 8;
2099 const uint8_t unused_bits_max = ones % 8;
2100
2101 // compress the max address by setting unused bits to 0, for the min address these are already 0
2102 if(unused_bits_max != 0) {
2103 BOTAN_ASSERT_NOMSG(discarded_octets_max < version_octets);
2104 max[version_octets - 1 - discarded_octets_max] >>= unused_bits_max;
2105 max[version_octets - 1 - discarded_octets_max] <<= unused_bits_max;
2106 }
2107
2108 into.start_sequence()
2109 .encode_bitstring(std::span{min}.first(version_octets - discarded_octets_min), unused_bits_min)
2110 .encode_bitstring(std::span{max}.first(version_octets - discarded_octets_max), unused_bits_max)
2111 .end_cons();
2112 }
2113}
2114
2115template <IPAddressBlocks::Version V>
2117 const ASN1_Type next_tag = from.peek_next_object().type_tag();
2118
2119 // this can either be a prefix or a single address
2120 if(next_tag == ASN1_Type::BitString) {
2121 // construct a min and a max address from the prefix
2122
2123 ASN1_BitString prefix;
2124 from.decode_bitstring(prefix);
2125
2126 // min address gets filled with 0's
2127 m_min = decode_single_address(prefix, true);
2128 // max address with 1's
2129 m_max = decode_single_address(prefix, false);
2130 } else if(next_tag == ASN1_Type::Sequence) {
2131 // this is a range
2132
2133 ASN1_BitString addr_min;
2134 ASN1_BitString addr_max;
2135
2136 from.start_sequence().decode_bitstring(addr_min).decode_bitstring(addr_max).end_cons();
2137
2138 m_min = decode_single_address(addr_min, true);
2139 m_max = decode_single_address(addr_max, false);
2140
2141 if(m_min > m_max) {
2142 throw Decoding_Error("IP address ranges must be sorted.");
2143 }
2144 } else {
2145 throw Decoding_Error(fmt("Unexpected type for IPAddressOrRange {}", static_cast<uint32_t>(next_tag)));
2146 }
2147}
2148
2149template <IPAddressBlocks::Version V>
2150IPAddressBlocks::IPAddress<V> IPAddressBlocks::IPAddressOrRange<V>::decode_single_address(const ASN1_BitString& decoded,
2151 bool min) {
2152 const size_t version_octets = static_cast<size_t>(V);
2153
2154 // decode a single address according to https://datatracker.ietf.org/doc/html/rfc3779#section-2.1.1 and following
2155
2156 if(decoded.bytes().size() > version_octets) {
2157 throw Decoding_Error(fmt("IP address range entries must have a length between 0 and {} bytes.", version_octets));
2158 }
2159
2160 const uint8_t unused = static_cast<uint8_t>(decoded.unused_bits());
2161 const uint8_t discarded_octets = version_octets - static_cast<uint8_t>(decoded.bytes().size());
2162
2163 std::vector<uint8_t> address(decoded.bytes().begin(), decoded.bytes().end());
2164
2165 if(address.empty() && unused != 0) {
2166 throw Decoding_Error("IP address range entry specified unused bits, but did not provide any octets.");
2167 }
2168
2169 // pad to version length with 0's for min addresses, 255's (0xff) for max addresses
2170 const uint8_t fill_discarded = min ? 0 : 0xff;
2171 for(size_t i = 0; i < discarded_octets; i++) {
2172 address.push_back(fill_discarded);
2173 }
2174
2175 // for min addresses they should already be 0, but we set them to zero regardless
2176 // for max addresses this turns the unused bits to 1
2177 for(size_t i = 0; i < unused; i++) {
2178 if(min) {
2179 address[version_octets - 1 - discarded_octets] &= ~(1 << i);
2180 } else {
2181 address[version_octets - 1 - discarded_octets] |= (1 << i);
2182 }
2183 }
2184
2185 return IPAddressBlocks::IPAddress<V>(address);
2186}
2187
2188template <IPAddressBlocks::Version V>
2189IPAddressBlocks::IPAddress<V>::IPAddress(std::span<const uint8_t> v) {
2190 if(v.size() != Length) {
2191 throw Decoding_Error("number of bytes does not match IP version used");
2192 }
2193
2194 for(size_t i = 0; i < Length; i++) {
2195 m_value[i] = v[i];
2196 }
2197}
2198
2200 const std::optional<X509_Certificate>& /* unused */,
2201 const std::vector<X509_Certificate>& cert_path,
2202 std::vector<std::set<Certificate_Status_Code>>& cert_status,
2203 size_t pos) const {
2204 // maps in the form of (s)afi -> (needs_checking, ranges)
2205 auto [v4_needs_check, v6_needs_check] = create_validation_map(m_ip_addr_blocks);
2206
2207 if(pos == cert_path.size() - 1) {
2208 // checks if any range / family has 'inherit' as a value somewhere, not allowed for the root cert
2209 auto validate_root_cert_ext = [&](const auto& map) {
2210 // check if any range has a value of 'false', indicating 'inherit'
2211 return std::any_of(map.begin(), map.end(), [&](const auto& it) {
2212 const auto& [_1, validation_info] = it;
2213 const auto& [needs_checking, _2] = validation_info;
2214 return !needs_checking;
2215 });
2216 };
2217 if(validate_root_cert_ext(v4_needs_check) || validate_root_cert_ext(v6_needs_check)) {
2218 cert_status.at(pos).insert(Certificate_Status_Code::IPADDR_BLOCKS_ERROR);
2219 }
2220 return;
2221 }
2222
2223 // traverse the chain until we find a cert with concrete values for the extension (so not 'inherit')
2224 for(auto cert_path_it = cert_path.begin() + pos + 1; cert_path_it != cert_path.end(); cert_path_it++) {
2225 const IPAddressBlocks* const parent_ip = cert_path_it->v3_extensions().get_extension_object_as<IPAddressBlocks>();
2226 // extension not present for parent
2227 if(parent_ip == nullptr) {
2228 cert_status.at(pos).insert(Certificate_Status_Code::IPADDR_BLOCKS_ERROR);
2229 return;
2230 }
2231 auto [issuer_v4, issuer_v6] = create_validation_map(parent_ip->addr_blocks());
2232
2233 auto validate_against_issuer = [&](auto& subject_map, const auto& issuer_map) {
2234 for(auto map_it = subject_map.begin(); map_it != subject_map.end(); map_it++) {
2235 auto& [afam, validation_info] = *map_it;
2236
2237 // the issuer does not have this combination of afi/safi
2238 if(issuer_map.count(afam) == 0) {
2239 cert_status.at(pos).insert(Certificate_Status_Code::IPADDR_BLOCKS_ERROR);
2240 return false;
2241 }
2242
2243 auto& [needs_check, subject_value] = validation_info;
2244 const auto& [issuer_has_value, issuer_value] = issuer_map.at(afam);
2245 BOTAN_ASSERT_NOMSG(!needs_check || subject_value != nullptr);
2246 BOTAN_ASSERT_NOMSG(!issuer_has_value || issuer_value != nullptr);
2247
2248 // we still need to check this range and the issuer has an actual value for it (so not 'inherit')
2249 if(needs_check && issuer_has_value) {
2250 if(!validate_subject_in_issuer(std::span(*subject_value), std::span(*issuer_value))) {
2251 cert_status.at(pos).insert(Certificate_Status_Code::IPADDR_BLOCKS_ERROR);
2252 return false;
2253 }
2254 needs_check = false;
2255 }
2256 }
2257 return true;
2258 };
2259
2260 if(!validate_against_issuer(v4_needs_check, issuer_v4) || !validate_against_issuer(v6_needs_check, issuer_v6)) {
2261 return;
2262 }
2263
2264 auto validate_no_checks_left = [&](const auto& map) {
2265 // check if all ranges have been checked, either by comparing their ranges if they have any,
2266 // or if they are inherit, their parent(s) will be validated later
2267 return std::all_of(map.begin(), map.end(), [&](const auto& it) {
2268 const auto& [_1, validation_info] = it;
2269 const auto& [needs_checking, _2] = validation_info;
2270 return !needs_checking;
2271 });
2272 };
2273
2274 if(validate_no_checks_left(v4_needs_check) && validate_no_checks_left(v6_needs_check)) {
2275 // we've validated what we need to and can stop traversing the cert chain
2276 return;
2277 }
2278 }
2279}
2280
2287
2288std::vector<uint8_t> ASBlocks::encode_inner() const {
2289 std::vector<uint8_t> output;
2290 DER_Encoder(output).encode(m_as_identifiers);
2291 return output;
2292}
2293
2294void ASBlocks::decode_inner(const std::vector<uint8_t>& in) {
2295 /* RFC 3779 Section 3.2.3.1 - ASIdentifiers ::= SEQUENCE { ... } */
2296 BER_Decoder(in, BER_Decoder::Limits::DER()).decode(m_as_identifiers).verify_end();
2297}
2298
2299ASBlocks::ASIdentifierChoice ASBlocks::add_new(const std::optional<ASIdentifierChoice>& old, asnum_t min, asnum_t max) {
2300 std::vector<ASIdOrRange> range;
2301 if(!old.has_value() || !old.value().ranges().has_value()) {
2302 range = {ASIdOrRange(min, max)};
2303 } else {
2304 range = old.value().ranges().value();
2305 range.push_back(ASIdOrRange(min, max));
2306 }
2307 return ASIdentifierChoice(range);
2308}
2309
2311 into.start_sequence();
2312
2313 if(!m_asnum.has_value() && !m_rdi.has_value()) {
2314 throw Encoding_Error("One of asnum, rdi must be present");
2315 }
2316
2317 if(m_asnum.has_value()) {
2318 into.start_explicit(0);
2319 into.encode(m_asnum.value());
2320 into.end_explicit();
2321 }
2322
2323 if(m_rdi.has_value()) {
2324 into.start_explicit(1);
2325 into.encode(m_rdi.value());
2326 into.end_explicit();
2327 }
2328
2329 into.end_cons();
2330}
2331
2333 const ASN1_Type next_tag = from.peek_next_object().type_tag();
2334 if(next_tag != ASN1_Type::Sequence) {
2335 throw Decoding_Error(fmt("Unexpected type for ASIdentifiers {}", static_cast<uint32_t>(next_tag)));
2336 }
2337
2338 BER_Decoder seq_dec = from.start_sequence();
2339
2340 const BER_Object elem_obj = seq_dec.get_next_object();
2341 const uint32_t elem_type_tag = static_cast<uint32_t>(elem_obj.type_tag());
2342
2343 // asnum, potentially followed by an rdi
2344 if(elem_type_tag == 0) {
2345 BER_Decoder as_obj_ber = BER_Decoder(elem_obj, seq_dec.limits());
2347 as_obj_ber.decode(asnum).verify_end();
2348 m_asnum = asnum;
2349
2350 const BER_Object rdi_obj = seq_dec.get_next_object();
2351 const ASN1_Type rdi_type_tag = rdi_obj.type_tag();
2352 if(static_cast<uint32_t>(rdi_type_tag) == 1) {
2353 BER_Decoder rdi_obj_ber = BER_Decoder(rdi_obj, seq_dec.limits());
2355 rdi_obj_ber.decode(rdi).verify_end();
2356 m_rdi = rdi;
2357 } else if(rdi_type_tag != ASN1_Type::NoObject) {
2358 throw Decoding_Error(fmt("Unexpected type for ASIdentifiers rdi: {}", static_cast<uint32_t>(rdi_type_tag)));
2359 }
2360 }
2361
2362 // just an rdi
2363 if(elem_type_tag == 1) {
2364 BER_Decoder rdi_obj_ber = BER_Decoder(elem_obj, seq_dec.limits());
2366 rdi_obj_ber.decode(rdi).verify_end();
2367 m_rdi = rdi;
2368 const BER_Object end = seq_dec.get_next_object();
2369 const ASN1_Type end_type_tag = end.type_tag();
2370 if(end_type_tag != ASN1_Type::NoObject) {
2371 throw Decoding_Error(
2372 fmt("Unexpected element with type {} in ASIdentifiers", static_cast<uint32_t>(end_type_tag)));
2373 }
2374 }
2375
2376 seq_dec.end_cons();
2377
2378 if(!m_asnum.has_value() && !m_rdi.has_value()) {
2379 throw Decoding_Error("Invalid encoding for ASIdentifiers");
2380 }
2381}
2382
2384 if(m_as_ranges.has_value()) {
2385 into.start_sequence().encode_list(m_as_ranges.value()).end_cons();
2386 } else {
2387 into.encode_null();
2388 }
2389}
2390
2391ASBlocks::ASIdentifierChoice::ASIdentifierChoice(const std::optional<std::vector<ASIdOrRange>>& ranges) {
2392 m_as_ranges = sort_and_merge_ranges<ASIdOrRange>(ranges);
2393}
2394
2396 const ASN1_Type next_tag = from.peek_next_object().type_tag();
2397
2398 if(next_tag == ASN1_Type::Null) {
2399 from.decode_null();
2400 m_as_ranges = std::nullopt;
2401 } else if(next_tag == ASN1_Type::Sequence) {
2402 std::vector<ASIdOrRange> as_ranges;
2403 from.decode_list(as_ranges);
2404
2405 m_as_ranges = sort_and_merge_ranges<ASIdOrRange>(as_ranges);
2406 } else {
2407 throw Decoding_Error(fmt("Unexpected type for ASIdentifierChoice {}", static_cast<uint32_t>(next_tag)));
2408 }
2409}
2410
2412 if(m_min == m_max) {
2413 into.encode(static_cast<size_t>(m_min));
2414 } else {
2415 if(m_min >= m_max) {
2416 throw Encoding_Error("AS range numbers must be sorted");
2417 }
2418 into.start_sequence().encode(static_cast<size_t>(m_min)).encode(static_cast<size_t>(m_max)).end_cons();
2419 }
2420}
2421
2423 const ASN1_Type next_tag = from.peek_next_object().type_tag();
2424
2425 size_t min = 0;
2426 size_t max = 0;
2427
2428 if(next_tag == ASN1_Type::Integer) {
2429 from.decode(min);
2431 m_max = m_min;
2432 } else if(next_tag == ASN1_Type::Sequence) {
2436 if(m_min >= m_max) {
2437 throw Decoding_Error("ASIdOrRange has min greater than max");
2438 }
2439 } else {
2440 throw Decoding_Error(fmt("Unexpected type for ASIdOrRange {}", static_cast<uint32_t>(next_tag)));
2441 }
2442}
2443
2444void ASBlocks::validate(const X509_Certificate& /* unused */,
2445 const std::optional<X509_Certificate>& /* unused */,
2446 const std::vector<X509_Certificate>& cert_path,
2447 std::vector<std::set<Certificate_Status_Code>>& cert_status,
2448 size_t pos) const {
2449 // the extension may not contain asnums or rdis, but one of them is always present
2450 const bool asnum_present = m_as_identifiers.asnum().has_value();
2451 const bool rdi_present = m_as_identifiers.rdi().has_value();
2452
2453 if(!asnum_present && !rdi_present) {
2454 // Invalid, should have been caught during decoding
2455 cert_status.at(pos).insert(Certificate_Status_Code::AS_BLOCKS_ERROR);
2456 return;
2457 }
2458
2459 bool asnum_needs_check = asnum_present ? m_as_identifiers.asnum().value().ranges().has_value() : false;
2460 bool rdi_needs_check = rdi_present ? m_as_identifiers.rdi().value().ranges().has_value() : false;
2461
2462 // we are at the (trusted) root cert, there is no parent to verify against
2463 if(pos == cert_path.size() - 1) {
2464 // asnum / rdi is present, but has 'inherit' value, but there is nothing to inherit from
2465 if((asnum_present && !asnum_needs_check) || (rdi_present && !rdi_needs_check)) {
2466 cert_status.at(pos).insert(Certificate_Status_Code::AS_BLOCKS_ERROR);
2467 }
2468 return;
2469 }
2470
2471 // traverse the chain until we find a cert with concrete values for the extension (so not 'inherit')
2472 for(auto it = cert_path.begin() + pos + 1; it != cert_path.end(); it++) {
2473 const ASBlocks* const parent_as = it->v3_extensions().get_extension_object_as<ASBlocks>();
2474 // no extension at all or no asnums or no rdis (if needed)
2475 if(parent_as == nullptr || (asnum_present && !parent_as->as_identifiers().asnum().has_value()) ||
2476 (rdi_present && !parent_as->as_identifiers().rdi().has_value())) {
2477 cert_status.at(pos).insert(Certificate_Status_Code::AS_BLOCKS_ERROR);
2478 return;
2479 }
2480 const auto as_identifiers = parent_as->as_identifiers();
2481
2482 // only something to validate if the subject does not have 'inherit' as a value
2483 if(asnum_needs_check && as_identifiers.asnum().value().ranges().has_value()) {
2484 const std::vector<ASBlocks::ASIdOrRange>& subject_asnums = m_as_identifiers.asnum()->ranges().value();
2485 const std::vector<ASBlocks::ASIdOrRange>& issuer_asnums = as_identifiers.asnum()->ranges().value();
2486
2487 if(!validate_subject_in_issuer<ASBlocks::ASIdOrRange>(subject_asnums, issuer_asnums)) {
2488 cert_status.at(pos).insert(Certificate_Status_Code::AS_BLOCKS_ERROR);
2489 return;
2490 }
2491 // successfully validated the asnums, but we may need to step further for rdis
2492 asnum_needs_check = false;
2493 }
2494
2495 if(rdi_needs_check && as_identifiers.rdi().value().ranges().has_value()) {
2496 const std::vector<ASBlocks::ASIdOrRange>& subject_rdis = m_as_identifiers.rdi()->ranges().value();
2497 const std::vector<ASBlocks::ASIdOrRange>& issuer_rdis = as_identifiers.rdi()->ranges().value();
2498
2499 if(!validate_subject_in_issuer<ASBlocks::ASIdOrRange>(subject_rdis, issuer_rdis)) {
2500 cert_status.at(pos).insert(Certificate_Status_Code::AS_BLOCKS_ERROR);
2501 return;
2502 }
2503 // successfully validated the rdis, but we may need to step further for asnums
2504 rdi_needs_check = false;
2505 }
2506
2507 if(!asnum_needs_check && !rdi_needs_check) {
2508 // we've validated what we need to and can stop traversing the cert chain
2509 return;
2510 }
2511 }
2512}
2513
2515 const std::optional<X509_Certificate>& /*issuer*/,
2516 const std::vector<X509_Certificate>& /*cert_path*/,
2517 std::vector<std::set<Certificate_Status_Code>>& cert_status,
2518 size_t pos) const {
2519 /*
2520 * RFC 6960 is not particularly explicit about when id-pkix-ocsp-nocheck can
2521 * or cannot be included in a certificate, but reasonably we should require
2522 * that id-pkix-ocsp-nocheck is only included for certificates that are marked
2523 * as OCSP responders. This checks for compatible key usage and also the OCSP
2524 * signer extended key usage.
2525 */
2527 cert_status.at(pos).insert(Certificate_Status_Code::INVALID_OCSP_NOCHECK);
2528 }
2529}
2530
2531std::vector<uint8_t> OCSP_NoCheck::encode_inner() const {
2532 return {0x05, 0x00}; // NULL
2533}
2534
2535void OCSP_NoCheck::decode_inner(const std::vector<uint8_t>& buf) {
2536 /* RFC 6960 Section 4.2.2.2.1 - id-pkix-ocsp-nocheck (value SHALL be NULL) */
2537 BER_Decoder(buf, BER_Decoder::Limits::DER()).decode_null().verify_end();
2538}
2539
2540std::vector<uint8_t> NoRevocationAvailable::encode_inner() const {
2541 return {0x05, 0x00}; // NULL
2542}
2543
2544void NoRevocationAvailable::decode_inner(const std::vector<uint8_t>& buf) {
2545 // RFC 9608 Section 2, it's just a NULL
2546 BER_Decoder(buf, BER_Decoder::Limits::DER()).decode_null().verify_end();
2547}
2548
2550 const std::optional<X509_Certificate>& /*issuer*/,
2551 const std::vector<X509_Certificate>& /*cert_path*/,
2552 std::vector<std::set<Certificate_Status_Code>>& cert_status,
2553 size_t pos) const {
2554 // RFC 9608 Section 2:
2555 // This extension MUST NOT be present in CA public key certificates.
2556 //
2557 // RFC 9608 Section 3:
2558 // Certificates that include the noRevAvail extension MUST NOT include
2559 // certificate extensions that point to CRL repositories or provide
2560 // locations of OCSP responders.
2561 //
2562 // Additionally (and unusually) the requirements of RFC 9608 Section 3
2563 // are not just on issuing parties but also on verifiers:
2564 //
2565 // If any of the above are violated in a certificate, then the relying
2566 // party MUST consider the certificate invalid.
2567
2568 const Extensions& exts = subject.v3_extensions();
2569
2570 if(const auto* bc = exts.get_extension_object_as<Basic_Constraints>(); bc != nullptr && bc->is_ca()) {
2571 // RFC 9608 Section 3:
2572 // The certificate MUST NOT also include the basic constraints
2573 // certificate extension with the cA BOOLEAN set to TRUE
2574 cert_status.at(pos).insert(Certificate_Status_Code::NO_REV_AVAIL_INVALID_USE);
2575 }
2576
2577 // RFC 9608 Section 3:
2578 // The certificate MUST NOT also include the CRL Distribution Points
2579 // certificate extension
2581 cert_status.at(pos).insert(Certificate_Status_Code::NO_REV_AVAIL_INVALID_USE);
2582 }
2583
2584 // RFC 9608 Section 3:
2585 // The certificate MUST NOT also include the Freshest CRL certificate
2586 // extension
2587 if(exts.extension_set(OID({2, 5, 29, 46}))) {
2588 cert_status.at(pos).insert(Certificate_Status_Code::NO_REV_AVAIL_INVALID_USE);
2589 }
2590
2591 // RFC 9608 Section 3:
2592 // The Authority Information Access certificate extension, if
2593 // present, MUST NOT include an id-ad-ocsp accessMethod
2594 //
2595 // Walk the raw AccessDescription list rather than the URI-only typed
2596 // accessor so a non-URI OCSP accessLocation also triggers the rejection.
2597 if(const auto* aia = exts.get_extension_object_as<Authority_Information_Access>(); aia != nullptr) {
2598 const OID id_ad_ocsp = OID::from_string("PKIX.OCSP");
2599 const bool has_ocsp = !aia->ocsp_responder_uris().empty() ||
2600 std::ranges::any_of(aia->access_descriptions(),
2601 [&](const auto& ad) { return ad.access_method() == id_ad_ocsp; });
2602 if(has_ocsp) {
2603 cert_status.at(pos).insert(Certificate_Status_Code::NO_REV_AVAIL_INVALID_USE);
2604 }
2605 }
2606}
2607
2608std::vector<uint8_t> Unknown_Extension::encode_inner() const {
2609 return m_bytes;
2610}
2611
2612void Unknown_Extension::decode_inner(const std::vector<uint8_t>& bytes) {
2613 // Just treat as an opaque blob at this level
2614 m_bytes = bytes;
2615}
2616
2617} // namespace Cert_Extension
2618
2619} // 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_ARG_CHECK(expr, msg)
Definition assert.h:33
#define BOTAN_ASSERT(expr, assertion_made)
Definition assert.h:62
size_t unused_bits() const
Definition asn1_obj.h:211
std::span< const uint8_t > bytes() const
Definition asn1_obj.h:206
const std::string & value() const
Definition asn1_obj.h:590
const std::set< X509_DN > & directory_names() const
Return the set of directory names included in this alternative name.
Definition pkix_types.h:443
static Limits DER()
Definition ber_dec.h:42
const BER_Object & peek_next_object()
Definition ber_dec.cpp:505
BER_Object get_next_object()
Definition ber_dec.cpp:516
BER_Decoder & decode_bitstring(ASN1_BitString &out, ASN1_Type type_tag=ASN1_Type::BitString, ASN1_Class class_tag=ASN1_Class::Universal)
Definition ber_dec.cpp:1042
BER_Decoder & decode(bool &out)
Definition ber_dec.h:358
bool more_items() const
Definition ber_dec.cpp:461
Limits limits() const
Definition ber_dec.h:197
BER_Decoder & verify_end()
Definition ber_dec.cpp:471
BER_Decoder & end_cons()
Definition ber_dec.cpp:630
BER_Decoder start_sequence()
Definition ber_dec.h:275
BER_Decoder start_context_specific(uint32_t tag)
Definition ber_dec.h:290
BER_Decoder & decode_optional(T &out, ASN1_Type type_tag, ASN1_Class class_tag, const T &default_value=T())
Definition ber_dec.h:553
BER_Decoder & decode_null()
Definition ber_dec.cpp:683
BER_Decoder & decode_implicit(BER_Object obj, T &out, ASN1_Type real_type, ASN1_Class real_class)
Definition ber_dec.h:640
BER_Decoder & decode_optional_field(uint32_t tag_no, ASN1_Class class_tag, F &&fn)
Definition ber_dec.h:626
BER_Decoder & decode_list(std::vector< T > &vec, ASN1_Type type_tag=ASN1_Type::Sequence, ASN1_Class class_tag=ASN1_Class::Universal)
Definition ber_dec.h:880
bool is_a(ASN1_Type type_tag, ASN1_Class class_tag) const
Definition asn1_obj.cpp:97
ASN1_Type type_tag() const
Definition asn1_obj.h:277
ASN1_Class get_class() const
Definition asn1_obj.h:292
int signum() const
Definition bigint.h:493
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:1176
const std::optional< ASIdentifierChoice > & asnum() const
Definition x509_ext.h:1195
const std::optional< ASIdentifierChoice > & rdi() const
Definition x509_ext.h:1197
void encode_into(DER_Encoder &to) const override
void decode_from(BER_Decoder &from) override
void validate(const X509_Certificate &subject, const std::optional< X509_Certificate > &issuer, const std::vector< X509_Certificate > &cert_path, std::vector< std::set< Certificate_Status_Code > > &cert_status, size_t pos) const override
const ASIdentifiers & as_identifiers() const
Definition x509_ext.h:1257
std::vector< std::string > ca_issuers() const
const std::vector< AccessDescription > & access_descriptions() const
Definition x509_ext.h:466
std::unique_ptr< Certificate_Extension > copy() const override
std::vector< std::string > ocsp_responders() const
BOTAN_FUTURE_EXPLICIT Basic_Constraints(bool is_ca=false, size_t path_length_constraint=0)
Definition x509_ext.cpp:445
std::optional< size_t > path_length_constraint() const
Definition x509_ext.h:55
const std::optional< AlternativeName > & crl_issuer() const
Definition x509_ext.h:631
std::vector< std::string > crl_distribution_urls() const
const BigInt & crl_number() const
std::unique_ptr< Certificate_Extension > copy() const override
void validate(const X509_Certificate &subject, const std::optional< X509_Certificate > &issuer, const std::vector< X509_Certificate > &cert_path, std::vector< std::set< Certificate_Status_Code > > &cert_status, size_t pos) const override
Definition x509_ext.cpp:935
void decode_from(BER_Decoder &from) override
void encode_into(DER_Encoder &to) const override
const std::optional< AlternativeName > & full_name() const
Definition x509_ext.h:587
void encode_into(DER_Encoder &to) const override
void encode_into(DER_Encoder &to) const override
std::variant< IPAddressChoice< Version::IPv4 >, IPAddressChoice< Version::IPv6 > > AddrChoice
Definition x509_ext.h:1028
void encode_into(DER_Encoder &to) const override
void validate(const X509_Certificate &subject, const std::optional< X509_Certificate > &issuer, const std::vector< X509_Certificate > &cert_path, std::vector< std::set< Certificate_Status_Code > > &cert_status, size_t pos) const override
const std::vector< IPAddressFamily > & addr_blocks() const
Definition x509_ext.h:1106
void validate(const X509_Certificate &subject, const std::optional< X509_Certificate > &issuer, const std::vector< X509_Certificate > &cert_path, std::vector< std::set< Certificate_Status_Code > > &cert_status, size_t pos) const override
Definition x509_ext.cpp:827
void validate(const X509_Certificate &subject, const std::optional< X509_Certificate > &issuer, const std::vector< X509_Certificate > &cert_path, std::vector< std::set< Certificate_Status_Code > > &cert_status, size_t pos) const override
void validate(const X509_Certificate &subject, const std::optional< X509_Certificate > &issuer, const std::vector< X509_Certificate > &cert_path, std::vector< std::set< Certificate_Status_Code > > &cert_status, size_t pos) const override
const std::string & service_provider_code() const
const std::string & telephone_number() const
std::vector< TelephoneNumberRangeData > RangeContainer
Definition x509_ext.h:878
void decode_from(class BER_Decoder &from) override
void encode_into(DER_Encoder &to) const override
const RangeContainer & telephone_number_range() const
virtual bool should_encode() const
Definition pkix_types.h:863
virtual void validate(const X509_Certificate &subject, const std::optional< X509_Certificate > &issuer, const std::vector< X509_Certificate > &cert_path, std::vector< std::set< Certificate_Status_Code > > &cert_status, size_t pos) const
Definition x509_ext.cpp:181
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:285
DER_Encoder & end_explicit()
Definition der_enc.cpp:230
DER_Encoder & encode_optional(const T &value, const T &default_value)
Definition der_enc.h:301
DER_Encoder & encode_list(const std::vector< T > &values)
Definition der_enc.h:327
DER_Encoder & start_explicit(uint16_t type_tag)
Definition der_enc.cpp:223
DER_Encoder & start_explicit_context_specific(uint32_t tag)
Definition der_enc.h:122
DER_Encoder & start_sequence()
Definition der_enc.h:86
DER_Encoder & encode_null()
Definition der_enc.cpp:306
DER_Encoder & end_cons()
Definition der_enc.cpp:208
DER_Encoder & encode_bitstring(std::span< const uint8_t > bits, size_t unused_bits=0, ASN1_Type type_tag=ASN1_Type::BitString, ASN1_Class class_tag=ASN1_Class::Universal)
Definition der_enc.cpp:411
DER_Encoder & encode(bool b)
Definition der_enc.cpp:313
const Certificate_Extension * get_extension_object(const OID &oid) const
Definition x509_ext.cpp:256
std::map< OID, std::pair< std::vector< uint8_t >, bool > > extensions_raw() const
Definition x509_ext.cpp:291
std::vector< OID > critical_extensions() const
Definition x509_ext.cpp:128
std::unique_ptr< Certificate_Extension > get(const OID &oid) const
Definition x509_ext.cpp:265
void validate(const X509_Certificate &subject, const std::optional< X509_Certificate > &issuer, const std::vector< X509_Certificate > &cert_path, std::vector< std::set< Certificate_Status_Code > > &cert_status, size_t pos) const
Definition x509_ext.cpp:281
void decode_from(BER_Decoder &from) override
Definition x509_ext.cpp:322
bool remove(const OID &oid)
Definition x509_ext.cpp:215
std::vector< uint8_t > get_extension_bits(const OID &oid) const
Definition x509_ext.cpp:247
bool critical_extension_set(const OID &oid) const
Definition x509_ext.cpp:239
const T * get_extension_object_as(const OID &oid=T::static_oid()) const
Definition pkix_types.h:884
std::vector< std::pair< std::unique_ptr< Certificate_Extension >, bool > > extensions() const
Definition x509_ext.cpp:272
void encode_into(DER_Encoder &to) const override
Definition x509_ext.cpp:302
void replace(std::unique_ptr< Certificate_Extension > extn, bool critical=false)
Definition x509_ext.cpp:225
bool add_new(std::unique_ptr< Certificate_Extension > extn, bool critical=false)
Definition x509_ext.cpp:203
bool extension_set(const OID &oid) const
Definition x509_ext.cpp:235
void add(std::unique_ptr< Certificate_Extension > extn, bool critical=false)
Definition x509_ext.cpp:190
static std::unique_ptr< HashFunction > create_or_throw(std::string_view algo_spec, std::string_view provider="")
Definition hash.cpp:308
static OID from_string(std::string_view str)
Definition asn1_oid.cpp:80
virtual std::vector< uint8_t > public_key_bits() const =0
static std::optional< URI > from_string(std::string_view raw)
Definition uri.cpp:164
bool is_CA_cert() const
Definition x509cert.cpp:483
bool is_critical(std::string_view ex_name) const
Definition x509cert.cpp:613
const Extensions & v3_extensions() const
Definition x509cert.cpp:519
bool allowed_usage(Key_Constraints usage) const
Definition x509cert.cpp:528
std::string to_string(const BER_Object &obj)
Definition asn1_obj.cpp:224
constexpr uint8_t get_byte(T input)
Definition loadstor.h:79
ASN1_Class
Definition asn1_obj.h:32
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53
ASN1_Type
Definition asn1_obj.h:47
constexpr RT checked_cast_to(AT i)
Definition int_utils.h:104
std::optional< uint32_t > is_sub_element_of(const OID &oid, std::initializer_list< uint32_t > prefix)
Definition x509_utils.h:22
Extension_Context
Definition pkix_types.h:797