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