Botan 2.13.0 Crypto and TLS for C++11

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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