Botan 3.4.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*
7* Botan is released under the Simplified BSD License (see license.txt)
8*/
9
10#include <botan/x509_ext.h>
11
12#include <botan/ber_dec.h>
13#include <botan/der_enc.h>
14#include <botan/hash.h>
15#include <botan/x509cert.h>
16#include <botan/internal/bit_ops.h>
17#include <botan/internal/loadstor.h>
18#include <algorithm>
19#include <set>
20#include <sstream>
21
22namespace Botan {
23
24namespace {
25
26std::unique_ptr<Certificate_Extension> extension_from_oid(const OID& oid) {
28 return std::make_unique<Cert_Extension::Subject_Key_ID>();
29 }
30
32 return std::make_unique<Cert_Extension::Key_Usage>();
33 }
34
36 return std::make_unique<Cert_Extension::Subject_Alternative_Name>();
37 }
38
40 return std::make_unique<Cert_Extension::Issuer_Alternative_Name>();
41 }
42
44 return std::make_unique<Cert_Extension::Basic_Constraints>();
45 }
46
48 return std::make_unique<Cert_Extension::CRL_Number>();
49 }
50
52 return std::make_unique<Cert_Extension::CRL_ReasonCode>();
53 }
54
56 return std::make_unique<Cert_Extension::Authority_Key_ID>();
57 }
58
60 return std::make_unique<Cert_Extension::Name_Constraints>();
61 }
62
64 return std::make_unique<Cert_Extension::CRL_Distribution_Points>();
65 }
66
68 return std::make_unique<Cert_Extension::CRL_Issuing_Distribution_Point>();
69 }
70
72 return std::make_unique<Cert_Extension::Certificate_Policies>();
73 }
74
76 return std::make_unique<Cert_Extension::Extended_Key_Usage>();
77 }
78
80 return std::make_unique<Cert_Extension::Authority_Information_Access>();
81 }
82
83 return nullptr; // unknown
84}
85
86} // namespace
87
88/*
89* Create a Certificate_Extension object of some kind to handle
90*/
91std::unique_ptr<Certificate_Extension> Extensions::create_extn_obj(const OID& oid,
92 bool critical,
93 const std::vector<uint8_t>& body) {
94 const std::string oid_str = oid.to_string();
95
96 auto extn = extension_from_oid(oid);
97
98 if(!extn) {
99 // some other unknown extension type
100 extn = std::make_unique<Cert_Extension::Unknown_Extension>(oid, critical);
101 }
102
103 try {
104 extn->decode_inner(body);
105 } catch(Decoding_Error&) {
106 extn = std::make_unique<Cert_Extension::Unknown_Extension>(oid, critical);
107 extn->decode_inner(body);
108 }
109 return extn;
110}
111
112/*
113* Validate the extension (the default implementation is a NOP)
114*/
116 const X509_Certificate& /*unused*/,
117 const std::vector<X509_Certificate>& /*unused*/,
118 std::vector<std::set<Certificate_Status_Code>>& /*unused*/,
119 size_t /*unused*/) {}
120
121/*
122* Add a new cert
123*/
124void Extensions::add(std::unique_ptr<Certificate_Extension> extn, bool critical) {
125 // sanity check: we don't want to have the same extension more than once
126 if(m_extension_info.contains(extn->oid_of())) {
127 const std::string name = extn->oid_name();
128 throw Invalid_Argument("Extension " + name + " already present in Extensions::add");
129 }
130
131 const OID oid = extn->oid_of();
132 Extensions_Info info(critical, std::move(extn));
133 m_extension_oids.push_back(oid);
134 m_extension_info.emplace(oid, info);
135}
136
137bool Extensions::add_new(std::unique_ptr<Certificate_Extension> extn, bool critical) {
138 if(m_extension_info.contains(extn->oid_of())) {
139 return false; // already exists
140 }
141
142 const OID oid = extn->oid_of();
143 Extensions_Info info(critical, std::move(extn));
144 m_extension_oids.push_back(oid);
145 m_extension_info.emplace(oid, info);
146 return true;
147}
148
149bool Extensions::remove(const OID& oid) {
150 const bool erased = m_extension_info.erase(oid) > 0;
151
152 if(erased) {
153 m_extension_oids.erase(std::find(m_extension_oids.begin(), m_extension_oids.end(), oid));
154 }
155
156 return erased;
157}
158
159void Extensions::replace(std::unique_ptr<Certificate_Extension> extn, bool critical) {
160 // Remove it if it existed
161 remove(extn->oid_of());
162
163 const OID oid = extn->oid_of();
164 Extensions_Info info(critical, std::move(extn));
165 m_extension_oids.push_back(oid);
166 m_extension_info.emplace(oid, info);
167}
168
169bool Extensions::extension_set(const OID& oid) const {
170 return (m_extension_info.find(oid) != m_extension_info.end());
171}
172
174 auto i = m_extension_info.find(oid);
175 if(i != m_extension_info.end()) {
176 return i->second.is_critical();
177 }
178 return false;
179}
180
181std::vector<uint8_t> Extensions::get_extension_bits(const OID& oid) const {
182 auto i = m_extension_info.find(oid);
183 if(i == m_extension_info.end()) {
184 throw Invalid_Argument("Extensions::get_extension_bits no such extension set");
185 }
186
187 return i->second.bits();
188}
189
191 auto extn = m_extension_info.find(oid);
192 if(extn == m_extension_info.end()) {
193 return nullptr;
194 }
195
196 return &extn->second.obj();
197}
198
199std::unique_ptr<Certificate_Extension> Extensions::get(const OID& oid) const {
200 if(const Certificate_Extension* ext = this->get_extension_object(oid)) {
201 return ext->copy();
202 }
203 return nullptr;
204}
205
206std::vector<std::pair<std::unique_ptr<Certificate_Extension>, bool>> Extensions::extensions() const {
207 std::vector<std::pair<std::unique_ptr<Certificate_Extension>, bool>> exts;
208 exts.reserve(m_extension_info.size());
209 for(auto&& ext : m_extension_info) {
210 exts.push_back(std::make_pair(ext.second.obj().copy(), ext.second.is_critical()));
211 }
212 return exts;
213}
214
215std::map<OID, std::pair<std::vector<uint8_t>, bool>> Extensions::extensions_raw() const {
216 std::map<OID, std::pair<std::vector<uint8_t>, bool>> out;
217 for(auto&& ext : m_extension_info) {
218 out.emplace(ext.first, std::make_pair(ext.second.bits(), ext.second.is_critical()));
219 }
220 return out;
221}
222
223/*
224* Encode an Extensions list
225*/
226void Extensions::encode_into(DER_Encoder& to_object) const {
227 for(const auto& ext_info : m_extension_info) {
228 const OID& oid = ext_info.first;
229 const bool should_encode = ext_info.second.obj().should_encode();
230
231 if(should_encode) {
232 const bool is_critical = ext_info.second.is_critical();
233 const std::vector<uint8_t>& ext_value = ext_info.second.bits();
234
235 to_object.start_sequence()
236 .encode(oid)
237 .encode_optional(is_critical, false)
238 .encode(ext_value, ASN1_Type::OctetString)
239 .end_cons();
240 }
241 }
242}
243
244/*
245* Decode a list of Extensions
246*/
248 m_extension_oids.clear();
249 m_extension_info.clear();
250
251 BER_Decoder sequence = from_source.start_sequence();
252
253 while(sequence.more_items()) {
254 OID oid;
255 bool critical;
256 std::vector<uint8_t> bits;
257
258 sequence.start_sequence()
259 .decode(oid)
262 .end_cons();
263
264 auto obj = create_extn_obj(oid, critical, bits);
265 Extensions_Info info(critical, bits, std::move(obj));
266
267 m_extension_oids.push_back(oid);
268 m_extension_info.emplace(oid, info);
269 }
270 sequence.verify_end();
271}
272
273namespace Cert_Extension {
274
275/*
276* Checked accessor for the path_limit member
277*/
279 if(!m_is_ca) {
280 throw Invalid_State("Basic_Constraints::get_path_limit: Not a CA");
281 }
282 return m_path_limit;
283}
284
285/*
286* Encode the extension
287*/
288std::vector<uint8_t> Basic_Constraints::encode_inner() const {
289 std::vector<uint8_t> output;
290 DER_Encoder(output)
292 .encode_if(m_is_ca, DER_Encoder().encode(m_is_ca).encode_optional(m_path_limit, NO_CERT_PATH_LIMIT))
293 .end_cons();
294 return output;
295}
296
297/*
298* Decode the extension
299*/
300void Basic_Constraints::decode_inner(const std::vector<uint8_t>& in) {
301 BER_Decoder(in)
304 .decode_optional(m_path_limit, ASN1_Type::Integer, ASN1_Class::Universal, NO_CERT_PATH_LIMIT)
305 .end_cons();
306
307 if(m_is_ca == false) {
308 m_path_limit = 0;
309 }
310}
311
312/*
313* Encode the extension
314*/
315std::vector<uint8_t> Key_Usage::encode_inner() const {
316 if(m_constraints.empty()) {
317 throw Encoding_Error("Cannot encode empty PKIX key constraints");
318 }
319
320 const size_t constraint_bits = m_constraints.value();
321 const size_t unused_bits = ctz(static_cast<uint32_t>(constraint_bits));
322
323 std::vector<uint8_t> der;
324 der.push_back(static_cast<uint8_t>(ASN1_Type::BitString));
325 der.push_back(2 + ((unused_bits < 8) ? 1 : 0));
326 der.push_back(unused_bits % 8);
327 der.push_back((constraint_bits >> 8) & 0xFF);
328 if(constraint_bits & 0xFF) {
329 der.push_back(constraint_bits & 0xFF);
330 }
331
332 return der;
333}
334
335/*
336* Decode the extension
337*/
338void Key_Usage::decode_inner(const std::vector<uint8_t>& in) {
339 BER_Decoder ber(in);
340
341 BER_Object obj = ber.get_next_object();
342
343 obj.assert_is_a(ASN1_Type::BitString, ASN1_Class::Universal, "usage constraint");
344
345 if(obj.length() != 2 && obj.length() != 3) {
346 throw BER_Decoding_Error("Bad size for BITSTRING in usage constraint");
347 }
348
349 uint16_t usage = 0;
350
351 const uint8_t* bits = obj.bits();
352
353 if(bits[0] >= 8) {
354 throw BER_Decoding_Error("Invalid unused bits in usage constraint");
355 }
356
357 const uint8_t mask = static_cast<uint8_t>(0xFF << bits[0]);
358
359 if(obj.length() == 2) {
360 usage = make_uint16(bits[1] & mask, 0);
361 } else if(obj.length() == 3) {
362 usage = make_uint16(bits[1], bits[2] & mask);
363 }
364
365 m_constraints = Key_Constraints(usage);
366}
367
368/*
369* Encode the extension
370*/
371std::vector<uint8_t> Subject_Key_ID::encode_inner() const {
372 std::vector<uint8_t> output;
373 DER_Encoder(output).encode(m_key_id, ASN1_Type::OctetString);
374 return output;
375}
376
377/*
378* Decode the extension
379*/
380void Subject_Key_ID::decode_inner(const std::vector<uint8_t>& in) {
381 BER_Decoder(in).decode(m_key_id, ASN1_Type::OctetString).verify_end();
382}
383
384/*
385* Subject_Key_ID Constructor
386*/
387Subject_Key_ID::Subject_Key_ID(const std::vector<uint8_t>& pub_key, std::string_view hash_name) {
388 auto hash = HashFunction::create_or_throw(hash_name);
389
390 m_key_id.resize(hash->output_length());
391
392 hash->update(pub_key);
393 hash->final(m_key_id.data());
394
395 // Truncate longer hashes, 192 bits here seems plenty
396 const size_t max_skid_len = (192 / 8);
397 if(m_key_id.size() > max_skid_len) {
398 m_key_id.resize(max_skid_len);
399 }
400}
401
402/*
403* Encode the extension
404*/
405std::vector<uint8_t> Authority_Key_ID::encode_inner() const {
406 std::vector<uint8_t> output;
407 DER_Encoder(output)
410 .end_cons();
411 return output;
412}
413
414/*
415* Decode the extension
416*/
417void Authority_Key_ID::decode_inner(const std::vector<uint8_t>& in) {
419}
420
421/*
422* Encode the extension
423*/
424std::vector<uint8_t> Subject_Alternative_Name::encode_inner() const {
425 std::vector<uint8_t> output;
426 DER_Encoder(output).encode(m_alt_name);
427 return output;
428}
429
430/*
431* Encode the extension
432*/
433std::vector<uint8_t> Issuer_Alternative_Name::encode_inner() const {
434 std::vector<uint8_t> output;
435 DER_Encoder(output).encode(m_alt_name);
436 return output;
437}
438
439/*
440* Decode the extension
441*/
442void Subject_Alternative_Name::decode_inner(const std::vector<uint8_t>& in) {
443 BER_Decoder(in).decode(m_alt_name);
444}
445
446/*
447* Decode the extension
448*/
449void Issuer_Alternative_Name::decode_inner(const std::vector<uint8_t>& in) {
450 BER_Decoder(in).decode(m_alt_name);
451}
452
453/*
454* Encode the extension
455*/
456std::vector<uint8_t> Extended_Key_Usage::encode_inner() const {
457 std::vector<uint8_t> output;
458 DER_Encoder(output).start_sequence().encode_list(m_oids).end_cons();
459 return output;
460}
461
462/*
463* Decode the extension
464*/
465void Extended_Key_Usage::decode_inner(const std::vector<uint8_t>& in) {
466 BER_Decoder(in).decode_list(m_oids);
467}
468
469/*
470* Encode the extension
471*/
472std::vector<uint8_t> Name_Constraints::encode_inner() const {
473 throw Not_Implemented("Name_Constraints encoding");
474}
475
476/*
477* Decode the extension
478*/
479void Name_Constraints::decode_inner(const std::vector<uint8_t>& in) {
480 std::vector<GeneralSubtree> permit, exclude;
481 BER_Decoder ber(in);
482 BER_Decoder ext = ber.start_sequence();
483 BER_Object per = ext.get_next_object();
484
485 ext.push_back(per);
488 if(permit.empty()) {
489 throw Encoding_Error("Empty Name Contraint list");
490 }
491 }
492
493 BER_Object exc = ext.get_next_object();
494 ext.push_back(exc);
496 ext.decode_list(exclude, ASN1_Type(1), ASN1_Class::Constructed | ASN1_Class::ContextSpecific);
497 if(exclude.empty()) {
498 throw Encoding_Error("Empty Name Contraint list");
499 }
500 }
501
502 ext.end_cons();
503
504 if(permit.empty() && exclude.empty()) {
505 throw Encoding_Error("Empty Name Contraint extension");
506 }
507
508 m_name_constraints = NameConstraints(std::move(permit), std::move(exclude));
509}
510
512 const X509_Certificate& issuer,
513 const std::vector<X509_Certificate>& cert_path,
514 std::vector<std::set<Certificate_Status_Code>>& cert_status,
515 size_t pos) {
516 if(!m_name_constraints.permitted().empty() || !m_name_constraints.excluded().empty()) {
517 if(!subject.is_CA_cert()) {
518 cert_status.at(pos).insert(Certificate_Status_Code::NAME_CONSTRAINT_ERROR);
519 }
520
521 const bool issuer_name_constraint_critical = issuer.is_critical("X509v3.NameConstraints");
522
523 // Check that all subordinate certs pass the name constraint
524 for(size_t j = 0; j < pos; ++j) {
525 bool permitted = m_name_constraints.permitted().empty();
526 bool failed = false;
527
528 for(const auto& c : m_name_constraints.permitted()) {
529 switch(c.base().matches(cert_path.at(j))) {
532 permitted = true;
533 break;
535 failed = issuer_name_constraint_critical;
536 permitted = true;
537 break;
538 default:
539 break;
540 }
541 }
542
543 for(const auto& c : m_name_constraints.excluded()) {
544 switch(c.base().matches(cert_path.at(j))) {
547 failed = true;
548 break;
550 failed = issuer_name_constraint_critical;
551 break;
552 default:
553 break;
554 }
555 }
556
557 if(failed || !permitted) {
558 cert_status.at(j).insert(Certificate_Status_Code::NAME_CONSTRAINT_ERROR);
559 }
560 }
561 }
562}
563
564namespace {
565
566/*
567* A policy specifier
568*/
569class Policy_Information final : public ASN1_Object {
570 public:
571 Policy_Information() = default;
572
573 explicit Policy_Information(const OID& oid) : m_oid(oid) {}
574
575 const OID& oid() const { return m_oid; }
576
577 void encode_into(DER_Encoder& codec) const override { codec.start_sequence().encode(m_oid).end_cons(); }
578
579 void decode_from(BER_Decoder& codec) override {
580 codec.start_sequence().decode(m_oid).discard_remaining().end_cons();
581 }
582
583 private:
584 OID m_oid;
585};
586
587} // namespace
588
589/*
590* Encode the extension
591*/
592std::vector<uint8_t> Certificate_Policies::encode_inner() const {
593 std::vector<Policy_Information> policies;
594
595 policies.reserve(m_oids.size());
596 for(const auto& oid : m_oids) {
597 policies.push_back(Policy_Information(oid));
598 }
599
600 std::vector<uint8_t> output;
601 DER_Encoder(output).start_sequence().encode_list(policies).end_cons();
602 return output;
603}
604
605/*
606* Decode the extension
607*/
608void Certificate_Policies::decode_inner(const std::vector<uint8_t>& in) {
609 std::vector<Policy_Information> policies;
610
611 BER_Decoder(in).decode_list(policies);
612 m_oids.clear();
613 for(const auto& policy : policies) {
614 m_oids.push_back(policy.oid());
615 }
616}
617
619 const X509_Certificate& /*issuer*/,
620 const std::vector<X509_Certificate>& /*cert_path*/,
621 std::vector<std::set<Certificate_Status_Code>>& cert_status,
622 size_t pos) {
623 std::set<OID> oid_set(m_oids.begin(), m_oids.end());
624 if(oid_set.size() != m_oids.size()) {
625 cert_status.at(pos).insert(Certificate_Status_Code::DUPLICATE_CERT_POLICY);
626 }
627}
628
629std::vector<uint8_t> Authority_Information_Access::encode_inner() const {
630 std::vector<uint8_t> output;
631 DER_Encoder der(output);
632
633 der.start_sequence();
634 // OCSP
635 if(!m_ocsp_responder.empty()) {
636 ASN1_String url(m_ocsp_responder, ASN1_Type::Ia5String);
637 der.start_sequence()
638 .encode(OID::from_string("PKIX.OCSP"))
639 .add_object(ASN1_Type(6), ASN1_Class::ContextSpecific, url.value())
640 .end_cons();
641 }
642
643 // CA Issuers
644 for(const auto& ca_isser : m_ca_issuers) {
645 ASN1_String asn1_ca_issuer(ca_isser, ASN1_Type::Ia5String);
646 der.start_sequence()
647 .encode(OID::from_string("PKIX.CertificateAuthorityIssuers"))
648 .add_object(ASN1_Type(6), ASN1_Class::ContextSpecific, asn1_ca_issuer.value())
649 .end_cons();
650 }
651
652 der.end_cons();
653 return output;
654}
655
656void Authority_Information_Access::decode_inner(const std::vector<uint8_t>& in) {
657 BER_Decoder ber = BER_Decoder(in).start_sequence();
658
659 while(ber.more_items()) {
660 OID oid;
661
662 BER_Decoder info = ber.start_sequence();
663
664 info.decode(oid);
665
666 if(oid == OID::from_string("PKIX.OCSP")) {
667 BER_Object name = info.get_next_object();
668
669 if(name.is_a(6, ASN1_Class::ContextSpecific)) {
670 m_ocsp_responder = ASN1::to_string(name);
671 }
672 }
673 if(oid == OID::from_string("PKIX.CertificateAuthorityIssuers")) {
674 BER_Object name = info.get_next_object();
675
676 if(name.is_a(6, ASN1_Class::ContextSpecific)) {
677 m_ca_issuers.push_back(ASN1::to_string(name));
678 }
679 }
680 }
681}
682
683/*
684* Checked accessor for the crl_number member
685*/
687 if(!m_has_value) {
688 throw Invalid_State("CRL_Number::get_crl_number: Not set");
689 }
690 return m_crl_number;
691}
692
693/*
694* Copy a CRL_Number extension
695*/
696std::unique_ptr<Certificate_Extension> CRL_Number::copy() const {
697 if(!m_has_value) {
698 throw Invalid_State("CRL_Number::copy: Not set");
699 }
700 return std::make_unique<CRL_Number>(m_crl_number);
701}
702
703/*
704* Encode the extension
705*/
706std::vector<uint8_t> CRL_Number::encode_inner() const {
707 std::vector<uint8_t> output;
708 DER_Encoder(output).encode(m_crl_number);
709 return output;
710}
711
712/*
713* Decode the extension
714*/
715void CRL_Number::decode_inner(const std::vector<uint8_t>& in) {
716 BER_Decoder(in).decode(m_crl_number);
717 m_has_value = true;
718}
719
720/*
721* Encode the extension
722*/
723std::vector<uint8_t> CRL_ReasonCode::encode_inner() const {
724 std::vector<uint8_t> output;
725 DER_Encoder(output).encode(static_cast<size_t>(m_reason), ASN1_Type::Enumerated, ASN1_Class::Universal);
726 return output;
727}
728
729/*
730* Decode the extension
731*/
732void CRL_ReasonCode::decode_inner(const std::vector<uint8_t>& in) {
733 size_t reason_code = 0;
734 BER_Decoder(in).decode(reason_code, ASN1_Type::Enumerated, ASN1_Class::Universal);
735 m_reason = static_cast<CRL_Code>(reason_code);
736}
737
738std::vector<uint8_t> CRL_Distribution_Points::encode_inner() const {
739 std::vector<uint8_t> output;
740 DER_Encoder(output).start_sequence().encode_list(m_distribution_points).end_cons();
741 return output;
742}
743
744void CRL_Distribution_Points::decode_inner(const std::vector<uint8_t>& buf) {
745 BER_Decoder(buf).decode_list(m_distribution_points).verify_end();
746
747 std::stringstream ss;
748
749 for(const auto& distribution_point : m_distribution_points) {
750 auto contents = distribution_point.point().contents();
751
752 for(const auto& pair : contents) {
753 ss << pair.first << ": " << pair.second << " ";
754 }
755 }
756
757 m_crl_distribution_urls.push_back(ss.str());
758}
759
761 if(!m_point.get_attributes().contains("URI")) {
762 throw Not_Implemented("Empty CRL_Distribution_Point encoding");
763 }
764
765 const auto range = m_point.get_attributes().equal_range("URI");
766
767 for(auto i = range.first; i != range.second; ++i) {
768 der.start_sequence()
771 .add_object(ASN1_Type(6), ASN1_Class::ContextSpecific, i->second)
772 .end_cons()
773 .end_cons()
774 .end_cons();
775 }
776}
777
789
790std::vector<uint8_t> CRL_Issuing_Distribution_Point::encode_inner() const {
791 throw Not_Implemented("CRL_Issuing_Distribution_Point encoding");
792}
793
794void CRL_Issuing_Distribution_Point::decode_inner(const std::vector<uint8_t>& buf) {
795 BER_Decoder(buf).decode(m_distribution_point).verify_end();
796}
797
798void OCSP_NoCheck::decode_inner(const std::vector<uint8_t>& buf) {
799 BER_Decoder(buf).verify_end();
800}
801
802std::vector<uint8_t> Unknown_Extension::encode_inner() const {
803 return m_bytes;
804}
805
806void Unknown_Extension::decode_inner(const std::vector<uint8_t>& bytes) {
807 // Just treat as an opaque blob at this level
808 m_bytes = bytes;
809}
810
811} // namespace Cert_Extension
812
813} // namespace Botan
const std::multimap< std::string, std::string, std::less<> > & get_attributes() const
Definition pkix_types.h:131
BER_Decoder & decode(bool &out)
Definition ber_dec.h:176
bool more_items() const
Definition ber_dec.cpp:195
BER_Decoder & verify_end()
Definition ber_dec.cpp:205
BER_Decoder & end_cons()
Definition ber_dec.cpp:295
BER_Decoder & decode_list(std::vector< T > &out, ASN1_Type type_tag=ASN1_Type::Sequence, ASN1_Class class_tag=ASN1_Class::Universal)
Definition ber_dec.h:364
BER_Decoder start_sequence()
Definition ber_dec.h:113
BER_Decoder start_context_specific(uint32_t tag)
Definition ber_dec.h:117
BER_Decoder & decode_optional(T &out, ASN1_Type type_tag, ASN1_Class class_tag, const T &default_value=T())
Definition ber_dec.h:317
BER_Decoder & decode_optional_string(std::vector< uint8_t, Alloc > &out, ASN1_Type real_type, uint32_t expected_tag, ASN1_Class class_tag=ASN1_Class::ContextSpecific)
Definition ber_dec.h:272
BER_Decoder & decode_optional_implicit(T &out, ASN1_Type type_tag, ASN1_Class class_tag, ASN1_Type real_type, ASN1_Class real_class, const T &default_value=T())
Definition ber_dec.h:339
std::unique_ptr< Certificate_Extension > copy() const override
Definition x509_ext.cpp:696
void validate(const X509_Certificate &subject, const X509_Certificate &issuer, const std::vector< X509_Certificate > &cert_path, std::vector< std::set< Certificate_Status_Code > > &cert_status, size_t pos) override
Definition x509_ext.cpp:618
void validate(const X509_Certificate &subject, const X509_Certificate &issuer, const std::vector< X509_Certificate > &cert_path, std::vector< std::set< Certificate_Status_Code > > &cert_status, size_t pos) override
Definition x509_ext.cpp:511
virtual void validate(const X509_Certificate &subject, const X509_Certificate &issuer, const std::vector< X509_Certificate > &cert_path, std::vector< std::set< Certificate_Status_Code > > &cert_status, size_t pos)
Definition x509_ext.cpp:115
DER_Encoder & encode_optional(const T &value, const T &default_value)
Definition der_enc.h:124
DER_Encoder & start_sequence()
Definition der_enc.h:65
DER_Encoder & encode_if(bool pred, DER_Encoder &enc)
Definition der_enc.h:147
DER_Encoder & start_cons(ASN1_Type type_tag, ASN1_Class class_tag)
Definition der_enc.cpp:163
DER_Encoder & end_cons()
Definition der_enc.cpp:171
DER_Encoder & encode(bool b)
Definition der_enc.cpp:250
const Certificate_Extension * get_extension_object(const OID &oid) const
Definition x509_ext.cpp:190
std::map< OID, std::pair< std::vector< uint8_t >, bool > > extensions_raw() const
Definition x509_ext.cpp:215
std::unique_ptr< Certificate_Extension > get(const OID &oid) const
Definition x509_ext.cpp:199
void decode_from(BER_Decoder &) override
Definition x509_ext.cpp:247
bool remove(const OID &oid)
Definition x509_ext.cpp:149
std::vector< uint8_t > get_extension_bits(const OID &oid) const
Definition x509_ext.cpp:181
bool critical_extension_set(const OID &oid) const
Definition x509_ext.cpp:173
std::vector< std::pair< std::unique_ptr< Certificate_Extension >, bool > > extensions() const
Definition x509_ext.cpp:206
void encode_into(DER_Encoder &) const override
Definition x509_ext.cpp:226
void replace(std::unique_ptr< Certificate_Extension > extn, bool critical=false)
Definition x509_ext.cpp:159
bool add_new(std::unique_ptr< Certificate_Extension > extn, bool critical=false)
Definition x509_ext.cpp:137
bool extension_set(const OID &oid) const
Definition x509_ext.cpp:169
void add(std::unique_ptr< Certificate_Extension > extn, bool critical=false)
Definition x509_ext.cpp:124
static std::unique_ptr< HashFunction > create_or_throw(std::string_view algo_spec, std::string_view provider="")
Definition hash.cpp:298
uint32_t value() const
Definition pkix_enums.h:169
const std::vector< GeneralSubtree > & permitted() const
Definition pkix_types.h:313
const std::vector< GeneralSubtree > & excluded() const
Definition pkix_types.h:318
static OID from_string(std::string_view str)
Definition asn1_oid.cpp:74
bool is_CA_cert() const
Definition x509cert.cpp:374
bool is_critical(std::string_view ex_name) const
Definition x509cert.cpp:481
std::string name
int(* final)(unsigned char *, CTX *)
std::string to_string(const BER_Object &obj)
Definition asn1_obj.cpp:185
ASN1_Type
Definition asn1_obj.h:43
constexpr size_t ctz(T n)
Definition bit_ops.h:102
constexpr uint16_t make_uint16(uint8_t i0, uint8_t i1)
Definition loadstor.h:88