Botan 3.0.0-alpha0
Crypto and TLS for C&
x509cert.cpp
Go to the documentation of this file.
1/*
2* X.509 Certificates
3* (C) 1999-2010,2015,2017 Jack Lloyd
4* (C) 2016 René Korthaus, Rohde & Schwarz Cybersecurity
5*
6* Botan is released under the Simplified BSD License (see license.txt)
7*/
8
9#include <botan/x509cert.h>
10#include <botan/x509_key.h>
11#include <botan/pk_keys.h>
12#include <botan/x509_ext.h>
13#include <botan/ber_dec.h>
14#include <botan/internal/parsing.h>
15#include <botan/bigint.h>
16#include <botan/oids.h>
17#include <botan/hash.h>
18#include <botan/hex.h>
19#include <algorithm>
20#include <sstream>
21
22namespace Botan {
23
24struct X509_Certificate_Data
25 {
26 std::vector<uint8_t> m_serial;
27 AlgorithmIdentifier m_sig_algo_inner;
28 X509_DN m_issuer_dn;
29 X509_DN m_subject_dn;
30 std::vector<uint8_t> m_issuer_dn_bits;
31 std::vector<uint8_t> m_subject_dn_bits;
32 X509_Time m_not_before;
33 X509_Time m_not_after;
34 std::vector<uint8_t> m_subject_public_key_bits;
35 std::vector<uint8_t> m_subject_public_key_bits_seq;
36 std::vector<uint8_t> m_subject_public_key_bitstring;
37 std::vector<uint8_t> m_subject_public_key_bitstring_sha1;
38 AlgorithmIdentifier m_subject_public_key_algid;
39
40 std::vector<uint8_t> m_v2_issuer_key_id;
41 std::vector<uint8_t> m_v2_subject_key_id;
42 Extensions m_v3_extensions;
43
44 std::vector<OID> m_extended_key_usage;
45 std::vector<uint8_t> m_authority_key_id;
46 std::vector<uint8_t> m_subject_key_id;
47 std::vector<OID> m_cert_policies;
48
49 std::vector<std::string> m_crl_distribution_points;
50 std::string m_ocsp_responder;
51 std::vector<std::string> m_ca_issuers;
52
53 std::vector<uint8_t> m_issuer_dn_bits_sha256;
54 std::vector<uint8_t> m_subject_dn_bits_sha256;
55
56 std::string m_fingerprint_sha1;
57 std::string m_fingerprint_sha256;
58
59 AlternativeName m_subject_alt_name;
60 AlternativeName m_issuer_alt_name;
61 NameConstraints m_name_constraints;
62
63 size_t m_version = 0;
64 size_t m_path_len_constraint = 0;
65 Key_Constraints m_key_constraints = NO_CONSTRAINTS;
66 bool m_self_signed = false;
67 bool m_is_ca_certificate = false;
68 bool m_serial_negative = false;
69 };
70
71std::string X509_Certificate::PEM_label() const
72 {
73 return "CERTIFICATE";
74 }
75
76std::vector<std::string> X509_Certificate::alternate_PEM_labels() const
77 {
78 return { "X509 CERTIFICATE" };
79 }
80
82 {
83 load_data(src);
84 }
85
86X509_Certificate::X509_Certificate(const std::vector<uint8_t>& vec)
87 {
88 DataSource_Memory src(vec.data(), vec.size());
89 load_data(src);
90 }
91
92X509_Certificate::X509_Certificate(const uint8_t data[], size_t len)
93 {
94 DataSource_Memory src(data, len);
95 load_data(src);
96 }
97
98#if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
99X509_Certificate::X509_Certificate(const std::string& fsname)
100 {
101 DataSource_Stream src(fsname, true);
102 load_data(src);
103 }
104#endif
105
106namespace {
107
108std::unique_ptr<X509_Certificate_Data> parse_x509_cert_body(const X509_Object& obj)
109 {
110 auto data = std::make_unique<X509_Certificate_Data>();
111
112 BigInt serial_bn;
113 BER_Object public_key;
114 BER_Object v3_exts_data;
115
116 BER_Decoder(obj.signed_body())
117 .decode_optional(data->m_version, ASN1_Type(0), ASN1_Class::Constructed | ASN1_Class::ContextSpecific)
118 .decode(serial_bn)
119 .decode(data->m_sig_algo_inner)
120 .decode(data->m_issuer_dn)
121 .start_sequence()
122 .decode(data->m_not_before)
123 .decode(data->m_not_after)
124 .end_cons()
125 .decode(data->m_subject_dn)
126 .get_next(public_key)
127 .decode_optional_string(data->m_v2_issuer_key_id, ASN1_Type::BitString, 1)
128 .decode_optional_string(data->m_v2_subject_key_id, ASN1_Type::BitString, 2)
129 .get_next(v3_exts_data)
130 .verify_end("TBSCertificate has extra data after extensions block");
131
132 if(data->m_version > 2)
133 throw Decoding_Error("Unknown X.509 cert version " + std::to_string(data->m_version));
134 if(obj.signature_algorithm() != data->m_sig_algo_inner)
135 throw Decoding_Error("X.509 Certificate had differing algorithm identifers in inner and outer ID fields");
136
137 public_key.assert_is_a(ASN1_Type::Sequence, ASN1_Class::Constructed, "X.509 certificate public key");
138
139 // crude method to save the serial's sign; will get lost during decoding, otherwise
140 data->m_serial_negative = serial_bn.is_negative();
141
142 // for general sanity convert wire version (0 based) to standards version (v1 .. v3)
143 data->m_version += 1;
144
145 data->m_serial = BigInt::encode(serial_bn);
146 data->m_subject_dn_bits = ASN1::put_in_sequence(data->m_subject_dn.get_bits());
147 data->m_issuer_dn_bits = ASN1::put_in_sequence(data->m_issuer_dn.get_bits());
148
149 // validate_public_key_params(public_key.value);
150 AlgorithmIdentifier public_key_alg_id;
151 BER_Decoder(public_key).decode(public_key_alg_id).discard_remaining();
152
153 const std::vector<std::string> public_key_info =
154 split_on(OIDS::oid2str_or_empty(public_key_alg_id.get_oid()), '/');
155
156 if(!public_key_info.empty() && public_key_info[0] == "RSA")
157 {
158 // RFC4055: If PublicKeyAlgo = PSS or OAEP: limit the use of the public key exclusively to either RSASSA - PSS or RSAES - OAEP
159 if(public_key_info.size() >= 2)
160 {
161 if(public_key_info[1] == "EMSA4")
162 {
163 /*
164 When the RSA private key owner wishes to limit the use of the public
165 key exclusively to RSASSA-PSS, then the id-RSASSA-PSS object
166 identifier MUST be used in the algorithm field within the subject
167 public key information, and, if present, the parameters field MUST
168 contain RSASSA-PSS-params.
169
170 All parameters in the signature structure algorithm identifier MUST
171 match the parameters in the key structure algorithm identifier
172 except the saltLength field. The saltLength field in the signature parameters
173 MUST be greater or equal to that in the key parameters field.
174
175 ToDo: Allow salt length to be greater
176 */
177 if(public_key_alg_id != obj.signature_algorithm())
178 {
179 throw Decoding_Error("Algorithm identifier mismatch");
180 }
181 }
182 }
183 else
184 {
185 // oid = rsaEncryption -> parameters field MUST contain NULL
186 if(public_key_alg_id != AlgorithmIdentifier(public_key_alg_id.get_oid(), AlgorithmIdentifier::USE_NULL_PARAM))
187 {
188 throw Decoding_Error("RSA algorithm parameters field MUST contain NULL");
189 }
190 }
191 }
192
193 data->m_subject_public_key_bits.assign(public_key.bits(), public_key.bits() + public_key.length());
194
195 data->m_subject_public_key_bits_seq = ASN1::put_in_sequence(data->m_subject_public_key_bits);
196
197 BER_Decoder(data->m_subject_public_key_bits)
198 .decode(data->m_subject_public_key_algid)
199 .decode(data->m_subject_public_key_bitstring, ASN1_Type::BitString);
200
201 if(v3_exts_data.is_a(3, ASN1_Class::Constructed | ASN1_Class::ContextSpecific))
202 {
203 // Path validation will reject a v1/v2 cert with v3 extensions
204 BER_Decoder(v3_exts_data).decode(data->m_v3_extensions).verify_end();
205 }
206 else if(v3_exts_data.is_set())
207 {
208 throw BER_Bad_Tag("Unknown tag in X.509 cert", v3_exts_data.tagging());
209 }
210
211 // Now cache some fields from the extensions
212 if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Key_Usage>())
213 {
214 data->m_key_constraints = ext->get_constraints();
215 /*
216 RFC 5280: When the keyUsage extension appears in a certificate,
217 at least one of the bits MUST be set to 1.
218 */
219 if(data->m_key_constraints == NO_CONSTRAINTS)
220 {
221 throw Decoding_Error("Certificate has invalid encoding for KeyUsage");
222 }
223 }
224 else
225 {
226 data->m_key_constraints = NO_CONSTRAINTS;
227 }
228
229 if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Subject_Key_ID>())
230 {
231 data->m_subject_key_id = ext->get_key_id();
232 }
233
234 if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Authority_Key_ID>())
235 {
236 data->m_authority_key_id = ext->get_key_id();
237 }
238
239 if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Name_Constraints>())
240 {
241 data->m_name_constraints = ext->get_name_constraints();
242 }
243
244 if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Basic_Constraints>())
245 {
246 if(ext->get_is_ca() == true)
247 {
248 /*
249 * RFC 5280 section 4.2.1.3 requires that CAs include KeyUsage in all
250 * intermediate CA certificates they issue. Currently we accept it being
251 * missing, as do most other implementations. But it may be worth
252 * removing this entirely, or alternately adding a warning level
253 * validation failure for it.
254 */
255 if(data->m_key_constraints == NO_CONSTRAINTS ||
256 (data->m_key_constraints & KEY_CERT_SIGN))
257 {
258 data->m_is_ca_certificate = true;
259 data->m_path_len_constraint = ext->get_path_limit();
260 }
261 }
262 }
263
264 if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Issuer_Alternative_Name>())
265 {
266 data->m_issuer_alt_name = ext->get_alt_name();
267 }
268
269 if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Subject_Alternative_Name>())
270 {
271 data->m_subject_alt_name = ext->get_alt_name();
272 }
273
274 if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Extended_Key_Usage>())
275 {
276 data->m_extended_key_usage = ext->get_oids();
277 }
278
279 if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Certificate_Policies>())
280 {
281 data->m_cert_policies = ext->get_policy_oids();
282 }
283
284 if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::Authority_Information_Access>())
285 {
286 data->m_ocsp_responder = ext->ocsp_responder();
287 data->m_ca_issuers = ext->ca_issuers();
288 }
289
290 if(auto ext = data->m_v3_extensions.get_extension_object_as<Cert_Extension::CRL_Distribution_Points>())
291 {
292 data->m_crl_distribution_points = ext->crl_distribution_urls();
293 }
294
295 // Check for self-signed vs self-issued certificates
296 if(data->m_subject_dn == data->m_issuer_dn)
297 {
298 if(data->m_subject_key_id.empty() == false && data->m_authority_key_id.empty() == false)
299 {
300 data->m_self_signed = (data->m_subject_key_id == data->m_authority_key_id);
301 }
302 else
303 {
304 /*
305 If a parse error or unknown algorithm is encountered, default
306 to assuming it is self signed. We have no way of being certain but
307 that is usually the default case (self-issued is rare in practice).
308 */
309 data->m_self_signed = true;
310
311 try
312 {
313 std::unique_ptr<Public_Key> pub_key(X509::load_key(data->m_subject_public_key_bits_seq));
314
315 Certificate_Status_Code sig_status = obj.verify_signature(*pub_key);
316
317 if(sig_status == Certificate_Status_Code::OK ||
319 {
320 data->m_self_signed = true;
321 }
322 else
323 {
324 data->m_self_signed = false;
325 }
326 }
327 catch(...)
328 {
329 // ignore errors here to allow parsing to continue
330 }
331 }
332 }
333
334 const std::vector<uint8_t> full_encoding = obj.BER_encode();
335
336 std::unique_ptr<HashFunction> sha1(HashFunction::create("SHA-1"));
337 if(sha1)
338 {
339 sha1->update(data->m_subject_public_key_bitstring);
340 data->m_subject_public_key_bitstring_sha1 = sha1->final_stdvec();
341 // otherwise left as empty, and we will throw if subject_public_key_bitstring_sha1 is called
342
343 data->m_fingerprint_sha1 = create_hex_fingerprint(full_encoding, "SHA-1");
344 }
345
346 std::unique_ptr<HashFunction> sha256(HashFunction::create("SHA-256"));
347 if(sha256)
348 {
349 sha256->update(data->m_issuer_dn_bits);
350 data->m_issuer_dn_bits_sha256 = sha256->final_stdvec();
351
352 sha256->update(data->m_subject_dn_bits);
353 data->m_subject_dn_bits_sha256 = sha256->final_stdvec();
354
355 data->m_fingerprint_sha256 = create_hex_fingerprint(full_encoding, "SHA-256");
356 }
357
358 return data;
359 }
360
361}
362
363/*
364* Decode the TBSCertificate data
365*/
366void X509_Certificate::force_decode()
367 {
368 m_data.reset();
369 m_data = parse_x509_cert_body(*this);
370 }
371
372const X509_Certificate_Data& X509_Certificate::data() const
373 {
374 if(m_data == nullptr)
375 {
376 throw Invalid_State("X509_Certificate uninitialized");
377 }
378 return *m_data.get();
379 }
380
382 {
383 return static_cast<uint32_t>(data().m_version);
384 }
385
387 {
388 return data().m_self_signed;
389 }
390
392 {
393 return data().m_not_before;
394 }
395
397 {
398 return data().m_not_after;
399 }
400
402 {
403 return data().m_subject_public_key_algid;
404 }
405
406const std::vector<uint8_t>& X509_Certificate::v2_issuer_key_id() const
407 {
408 return data().m_v2_issuer_key_id;
409 }
410
411const std::vector<uint8_t>& X509_Certificate::v2_subject_key_id() const
412 {
413 return data().m_v2_subject_key_id;
414 }
415
416const std::vector<uint8_t>& X509_Certificate::subject_public_key_bits() const
417 {
418 return data().m_subject_public_key_bits;
419 }
420
421const std::vector<uint8_t>& X509_Certificate::subject_public_key_info() const
422 {
423 return data().m_subject_public_key_bits_seq;
424 }
425
426const std::vector<uint8_t>& X509_Certificate::subject_public_key_bitstring() const
427 {
428 return data().m_subject_public_key_bitstring;
429 }
430
432 {
433 if(data().m_subject_public_key_bitstring_sha1.empty())
434 throw Encoding_Error("X509_Certificate::subject_public_key_bitstring_sha1 called but SHA-1 disabled in build");
435
436 return data().m_subject_public_key_bitstring_sha1;
437 }
438
439const std::vector<uint8_t>& X509_Certificate::authority_key_id() const
440 {
441 return data().m_authority_key_id;
442 }
443
444const std::vector<uint8_t>& X509_Certificate::subject_key_id() const
445 {
446 return data().m_subject_key_id;
447 }
448
449const std::vector<uint8_t>& X509_Certificate::serial_number() const
450 {
451 return data().m_serial;
452 }
453
455 {
456 return data().m_serial_negative;
457 }
458
459
461 {
462 return data().m_issuer_dn;
463 }
464
466 {
467 return data().m_subject_dn;
468 }
469
470const std::vector<uint8_t>& X509_Certificate::raw_issuer_dn() const
471 {
472 return data().m_issuer_dn_bits;
473 }
474
475const std::vector<uint8_t>& X509_Certificate::raw_subject_dn() const
476 {
477 return data().m_subject_dn_bits;
478 }
479
481 {
482 if(data().m_version < 3 && data().m_self_signed)
483 return true;
484
485 return data().m_is_ca_certificate;
486 }
487
489 {
490 if(data().m_version < 3 && data().m_self_signed)
491 return 32; // in theory infinite, but this is more than enough
492
493 return static_cast<uint32_t>(data().m_path_len_constraint);
494 }
495
497 {
498 return data().m_key_constraints;
499 }
500
501const std::vector<OID>& X509_Certificate::extended_key_usage() const
502 {
503 return data().m_extended_key_usage;
504 }
505
506const std::vector<OID>& X509_Certificate::certificate_policy_oids() const
507 {
508 return data().m_cert_policies;
509 }
510
512 {
513 return data().m_name_constraints;
514 }
515
517 {
518 return data().m_v3_extensions;
519 }
520
522 {
524 return true;
525 return ((constraints() & usage) == usage);
526 }
527
528bool X509_Certificate::allowed_extended_usage(const std::string& usage) const
529 {
531 }
532
534 {
535 const std::vector<OID>& ex = extended_key_usage();
536 if(ex.empty())
537 return true;
538
539 if(std::find(ex.begin(), ex.end(), usage) != ex.end())
540 return true;
541
542 return false;
543 }
544
546 {
547 // These follow suggestions in RFC 5280 4.2.1.12
548
549 switch(usage)
550 {
552 return true;
553
556
559
562
564 return is_CA_cert();
565
568 }
569
570 return false;
571 }
572
574 {
575 if(this->constraints() == NO_CONSTRAINTS)
576 {
577 return false;
578 }
579
580 return ((this->constraints() & constraints) != 0);
581 }
582
584 {
585 const std::vector<OID>& ex = extended_key_usage();
586 return (std::find(ex.begin(), ex.end(), usage) != ex.end());
587 }
588
589/*
590* Return if a certificate extension is marked critical
591*/
592bool X509_Certificate::is_critical(const std::string& ex_name) const
593 {
595 }
596
598 {
599 return data().m_ocsp_responder;
600 }
601
602std::vector<std::string> X509_Certificate::ca_issuers() const
603 {
604 return data().m_ca_issuers;
605 }
606
608 {
609 // just returns the first (arbitrarily)
610 if(!data().m_crl_distribution_points.empty())
611 return data().m_crl_distribution_points[0];
612 return "";
613 }
614
616 {
617 return data().m_subject_alt_name;
618 }
619
621 {
622 return data().m_issuer_alt_name;
623 }
624
625/*
626* Return information about the subject
627*/
628std::vector<std::string>
629X509_Certificate::subject_info(const std::string& req) const
630 {
631 if(req == "Email")
632 return this->subject_info("RFC822");
633
634 if(subject_dn().has_field(req))
635 return subject_dn().get_attribute(req);
636
637 if(subject_alt_name().has_field(req))
638 return subject_alt_name().get_attribute(req);
639
640 return {};
641 }
642
643/*
644* Return information about the issuer
645*/
646std::vector<std::string>
647X509_Certificate::issuer_info(const std::string& req) const
648 {
649 if(issuer_dn().has_field(req))
650 return issuer_dn().get_attribute(req);
651
652 if(issuer_alt_name().has_field(req))
653 return issuer_alt_name().get_attribute(req);
654
655 return {};
656 }
657
658/*
659* Return the public key in this certificate
660*/
661std::unique_ptr<Public_Key> X509_Certificate::load_subject_public_key() const
662 {
663 try
664 {
665 return std::unique_ptr<Public_Key>(X509::load_key(subject_public_key_info()));
666 }
667 catch(std::exception& e)
668 {
669 throw Decoding_Error("X509_Certificate::load_subject_public_key", e);
670 }
671 }
672
674 {
675 return load_subject_public_key().release();
676 }
677
678std::vector<uint8_t> X509_Certificate::raw_issuer_dn_sha256() const
679 {
680 if(data().m_issuer_dn_bits_sha256.empty())
681 throw Encoding_Error("X509_Certificate::raw_issuer_dn_sha256 called but SHA-256 disabled in build");
682 return data().m_issuer_dn_bits_sha256;
683 }
684
685std::vector<uint8_t> X509_Certificate::raw_subject_dn_sha256() const
686 {
687 if(data().m_subject_dn_bits_sha256.empty())
688 throw Encoding_Error("X509_Certificate::raw_subject_dn_sha256 called but SHA-256 disabled in build");
689 return data().m_subject_dn_bits_sha256;
690 }
691
692std::string X509_Certificate::fingerprint(const std::string& hash_name) const
693 {
694 /*
695 * The SHA-1 and SHA-256 fingerprints are precomputed since these
696 * are the most commonly used. Especially, SHA-256 fingerprints are
697 * used for cycle detection during path construction.
698 *
699 * If SHA-1 or SHA-256 was missing at parsing time the vectors are
700 * left empty in which case we fall back to create_hex_fingerprint
701 * which will throw if the hash is unavailable.
702 */
703 if(hash_name == "SHA-256" && !data().m_fingerprint_sha256.empty())
704 return data().m_fingerprint_sha256;
705 else if(hash_name == "SHA-1" && !data().m_fingerprint_sha1.empty())
706 return data().m_fingerprint_sha1;
707 else
708 return create_hex_fingerprint(this->BER_encode(), hash_name);
709 }
710
711bool X509_Certificate::matches_dns_name(const std::string& name) const
712 {
713 if(name.empty())
714 return false;
715
716 auto issued_names = subject_info("DNS");
717
718 // Fall back to CN only if no DNS names are set (RFC 6125 sec 6.4.4)
719 if(issued_names.empty())
720 issued_names = subject_info("Name");
721
722 for(const auto& issued_name : issued_names)
723 {
724 if(host_wildcard_match(issued_name, name))
725 return true;
726 }
727
728 return false;
729 }
730
731/*
732* Compare two certificates for equality
733*/
735 {
736 return (this->signature() == other.signature() &&
737 this->signature_algorithm() == other.signature_algorithm() &&
738 this->signed_body() == other.signed_body());
739 }
740
742 {
743 /* If signature values are not equal, sort by lexicographic ordering of that */
744 if(this->signature() != other.signature())
745 {
746 return (this->signature() < other.signature());
747 }
748
749 // Then compare the signed contents
750 return this->signed_body() < other.signed_body();
751 }
752
753/*
754* X.509 Certificate Comparison
755*/
756bool operator!=(const X509_Certificate& cert1, const X509_Certificate& cert2)
757 {
758 return !(cert1 == cert2);
759 }
760
762 {
763 std::ostringstream out;
764
765 out << "Version: " << this->x509_version() << "\n";
766 out << "Subject: " << subject_dn() << "\n";
767 out << "Issuer: " << issuer_dn() << "\n";
768 out << "Issued: " << this->not_before().readable_string() << "\n";
769 out << "Expires: " << this->not_after().readable_string() << "\n";
770
771 out << "Constraints:\n";
773 if(constraints == NO_CONSTRAINTS)
774 out << " None\n";
775 else
776 {
778 out << " Digital Signature\n";
780 out << " Non-Repudiation\n";
782 out << " Key Encipherment\n";
784 out << " Data Encipherment\n";
786 out << " Key Agreement\n";
788 out << " Cert Sign\n";
790 out << " CRL Sign\n";
792 out << " Encipher Only\n";
794 out << " Decipher Only\n";
795 }
796
797 const std::vector<OID>& policies = this->certificate_policy_oids();
798 if(!policies.empty())
799 {
800 out << "Policies: " << "\n";
801 for(const auto& oid : policies)
802 out << " " << oid.to_string() << "\n";
803 }
804
805 const std::vector<OID>& ex_constraints = this->extended_key_usage();
806 if(!ex_constraints.empty())
807 {
808 out << "Extended Constraints:\n";
809 for(auto&& oid : ex_constraints)
810 {
811 out << " " << oid.to_formatted_string() << "\n";
812 }
813 }
814
816
817 if(!name_constraints.permitted().empty() || !name_constraints.excluded().empty())
818 {
819 out << "Name Constraints:\n";
820
821 if(!name_constraints.permitted().empty())
822 {
823 out << " Permit";
824 for(const auto& st: name_constraints.permitted())
825 {
826 out << " " << st.base();
827 }
828 out << "\n";
829 }
830
831 if(!name_constraints.excluded().empty())
832 {
833 out << " Exclude";
834 for(const auto& st: name_constraints.excluded())
835 {
836 out << " " << st.base();
837 }
838 out << "\n";
839 }
840 }
841
842 if(!ocsp_responder().empty())
843 out << "OCSP responder " << ocsp_responder() << "\n";
844
845 const std::vector<std::string> ca_issuers = this->ca_issuers();
846 if(!ca_issuers.empty())
847 {
848 out << "CA Issuers:\n";
849 for(const auto& ca_issuer : ca_issuers)
850 out << " URI: " << ca_issuer << "\n";
851 }
852
853 if(!crl_distribution_point().empty())
854 out << "CRL " << crl_distribution_point() << "\n";
855
856 out << "Signature algorithm: " << this->signature_algorithm().get_oid().to_formatted_string() << "\n";
857
858 out << "Serial number: " << hex_encode(this->serial_number()) << "\n";
859
860 if(!this->authority_key_id().empty())
861 out << "Authority keyid: " << hex_encode(this->authority_key_id()) << "\n";
862
863 if(!this->subject_key_id().empty())
864 out << "Subject keyid: " << hex_encode(this->subject_key_id()) << "\n";
865
866 try
867 {
868 std::unique_ptr<Public_Key> pubkey(this->subject_public_key());
869 out << "Public Key [" << pubkey->algo_name() << "-" << pubkey->key_length() << "]\n\n";
870 out << X509::PEM_encode(*pubkey);
871 }
872 catch(Decoding_Error&)
873 {
874 const AlgorithmIdentifier& alg_id = this->subject_public_key_algo();
875 out << "Failed to decode key with oid " << alg_id.get_oid().to_string() << "\n";
876 }
877
878 return out.str();
879 }
880
881}
std::vector< uint8_t > BER_encode() const
Definition: asn1_obj.cpp:16
std::string readable_string() const
Returns a human friendly string replesentation of no particular formatting.
Definition: asn1_time.cpp:103
const OID & get_oid() const
Definition: asn1_obj.h:447
std::vector< std::string > get_attribute(const std::string &attr) const
static std::vector< uint8_t > encode(const BigInt &n)
Definition: bigint.h:765
bool critical_extension_set(const OID &oid) const
Definition: x509_ext.cpp:175
static std::unique_ptr< HashFunction > create(const std::string &algo_spec, const std::string &provider="")
Definition: hash.cpp:98
Name Constraints.
Definition: pkix_types.h:314
const std::vector< GeneralSubtree > & permitted() const
Definition: pkix_types.h:334
const std::vector< GeneralSubtree > & excluded() const
Definition: pkix_types.h:339
std::string to_formatted_string() const
Definition: asn1_oid.cpp:109
static OID from_string(const std::string &str)
Definition: asn1_oid.cpp:61
std::string to_string() const
Definition: asn1_oid.cpp:97
const std::vector< OID > & extended_key_usage() const
Definition: x509cert.cpp:501
bool is_CA_cert() const
Definition: x509cert.cpp:480
Key_Constraints constraints() const
Definition: x509cert.cpp:496
bool operator==(const X509_Certificate &other) const
Definition: x509cert.cpp:734
const NameConstraints & name_constraints() const
Definition: x509cert.cpp:511
std::vector< std::string > issuer_info(const std::string &name) const
Definition: x509cert.cpp:647
const std::vector< uint8_t > & serial_number() const
Definition: x509cert.cpp:449
const X509_DN & subject_dn() const
Definition: x509cert.cpp:465
std::vector< uint8_t > raw_subject_dn_sha256() const
Definition: x509cert.cpp:685
bool allowed_extended_usage(const std::string &usage) const
Definition: x509cert.cpp:528
uint32_t path_limit() const
Definition: x509cert.cpp:488
const X509_Time & not_after() const
Definition: x509cert.cpp:396
const std::vector< uint8_t > & authority_key_id() const
Definition: x509cert.cpp:439
const AlternativeName & issuer_alt_name() const
Definition: x509cert.cpp:620
const std::vector< uint8_t > & raw_subject_dn() const
Definition: x509cert.cpp:475
const std::vector< uint8_t > & subject_key_id() const
Definition: x509cert.cpp:444
bool has_ex_constraint(const OID &ex_constraint) const
Definition: x509cert.cpp:583
const std::vector< uint8_t > & subject_public_key_bits() const
Definition: x509cert.cpp:416
bool has_constraints(Key_Constraints constraints) const
Definition: x509cert.cpp:573
const Extensions & v3_extensions() const
Definition: x509cert.cpp:516
std::vector< std::string > subject_info(const std::string &name) const
Definition: x509cert.cpp:629
const std::vector< uint8_t > & subject_public_key_bitstring_sha1() const
Definition: x509cert.cpp:431
bool allowed_usage(Key_Constraints usage) const
Definition: x509cert.cpp:521
const X509_DN & issuer_dn() const
Definition: x509cert.cpp:460
const std::vector< uint8_t > & v2_issuer_key_id() const
Definition: x509cert.cpp:406
std::string ocsp_responder() const
Definition: x509cert.cpp:597
uint32_t x509_version() const
Definition: x509cert.cpp:381
std::string crl_distribution_point() const
Definition: x509cert.cpp:607
const std::vector< OID > & certificate_policy_oids() const
Definition: x509cert.cpp:506
std::unique_ptr< Public_Key > load_subject_public_key() const
Definition: x509cert.cpp:661
bool is_self_signed() const
Definition: x509cert.cpp:386
const std::vector< uint8_t > & raw_issuer_dn() const
Definition: x509cert.cpp:470
bool operator<(const X509_Certificate &other) const
Definition: x509cert.cpp:741
Public_Key * subject_public_key() const
Definition: x509cert.cpp:673
const AlgorithmIdentifier & subject_public_key_algo() const
Definition: x509cert.cpp:401
bool matches_dns_name(const std::string &name) const
Definition: x509cert.cpp:711
const AlternativeName & subject_alt_name() const
Definition: x509cert.cpp:615
std::vector< std::string > ca_issuers() const
Definition: x509cert.cpp:602
const std::vector< uint8_t > & subject_public_key_info() const
Definition: x509cert.cpp:421
std::vector< uint8_t > raw_issuer_dn_sha256() const
Definition: x509cert.cpp:678
bool is_serial_negative() const
Definition: x509cert.cpp:454
const std::vector< uint8_t > & subject_public_key_bitstring() const
Definition: x509cert.cpp:426
std::string fingerprint(const std::string &hash_name="SHA-1") const
Definition: x509cert.cpp:692
const std::vector< uint8_t > & v2_subject_key_id() const
Definition: x509cert.cpp:411
const X509_Time & not_before() const
Definition: x509cert.cpp:391
std::string to_string() const
Definition: x509cert.cpp:761
bool is_critical(const std::string &ex_name) const
Definition: x509cert.cpp:592
std::vector< std::string > get_attribute(const std::string &attr) const
Definition: x509_dn.cpp:168
const std::vector< uint8_t > & signed_body() const
Definition: x509_obj.h:43
const AlgorithmIdentifier & signature_algorithm() const
Definition: x509_obj.h:48
const std::vector< uint8_t > & signature() const
Definition: x509_obj.h:38
void load_data(DataSource &src)
Definition: x509_obj.cpp:52
std::string name
std::vector< uint8_t > put_in_sequence(const std::vector< uint8_t > &contents)
Definition: asn1_obj.cpp:191
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:209
BOTAN_UNSTABLE_API std::string oid2str_or_empty(const OID &oid)
Definition: oids.cpp:105
Public_Key * load_key(DataSource &source)
Definition: x509_key.cpp:29
std::string PEM_encode(const Public_Key &key)
Definition: x509_key.cpp:20
Definition: alg_id.cpp:13
ASN1_Time X509_Time
Definition: asn1_obj.h:389
ASN1_Type
Definition: asn1_obj.h:39
bool host_wildcard_match(const std::string &issued_, const std::string &host_)
Definition: parsing.cpp:211
bool operator!=(const AlgorithmIdentifier &a1, const AlgorithmIdentifier &a2)
Definition: alg_id.cpp:82
std::vector< std::string > split_on(const std::string &str, char delim)
Definition: parsing.cpp:111
void hex_encode(char output[], const uint8_t input[], size_t input_length, bool uppercase)
Definition: hex.cpp:31
Usage_Type
Definition: x509cert.h:23
std::string create_hex_fingerprint(const uint8_t bits[], size_t bits_len, const std::string &hash_name)
Definition: pk_keys.cpp:17
Certificate_Status_Code
Definition: pkix_enums.h:17
Key_Constraints
Definition: pkix_enums.h:102
@ DATA_ENCIPHERMENT
Definition: pkix_enums.h:107
@ CRL_SIGN
Definition: pkix_enums.h:110
@ KEY_CERT_SIGN
Definition: pkix_enums.h:109
@ NO_CONSTRAINTS
Definition: pkix_enums.h:103
@ ENCIPHER_ONLY
Definition: pkix_enums.h:111
@ DIGITAL_SIGNATURE
Definition: pkix_enums.h:104
@ KEY_AGREEMENT
Definition: pkix_enums.h:108
@ DECIPHER_ONLY
Definition: pkix_enums.h:112
@ KEY_ENCIPHERMENT
Definition: pkix_enums.h:106
@ NON_REPUDIATION
Definition: pkix_enums.h:105