Coverage Report

Created: 2024-05-20 06:13

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