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
24 namespace Botan {
25
26 struct 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
86 X509_Certificate::X509_Certificate(DataSource& src)
87 {
88 load_data(src);
89 }
90
91 X509_Certificate::X509_Certificate(const std::vector<uint8_t>& vec)
92 {
93 DataSource_Memory src(vec.data(), vec.size());
94 load_data(src);
95 }
96
97 X509_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)
104 X509_Certificate::X509_Certificate(const std::string& fsname)
105 {
106 DataSource_Stream src(fsname, true);
107 load_data(src);
108 }
109#endif
110
111 namespace {
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 ||
323 sig_status == Certificate_Status_Code::SIGNATURE_ALGO_UNKNOWN)
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*/
375 void 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
384 const 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
393uint32_t X509_Certificate::x509_version() const
394 {
395 return static_cast<uint32_t>(data().m_version);
396 }
397
398 bool X509_Certificate::is_self_signed() const
399 {
400 return data().m_self_signed;
401 }
402
403 const X509_Time& X509_Certificate::not_before() const
404 {
405 return data().m_not_before;
406 }
407
408 const X509_Time& X509_Certificate::not_after() const
409 {
410 return data().m_not_after;
411 }
412
413 const AlgorithmIdentifier& X509_Certificate::subject_public_key_algo() const
414 {
415 return data().m_subject_public_key_algid;
416 }
417
418 const std::vector<uint8_t>& X509_Certificate::v2_issuer_key_id() const
419 {
420 return data().m_v2_issuer_key_id;
421 }
422
423 const std::vector<uint8_t>& X509_Certificate::v2_subject_key_id() const
424 {
425 return data().m_v2_subject_key_id;
426 }
427
428 const std::vector<uint8_t>& X509_Certificate::subject_public_key_bits() const
429 {
430 return data().m_subject_public_key_bits;
431 }
432
433 const std::vector<uint8_t>& X509_Certificate::subject_public_key_info() const
434 {
435 return data().m_subject_public_key_bits_seq;
436 }
437
438 const std::vector<uint8_t>& X509_Certificate::subject_public_key_bitstring() const
439 {
440 return data().m_subject_public_key_bitstring;
441 }
442
443 const std::vector<uint8_t>& X509_Certificate::subject_public_key_bitstring_sha1() const
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
451 const std::vector<uint8_t>& X509_Certificate::authority_key_id() const
452 {
453 return data().m_authority_key_id;
454 }
455
456 const std::vector<uint8_t>& X509_Certificate::subject_key_id() const
457 {
458 return data().m_subject_key_id;
459 }
460
461 const std::vector<uint8_t>& X509_Certificate::serial_number() const
462 {
463 return data().m_serial;
464 }
465
466 bool X509_Certificate::is_serial_negative() const
467 {
468 return data().m_serial_negative;
469 }
470
471
472 const X509_DN& X509_Certificate::issuer_dn() const
473 {
474 return data().m_issuer_dn;
475 }
476
477 const X509_DN& X509_Certificate::subject_dn() const
478 {
479 return data().m_subject_dn;
480 }
481
482 const std::vector<uint8_t>& X509_Certificate::raw_issuer_dn() const
483 {
484 return data().m_issuer_dn_bits;
485 }
486
487 const std::vector<uint8_t>& X509_Certificate::raw_subject_dn() const
488 {
489 return data().m_subject_dn_bits;
490 }
491
492 bool X509_Certificate::is_CA_cert() const
493 {
494 if(data().m_version < 3 && data().m_self_signed)
495 return true;
496
497 return data().m_is_ca_certificate;
498 }
499
500uint32_t X509_Certificate::path_limit() const
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
508 Key_Constraints X509_Certificate::constraints() const
509 {
510 return data().m_key_constraints;
511 }
512
513 const std::vector<OID>& X509_Certificate::extended_key_usage() const
514 {
515 return data().m_extended_key_usage;
516 }
517
518 const std::vector<OID>& X509_Certificate::certificate_policy_oids() const
519 {
520 return data().m_cert_policies;
521 }
522
523 const NameConstraints& X509_Certificate::name_constraints() const
524 {
525 return data().m_name_constraints;
526 }
527
528 const Extensions& X509_Certificate::v3_extensions() const
529 {
530 return data().m_v3_extensions;
531 }
532
533 bool X509_Certificate::allowed_usage(Key_Constraints usage) const
534 {
535 if(constraints() == NO_CONSTRAINTS)
536 return true;
537 return ((constraints() & usage) == usage);
538 }
539
540 bool X509_Certificate::allowed_extended_usage(const std::string& usage) const
541 {
542 return allowed_extended_usage(OID::from_string(usage));
543 }
544
545 bool X509_Certificate::allowed_extended_usage(const OID& usage) const
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
557 bool X509_Certificate::allowed_usage(Usage_Type usage) const
558 {
559 // These follow suggestions in RFC 5280 4.2.1.12
560
561 switch(usage)
562 {
563 case Usage_Type::UNSPECIFIED:
564 return true;
565
566 case Usage_Type::TLS_SERVER_AUTH:
567 return (allowed_usage(KEY_AGREEMENT) || allowed_usage(KEY_ENCIPHERMENT) || allowed_usage(DIGITAL_SIGNATURE)) && allowed_extended_usage("PKIX.ServerAuth");
568
569 case Usage_Type::TLS_CLIENT_AUTH:
570 return (allowed_usage(DIGITAL_SIGNATURE) || allowed_usage(KEY_AGREEMENT)) && allowed_extended_usage("PKIX.ClientAuth");
571
572 case Usage_Type::OCSP_RESPONDER:
573 return (allowed_usage(DIGITAL_SIGNATURE) || allowed_usage(NON_REPUDIATION)) && allowed_extended_usage("PKIX.OCSPSigning");
574
575 case Usage_Type::CERTIFICATE_AUTHORITY:
576 return is_CA_cert();
577
578 case Usage_Type::ENCRYPTION:
579 return (allowed_usage(KEY_ENCIPHERMENT) || allowed_usage(DATA_ENCIPHERMENT));
580 }
581
582 return false;
583 }
584
585 bool X509_Certificate::has_constraints(Key_Constraints constraints) const
586 {
587 if(this->constraints() == NO_CONSTRAINTS)
588 {
589 return false;
590 }
591
592 return ((this->constraints() & constraints) != 0);
593 }
594
595 bool X509_Certificate::has_ex_constraint(const std::string& ex_constraint) const
596 {
597 return has_ex_constraint(OID::from_string(ex_constraint));
598 }
599
600 bool X509_Certificate::has_ex_constraint(const OID& usage) const
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*/
609 bool X509_Certificate::is_critical(const std::string& ex_name) const
610 {
611 return v3_extensions().critical_extension_set(OID::from_string(ex_name));
612 }
613
614std::string X509_Certificate::ocsp_responder() const
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
624std::string X509_Certificate::crl_distribution_point() const
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
632 const AlternativeName& X509_Certificate::subject_alt_name() const
633 {
634 return data().m_subject_alt_name;
635 }
636
637 const AlternativeName& X509_Certificate::issuer_alt_name() const
638 {
639 return data().m_issuer_alt_name;
640 }
641
642/*
643* Return information about the subject
644*/
645std::vector<std::string>
646 X509_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>
681 X509_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
715 Public_Key* X509_Certificate::subject_public_key() const
716 {
717 return load_subject_public_key().release();
718 }
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
734 namespace {
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
787 bool 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 {
795 string_to_ipv4(name);
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*/
829 bool X509_Certificate::operator==(const X509_Certificate& other) const
830 {
831 return (this->signature() == other.signature() &&
832 this->signature_algorithm() == other.signature_algorithm() &&
833 this->signed_body() == other.signed_body());
834 }
835
836 bool X509_Certificate::operator<(const X509_Certificate& other) const
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*/
851 bool operator!=(const X509_Certificate& cert1, const X509_Certificate& cert2)
852 {
853 return !(cert1 == cert2);
854 }
855
856std::string X509_Certificate::to_string() const
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";
867 Key_Constraints constraints = this->constraints();
868 if(constraints == NO_CONSTRAINTS)
869 out << " None\n";
870 else
871 {
872 if(constraints & DIGITAL_SIGNATURE)
873 out << " Digital Signature\n";
874 if(constraints & NON_REPUDIATION)
875 out << " Non-Repudiation\n";
876 if(constraints & KEY_ENCIPHERMENT)
877 out << " Key Encipherment\n";
878 if(constraints & DATA_ENCIPHERMENT)
879 out << " Data Encipherment\n";
880 if(constraints & KEY_AGREEMENT)
881 out << " Key Agreement\n";
882 if(constraints & KEY_CERT_SIGN)
883 out << " Cert Sign\n";
884 if(constraints & CRL_SIGN)
885 out << " CRL Sign\n";
886 if(constraints & ENCIPHER_ONLY)
887 out << " Encipher Only\n";
888 if(constraints & DECIPHER_ONLY)
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
910 const NameConstraints& name_constraints = this->name_constraints();
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}
Botan::ASN1_Object::BER_encode
std::vector< uint8_t > BER_encode() const
Definition: asn1_obj.cpp:16
Botan::ASN1_Time
Definition: asn1_obj.h:328
Botan::ASN1_Time::to_string
std::string to_string() const
Return an internal string representation of the time.
Definition: asn1_time.cpp:53
Botan::ASN1_Time::readable_string
std::string readable_string() const
Returns a human friendly string replesentation of no particular formatting.
Definition: asn1_time.cpp:93
Botan::AlgorithmIdentifier
Definition: asn1_obj.h:430
Botan::AlgorithmIdentifier::USE_NULL_PARAM
@ USE_NULL_PARAM
Definition: asn1_obj.h:432
Botan::AlgorithmIdentifier::get_oid
const OID & get_oid() const
Definition: asn1_obj.h:445
Botan::AlternativeName
Definition: pkix_types.h:124
Botan::AlternativeName::get_attribute
std::vector< std::string > get_attribute(const std::string &attr) const
Definition: asn1_alt_name.cpp:98
Botan::BigInt::encode
static std::vector< uint8_t > encode(const BigInt &n)
Definition: bigint.h:782
Botan::DataSource_Memory
Definition: data_src.h:99
Botan::DataSource_Stream
Definition: data_src.h:144
Botan::DataSource
Definition: data_src.h:22
Botan::Decoding_Error
Definition: exceptn.h:200
Botan::Encoding_Error
Definition: exceptn.h:185
Botan::Extensions
Definition: pkix_types.h:436
Botan::Extensions::critical_extension_set
bool critical_extension_set(const OID &oid) const
Definition: x509_ext.cpp:182
Botan::HashFunction::create
static std::unique_ptr< HashFunction > create(const std::string &algo_spec, const std::string &provider="")
Definition: hash.cpp:102
Botan::NameConstraints
Name Constraints.
Definition: pkix_types.h:327
Botan::NameConstraints::permitted
const std::vector< GeneralSubtree > & permitted() const
Definition: pkix_types.h:345
Botan::NameConstraints::excluded
const std::vector< GeneralSubtree > & excluded() const
Definition: pkix_types.h:350
Botan::OID
Definition: asn1_obj.h:194
Botan::OID::to_formatted_string
std::string to_formatted_string() const
Definition: asn1_oid.cpp:111
Botan::OID::from_string
static OID from_string(const std::string &str)
Definition: asn1_oid.cpp:62
Botan::OID::to_string
std::string to_string() const
Definition: asn1_oid.cpp:98
Botan::Public_Key
Definition: pk_keys.h:29
Botan::X509_Certificate
Definition: x509cert.h:38
Botan::X509_Certificate::extended_key_usage
const std::vector< OID > & extended_key_usage() const
Definition: x509cert.cpp:513
Botan::X509_Certificate::is_CA_cert
bool is_CA_cert() const
Definition: x509cert.cpp:492
Botan::X509_Certificate::constraints
Key_Constraints constraints() const
Definition: x509cert.cpp:508
Botan::X509_Certificate::operator==
bool operator==(const X509_Certificate &other) const
Definition: x509cert.cpp:829
Botan::X509_Certificate::name_constraints
const NameConstraints & name_constraints() const
Definition: x509cert.cpp:523
Botan::X509_Certificate::X509_Certificate
X509_Certificate()=default
Botan::X509_Certificate::issuer_info
std::vector< std::string > issuer_info(const std::string &name) const
Definition: x509cert.cpp:681
Botan::X509_Certificate::serial_number
const std::vector< uint8_t > & serial_number() const
Definition: x509cert.cpp:461
Botan::X509_Certificate::ex_constraints
std::vector< std::string > ex_constraints() const
Definition: x509cert.cpp:755
Botan::X509_Certificate::subject_dn
const X509_DN & subject_dn() const
Definition: x509cert.cpp:477
Botan::X509_Certificate::raw_subject_dn_sha256
std::vector< uint8_t > raw_subject_dn_sha256() const
Definition: x509cert.cpp:727
Botan::X509_Certificate::allowed_extended_usage
bool allowed_extended_usage(const std::string &usage) const
Definition: x509cert.cpp:540
Botan::X509_Certificate::path_limit
uint32_t path_limit() const
Definition: x509cert.cpp:500
Botan::X509_Certificate::not_after
const X509_Time & not_after() const
Definition: x509cert.cpp:408
Botan::X509_Certificate::authority_key_id
const std::vector< uint8_t > & authority_key_id() const
Definition: x509cert.cpp:451
Botan::X509_Certificate::issuer_alt_name
const AlternativeName & issuer_alt_name() const
Definition: x509cert.cpp:637
Botan::X509_Certificate::raw_subject_dn
const std::vector< uint8_t > & raw_subject_dn() const
Definition: x509cert.cpp:487
Botan::X509_Certificate::subject_key_id
const std::vector< uint8_t > & subject_key_id() const
Definition: x509cert.cpp:456
Botan::X509_Certificate::subject_public_key_bits
const std::vector< uint8_t > & subject_public_key_bits() const
Definition: x509cert.cpp:428
Botan::X509_Certificate::has_constraints
bool has_constraints(Key_Constraints constraints) const
Definition: x509cert.cpp:585
Botan::X509_Certificate::v3_extensions
const Extensions & v3_extensions() const
Definition: x509cert.cpp:528
Botan::X509_Certificate::subject_info
std::vector< std::string > subject_info(const std::string &name) const
Definition: x509cert.cpp:646
Botan::X509_Certificate::subject_public_key_bitstring_sha1
const std::vector< uint8_t > & subject_public_key_bitstring_sha1() const
Definition: x509cert.cpp:443
Botan::X509_Certificate::allowed_usage
bool allowed_usage(Key_Constraints usage) const
Definition: x509cert.cpp:533
Botan::X509_Certificate::issuer_dn
const X509_DN & issuer_dn() const
Definition: x509cert.cpp:472
Botan::X509_Certificate::v2_issuer_key_id
const std::vector< uint8_t > & v2_issuer_key_id() const
Definition: x509cert.cpp:418
Botan::X509_Certificate::ocsp_responder
std::string ocsp_responder() const
Definition: x509cert.cpp:614
Botan::X509_Certificate::has_ex_constraint
bool has_ex_constraint(const std::string &ex_constraint) const
Definition: x509cert.cpp:595
Botan::X509_Certificate::x509_version
uint32_t x509_version() const
Definition: x509cert.cpp:393
Botan::X509_Certificate::policies
std::vector< std::string > policies() const
Definition: x509cert.cpp:763
Botan::X509_Certificate::crl_distribution_point
std::string crl_distribution_point() const
Definition: x509cert.cpp:624
Botan::X509_Certificate::certificate_policy_oids
const std::vector< OID > & certificate_policy_oids() const
Definition: x509cert.cpp:518
Botan::X509_Certificate::load_subject_public_key
std::unique_ptr< Public_Key > load_subject_public_key() const
Definition: x509cert.cpp:703
Botan::X509_Certificate::is_self_signed
bool is_self_signed() const
Definition: x509cert.cpp:398
Botan::X509_Certificate::raw_issuer_dn
const std::vector< uint8_t > & raw_issuer_dn() const
Definition: x509cert.cpp:482
Botan::X509_Certificate::operator<
bool operator<(const X509_Certificate &other) const
Definition: x509cert.cpp:836
Botan::X509_Certificate::subject_public_key
Public_Key * subject_public_key() const
Definition: x509cert.cpp:715
Botan::X509_Certificate::subject_public_key_algo
const AlgorithmIdentifier & subject_public_key_algo() const
Definition: x509cert.cpp:413
Botan::X509_Certificate::matches_dns_name
bool matches_dns_name(const std::string &name) const
Definition: x509cert.cpp:787
Botan::X509_Certificate::subject_alt_name
const AlternativeName & subject_alt_name() const
Definition: x509cert.cpp:632
Botan::X509_Certificate::ca_issuers
std::vector< std::string > ca_issuers() const
Definition: x509cert.cpp:619
Botan::X509_Certificate::subject_public_key_info
const std::vector< uint8_t > & subject_public_key_info() const
Definition: x509cert.cpp:433
Botan::X509_Certificate::raw_issuer_dn_sha256
std::vector< uint8_t > raw_issuer_dn_sha256() const
Definition: x509cert.cpp:720
Botan::X509_Certificate::is_serial_negative
bool is_serial_negative() const
Definition: x509cert.cpp:466
Botan::X509_Certificate::subject_public_key_bitstring
const std::vector< uint8_t > & subject_public_key_bitstring() const
Definition: x509cert.cpp:438
Botan::X509_Certificate::fingerprint
std::string fingerprint(const std::string &hash_name="SHA-1") const
Definition: x509cert.cpp:768
Botan::X509_Certificate::v2_subject_key_id
const std::vector< uint8_t > & v2_subject_key_id() const
Definition: x509cert.cpp:423
Botan::X509_Certificate::not_before
const X509_Time & not_before() const
Definition: x509cert.cpp:403
Botan::X509_Certificate::to_string
std::string to_string() const
Definition: x509cert.cpp:856
Botan::X509_Certificate::is_critical
bool is_critical(const std::string &ex_name) const
Definition: x509cert.cpp:609
Botan::X509_DN
Definition: pkix_types.h:43
Botan::X509_DN::get_attribute
std::vector< std::string > get_attribute(const std::string &attr) const
Definition: x509_dn.cpp:109
Botan::X509_Object::signed_body
const std::vector< uint8_t > & signed_body() const
Definition: x509_obj.h:42
Botan::X509_Object::signature_algorithm
const AlgorithmIdentifier & signature_algorithm() const
Definition: x509_obj.h:47
Botan::X509_Object::signature
const std::vector< uint8_t > & signature() const
Definition: x509_obj.h:37
Botan::X509_Object::load_data
void load_data(DataSource &src)
Definition: x509_obj.cpp:52
name
std::string name
Definition: commoncrypto_hash.cpp:24
Botan::ASN1::put_in_sequence
std::vector< uint8_t > put_in_sequence(const std::vector< uint8_t > &contents)
Definition: asn1_obj.cpp:195
Botan::ASN1::to_string
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:213
Botan::OIDS::oid2str_or_empty
BOTAN_UNSTABLE_API std::string oid2str_or_empty(const OID &oid)
Definition: oids.cpp:111
Botan::X509::load_key
Public_Key * load_key(DataSource &source)
Definition: x509_key.cpp:37
Botan::X509::PEM_encode
std::string PEM_encode(const Public_Key &key)
Definition: x509_key.cpp:28
Botan
Definition: alg_id.cpp:13
Botan::X509_Time
ASN1_Time X509_Time
Definition: asn1_obj.h:386
Botan::split_on
std::vector< std::string > split_on(const std::string &str, char delim)
Definition: parsing.cpp:148
Botan::string_to_ipv4
uint32_t string_to_ipv4(const std::string &str)
Definition: parsing.cpp:253
Botan::operator!=
bool operator!=(const AlgorithmIdentifier &a1, const AlgorithmIdentifier &a2)
Definition: alg_id.cpp:82
Botan::hex_encode
void hex_encode(char output[], const uint8_t input[], size_t input_length, bool uppercase)
Definition: hex.cpp:31
Botan::Usage_Type
Usage_Type
Definition: x509cert.h:23
Botan::Usage_Type::UNSPECIFIED
@ UNSPECIFIED
Botan::Usage_Type::CERTIFICATE_AUTHORITY
@ CERTIFICATE_AUTHORITY
Botan::Usage_Type::TLS_SERVER_AUTH
@ TLS_SERVER_AUTH
Botan::Usage_Type::OCSP_RESPONDER
@ OCSP_RESPONDER
Botan::Usage_Type::TLS_CLIENT_AUTH
@ TLS_CLIENT_AUTH
Botan::Usage_Type::ENCRYPTION
@ ENCRYPTION
Botan::create_hex_fingerprint
std::string create_hex_fingerprint(const uint8_t bits[], size_t bits_len, const std::string &hash_name)
Definition: pk_keys.cpp:17
Botan::ASN1_Tag
ASN1_Tag
Definition: asn1_obj.h:25
Botan::CONSTRUCTED
@ CONSTRUCTED
Definition: asn1_obj.h:30
Botan::BIT_STRING
@ BIT_STRING
Definition: asn1_obj.h:37
Botan::SEQUENCE
@ SEQUENCE
Definition: asn1_obj.h:42
Botan::CONTEXT_SPECIFIC
@ CONTEXT_SPECIFIC
Definition: asn1_obj.h:28
Botan::Certificate_Status_Code
Certificate_Status_Code
Definition: pkix_enums.h:17
Botan::Certificate_Status_Code::SIGNATURE_ALGO_UNKNOWN
@ SIGNATURE_ALGO_UNKNOWN
Botan::Certificate_Status_Code::OK
@ OK
Botan::host_wildcard_match
bool host_wildcard_match(const std::string &issued_, const std::string &host_)
Definition: parsing.cpp:339
Botan::Key_Constraints
Key_Constraints
Definition: pkix_enums.h:106
Botan::DATA_ENCIPHERMENT
@ DATA_ENCIPHERMENT
Definition: pkix_enums.h:111
Botan::CRL_SIGN
@ CRL_SIGN
Definition: pkix_enums.h:114
Botan::KEY_CERT_SIGN
@ KEY_CERT_SIGN
Definition: pkix_enums.h:113
Botan::NO_CONSTRAINTS
@ NO_CONSTRAINTS
Definition: pkix_enums.h:107
Botan::ENCIPHER_ONLY
@ ENCIPHER_ONLY
Definition: pkix_enums.h:115
Botan::DIGITAL_SIGNATURE
@ DIGITAL_SIGNATURE
Definition: pkix_enums.h:108
Botan::KEY_AGREEMENT
@ KEY_AGREEMENT
Definition: pkix_enums.h:112
Botan::DECIPHER_ONLY
@ DECIPHER_ONLY
Definition: pkix_enums.h:116
Botan::KEY_ENCIPHERMENT
@ KEY_ENCIPHERMENT
Definition: pkix_enums.h:110
Botan::NON_REPUDIATION
@ NON_REPUDIATION
Definition: pkix_enums.h:109