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