Botan 1.10.17
x509cert.cpp
Go to the documentation of this file.
1/*
2* X.509 Certificates
3* (C) 1999-2010 Jack Lloyd
4*
5* Distributed under the terms of the Botan license
6*/
7
8#include <botan/x509cert.h>
9#include <botan/x509_ext.h>
10#include <botan/der_enc.h>
11#include <botan/ber_dec.h>
12#include <botan/internal/stl_util.h>
13#include <botan/parsing.h>
14#include <botan/bigint.h>
15#include <botan/oids.h>
16#include <botan/pem.h>
17#include <botan/hex.h>
18#include <algorithm>
19#include <iterator>
20#include <sstream>
21
22namespace Botan {
23
24namespace {
25
26/*
27* Lookup each OID in the vector
28*/
29std::vector<std::string> lookup_oids(const std::vector<std::string>& in)
30 {
31 std::vector<std::string> out;
32
33 std::vector<std::string>::const_iterator i = in.begin();
34 while(i != in.end())
35 {
36 out.push_back(OIDS::lookup(OID(*i)));
37 ++i;
38 }
39 return out;
40 }
41
42}
43
44/*
45* X509_Certificate Constructor
46*/
48 X509_Object(in, "CERTIFICATE/X509 CERTIFICATE")
49 {
50 self_signed = false;
51 do_decode();
52 }
53
54/*
55* X509_Certificate Constructor
56*/
57X509_Certificate::X509_Certificate(const std::string& in) :
58 X509_Object(in, "CERTIFICATE/X509 CERTIFICATE")
59 {
60 self_signed = false;
61 do_decode();
62 }
63
64/*
65* Decode the TBSCertificate data
66*/
67void X509_Certificate::force_decode()
68 {
69 size_t version;
70 BigInt serial_bn;
71 AlgorithmIdentifier sig_algo_inner;
72 X509_DN dn_issuer, dn_subject;
73 X509_Time start, end;
74
75 BER_Decoder tbs_cert(tbs_bits);
76
77 tbs_cert.decode_optional(version, ASN1_Tag(0),
79 .decode(serial_bn)
80 .decode(sig_algo_inner)
81 .decode(dn_issuer)
82 .start_cons(SEQUENCE)
83 .decode(start)
84 .decode(end)
85 .verify_end()
86 .end_cons()
87 .decode(dn_subject);
88
89 if(version > 2)
90 throw Decoding_Error("Unknown X.509 cert version " + Botan::to_string(version));
91 if(sig_algo != sig_algo_inner)
92 throw Decoding_Error("Algorithm identifier mismatch");
93
94 self_signed = (dn_subject == dn_issuer);
95
96 subject.add(dn_subject.contents());
97 issuer.add(dn_issuer.contents());
98
99 BER_Object public_key = tbs_cert.get_next_object();
100 if(public_key.type_tag != SEQUENCE || public_key.class_tag != CONSTRUCTED)
101 throw BER_Bad_Tag("X509_Certificate: Unexpected tag for public key",
102 public_key.type_tag, public_key.class_tag);
103
104 MemoryVector<byte> v2_issuer_key_id, v2_subject_key_id;
105
106 tbs_cert.decode_optional_string(v2_issuer_key_id, BIT_STRING, 1);
107 tbs_cert.decode_optional_string(v2_subject_key_id, BIT_STRING, 2);
108
109 BER_Object v3_exts_data = tbs_cert.get_next_object();
110 if(v3_exts_data.type_tag == 3 &&
112 {
113 Extensions extensions;
114
115 BER_Decoder(v3_exts_data.value).decode(extensions).verify_end();
116
117 extensions.contents_to(subject, issuer);
118 }
119 else if(v3_exts_data.type_tag != NO_OBJECT)
120 throw BER_Bad_Tag("Unknown tag in X.509 cert",
121 v3_exts_data.type_tag, v3_exts_data.class_tag);
122
123 if(tbs_cert.more_items())
124 throw Decoding_Error("TBSCertificate has more items that expected");
125
126 subject.add("X509.Certificate.version", version);
127 subject.add("X509.Certificate.serial", BigInt::encode(serial_bn));
128 subject.add("X509.Certificate.start", start.readable_string());
129 subject.add("X509.Certificate.end", end.readable_string());
130
131 issuer.add("X509.Certificate.v2.key_id", v2_issuer_key_id);
132 subject.add("X509.Certificate.v2.key_id", v2_subject_key_id);
133
134 subject.add("X509.Certificate.public_key",
136 ASN1::put_in_sequence(public_key.value),
137 "PUBLIC KEY"
138 )
139 );
140
141 if(is_CA_cert() &&
142 !subject.has_value("X509v3.BasicConstraints.path_constraint"))
143 {
144 const size_t limit = (x509_version() < 3) ?
145 Cert_Extension::NO_CERT_PATH_LIMIT : 0;
146
147 subject.add("X509v3.BasicConstraints.path_constraint", limit);
148 }
149 }
150
151/*
152* Return the X.509 version in use
153*/
155 {
156 return (subject.get1_u32bit("X509.Certificate.version") + 1);
157 }
158
159/*
160* Return the time this cert becomes valid
161*/
163 {
164 return subject.get1("X509.Certificate.start");
165 }
166
167/*
168* Return the time this cert becomes invalid
169*/
170std::string X509_Certificate::end_time() const
171 {
172 return subject.get1("X509.Certificate.end");
173 }
174
175/*
176* Return information about the subject
177*/
178std::vector<std::string>
179X509_Certificate::subject_info(const std::string& what) const
180 {
181 return subject.get(X509_DN::deref_info_field(what));
182 }
183
184/*
185* Return information about the issuer
186*/
187std::vector<std::string>
188X509_Certificate::issuer_info(const std::string& what) const
189 {
190 return issuer.get(X509_DN::deref_info_field(what));
191 }
192
193/*
194* Return the public key in this certificate
195*/
197 {
198 DataSource_Memory source(subject.get1("X509.Certificate.public_key"));
199 return X509::load_key(source);
200 }
201
202/*
203* Check if the certificate is for a CA
204*/
206 {
207 if(!subject.get1_u32bit("X509v3.BasicConstraints.is_ca"))
208 return false;
210 return true;
211 return false;
212 }
213
214/*
215* Return the path length constraint
216*/
218 {
219 return subject.get1_u32bit("X509v3.BasicConstraints.path_constraint", 0);
220 }
221
222/*
223* Return the key usage constraints
224*/
226 {
227 return Key_Constraints(subject.get1_u32bit("X509v3.KeyUsage",
229 }
230
231/*
232* Return the list of extended key usage OIDs
233*/
234std::vector<std::string> X509_Certificate::ex_constraints() const
235 {
236 return lookup_oids(subject.get("X509v3.ExtendedKeyUsage"));
237 }
238
239/*
240* Return the list of certificate policies
241*/
242std::vector<std::string> X509_Certificate::policies() const
243 {
244 return lookup_oids(subject.get("X509v3.CertificatePolicies"));
245 }
246
247/*
248* Return the authority key id
249*/
251 {
252 return issuer.get1_memvec("X509v3.AuthorityKeyIdentifier");
253 }
254
255/*
256* Return the subject key id
257*/
259 {
260 return subject.get1_memvec("X509v3.SubjectKeyIdentifier");
261 }
262
263/*
264* Return the certificate serial number
265*/
267 {
268 return subject.get1_memvec("X509.Certificate.serial");
269 }
270
271/*
272* Return the distinguished name of the issuer
273*/
275 {
276 return create_dn(issuer);
277 }
278
279/*
280* Return the distinguished name of the subject
281*/
283 {
284 return create_dn(subject);
285 }
286
287/*
288* Compare two certificates for equality
289*/
291 {
292 return (sig == other.sig &&
293 sig_algo == other.sig_algo &&
294 self_signed == other.self_signed &&
295 issuer == other.issuer &&
296 subject == other.subject);
297 }
298
299/*
300* X.509 Certificate Comparison
301*/
302bool operator!=(const X509_Certificate& cert1, const X509_Certificate& cert2)
303 {
304 return !(cert1 == cert2);
305 }
306
308 {
309 const char* dn_fields[] = { "Name",
310 "Email",
311 "Organization",
312 "Organizational Unit",
313 "Locality",
314 "State",
315 "Country",
316 "IP",
317 "DNS",
318 "URI",
319 "PKIX.XMPPAddr",
320 0 };
321
322 std::ostringstream out;
323
324 for(size_t i = 0; dn_fields[i]; ++i)
325 {
326 const std::vector<std::string> vals = this->subject_info(dn_fields[i]);
327
328 if(vals.empty())
329 continue;
330
331 out << "Subject " << dn_fields[i] << ":";
332 for(size_t j = 0; j != vals.size(); ++j)
333 out << " " << vals[j];
334 out << "\n";
335 }
336
337 for(size_t i = 0; dn_fields[i]; ++i)
338 {
339 const std::vector<std::string> vals = this->issuer_info(dn_fields[i]);
340
341 if(vals.empty())
342 continue;
343
344 out << "Issuer " << dn_fields[i] << ":";
345 for(size_t j = 0; j != vals.size(); ++j)
346 out << " " << vals[j];
347 out << "\n";
348 }
349
350 out << "Version: " << this->x509_version() << "\n";
351
352 out << "Not valid before: " << this->start_time() << "\n";
353 out << "Not valid after: " << this->end_time() << "\n";
354
355 out << "Constraints:\n";
356 Key_Constraints constraints = this->constraints();
358 out << " None\n";
359 else
360 {
362 out << " Digital Signature\n";
364 out << " Non-Repuidation\n";
366 out << " Key Encipherment\n";
368 out << " Data Encipherment\n";
370 out << " Key Agreement\n";
372 out << " Cert Sign\n";
374 out << " CRL Sign\n";
375 }
376
377 std::vector<std::string> policies = this->policies();
378 if(policies.size())
379 {
380 out << "Policies: " << "\n";
381 for(size_t i = 0; i != policies.size(); i++)
382 out << " " << policies[i] << "\n";
383 }
384
385 std::vector<std::string> ex_constraints = this->ex_constraints();
386 if(ex_constraints.size())
387 {
388 out << "Extended Constraints:\n";
389 for(size_t i = 0; i != ex_constraints.size(); i++)
390 out << " " << ex_constraints[i] << "\n";
391 }
392
393 out << "Signature algorithm: " <<
394 OIDS::lookup(this->signature_algorithm().oid) << "\n";
395
396 out << "Serial number: " << hex_encode(this->serial_number()) << "\n";
397
398 if(this->authority_key_id().size())
399 out << "Authority keyid: " << hex_encode(this->authority_key_id()) << "\n";
400
401 if(this->subject_key_id().size())
402 out << "Subject keyid: " << hex_encode(this->subject_key_id()) << "\n";
403
404 X509_PublicKey* pubkey = this->subject_public_key();
405 out << "Public Key:\n" << X509::PEM_encode(*pubkey);
406 delete pubkey;
407
408 return out.str();
409 }
410
411/*
412* Create and populate a X509_DN
413*/
415 {
416 class DN_Matcher : public Data_Store::Matcher
417 {
418 public:
419 bool operator()(const std::string& key, const std::string&) const
420 {
421 if(key.find("X520.") != std::string::npos)
422 return true;
423 return false;
424 }
425 };
426
427 std::multimap<std::string, std::string> names =
428 info.search_with(DN_Matcher());
429
430 X509_DN dn;
431
432 std::multimap<std::string, std::string>::iterator i;
433 for(i = names.begin(); i != names.end(); ++i)
434 dn.add_attribute(i->first, i->second);
435
436 return dn;
437 }
438
439/*
440* Create and populate an AlternativeName
441*/
443 {
444 class AltName_Matcher : public Data_Store::Matcher
445 {
446 public:
447 bool operator()(const std::string& key, const std::string&) const
448 {
449 for(size_t i = 0; i != matches.size(); ++i)
450 if(key.compare(matches[i]) == 0)
451 return true;
452 return false;
453 }
454
455 AltName_Matcher(const std::string& match_any_of)
456 {
457 matches = split_on(match_any_of, '/');
458 }
459 private:
460 std::vector<std::string> matches;
461 };
462
463 std::multimap<std::string, std::string> names =
464 info.search_with(AltName_Matcher("RFC822/DNS/URI/IP"));
465
466 AlternativeName alt_name;
467
468 std::multimap<std::string, std::string>::iterator i;
469 for(i = names.begin(); i != names.end(); ++i)
470 alt_name.add_attribute(i->first, i->second);
471
472 return alt_name;
473 }
474
475}
void add_attribute(const std::string &, const std::string &)
Definition asn1_alt.cpp:55
BER_Decoder(DataSource &)
Definition ber_dec.cpp:264
SecureVector< byte > value
Definition asn1_int.h:83
ASN1_Tag class_tag
Definition asn1_int.h:82
ASN1_Tag type_tag
Definition asn1_int.h:82
static SecureVector< byte > encode(const BigInt &n, Base base=Binary)
Definition big_code.cpp:64
void add(const std::multimap< std::string, std::string > &)
Definition datastor.cpp:161
std::multimap< std::string, std::string > search_with(const Matcher &) const
Definition datastor.cpp:46
bool has_value(const std::string &) const
Definition datastor.cpp:37
void contents_to(Data_Store &, Data_Store &) const
Definition x509_ext.cpp:150
OID(const std::string &str="")
Definition asn1_oid.cpp:19
bool is_CA_cert() const
Definition x509cert.cpp:205
Key_Constraints constraints() const
Definition x509cert.cpp:225
bool operator==(const X509_Certificate &other) const
Definition x509cert.cpp:290
std::vector< std::string > issuer_info(const std::string &name) const
Definition x509cert.cpp:188
std::vector< std::string > ex_constraints() const
Definition x509cert.cpp:234
u32bit x509_version() const
Definition x509cert.cpp:154
X509_DN subject_dn() const
Definition x509cert.cpp:282
MemoryVector< byte > serial_number() const
Definition x509cert.cpp:266
std::string end_time() const
Definition x509cert.cpp:170
MemoryVector< byte > authority_key_id() const
Definition x509cert.cpp:250
std::vector< std::string > subject_info(const std::string &name) const
Definition x509cert.cpp:179
u32bit path_limit() const
Definition x509cert.cpp:217
std::vector< std::string > policies() const
Definition x509cert.cpp:242
std::string start_time() const
Definition x509cert.cpp:162
X509_Certificate(DataSource &source)
Definition x509cert.cpp:47
Public_Key * subject_public_key() const
Definition x509cert.cpp:196
X509_DN issuer_dn() const
Definition x509cert.cpp:274
std::string to_string() const
Definition x509cert.cpp:307
MemoryVector< byte > subject_key_id() const
Definition x509cert.cpp:258
static std::string deref_info_field(const std::string &)
Definition x509_dn.cpp:126
std::multimap< std::string, std::string > contents() const
Definition x509_dn.cpp:89
void add_attribute(const std::string &, const std::string &)
Definition x509_dn.cpp:47
MemoryVector< byte > sig
Definition x509_obj.h:102
X509_Object(DataSource &src, const std::string &pem_labels)
Definition x509_obj.cpp:24
AlgorithmIdentifier signature_algorithm() const
Definition x509_obj.cpp:140
AlgorithmIdentifier sig_algo
Definition x509_obj.h:101
MemoryVector< byte > tbs_bits
Definition x509_obj.h:102
std::string readable_string() const
Definition asn1_tm.cpp:216
SecureVector< byte > put_in_sequence(const MemoryRegion< byte > &contents)
Definition asn1_int.cpp:34
std::string lookup(const OID &oid)
Definition oids.cpp:31
std::string encode(const byte der[], size_t length, const std::string &label, size_t width)
Definition pem.cpp:19
std::string PEM_encode(const Public_Key &key)
Definition x509_key.cpp:34
Public_Key * load_key(DataSource &source)
Definition x509_key.cpp:43
void hex_encode(char output[], const byte input[], size_t input_length, bool uppercase)
Definition hex.cpp:14
std::string to_string(u64bit n, size_t min_len)
Definition parsing.cpp:42
bool operator!=(const OctetString &s1, const OctetString &s2)
Definition symkey.cpp:106
ASN1_Tag
Definition asn1_int.h:19
@ CONSTRUCTED
Definition asn1_int.h:25
@ BIT_STRING
Definition asn1_int.h:30
@ SEQUENCE
Definition asn1_int.h:35
@ CONTEXT_SPECIFIC
Definition asn1_int.h:22
@ NO_OBJECT
Definition asn1_int.h:49
unsigned int u32bit
Definition types.h:32
std::vector< std::string > split_on(const std::string &str, char delim)
Definition parsing.cpp:152
Public_Key X509_PublicKey
Definition pk_keys.h:133
Key_Constraints
@ DATA_ENCIPHERMENT
@ KEY_CERT_SIGN
@ NO_CONSTRAINTS
@ DIGITAL_SIGNATURE
@ KEY_AGREEMENT
@ KEY_ENCIPHERMENT
@ NON_REPUDIATION
X509_DN create_dn(const Data_Store &info)
Definition x509cert.cpp:414
AlternativeName create_alt_name(const Data_Store &info)
Definition x509cert.cpp:442
BER_Bad_Tag(const std::string &msg, ASN1_Tag tag)
Definition asn1_int.cpp:22
Decoding_Error(const std::string &name)
Definition exceptn.h:140