Botan  1.10.9
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 
22 namespace Botan {
23 
24 namespace {
25 
26 /*
27 * Lookup each OID in the vector
28 */
29 std::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 */
47 X509_Certificate::X509_Certificate(DataSource& in) :
48  X509_Object(in, "CERTIFICATE/X509 CERTIFICATE")
49  {
50  self_signed = false;
51  do_decode();
52  }
53 
54 /*
55 * X509_Certificate Constructor
56 */
57 X509_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 */
67 void 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 &&
111  v3_exts_data.class_tag == ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC))
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 */
162 std::string X509_Certificate::start_time() const
163  {
164  return subject.get1("X509.Certificate.start");
165  }
166 
167 /*
168 * Return the time this cert becomes invalid
169 */
170 std::string X509_Certificate::end_time() const
171  {
172  return subject.get1("X509.Certificate.end");
173  }
174 
175 /*
176 * Return information about the subject
177 */
178 std::vector<std::string>
179 X509_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 */
187 std::vector<std::string>
188 X509_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",
228  NO_CONSTRAINTS));
229  }
230 
231 /*
232 * Return the list of extended key usage OIDs
233 */
234 std::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 */
242 std::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 */
302 bool operator!=(const X509_Certificate& cert1, const X509_Certificate& cert2)
303  {
304  return !(cert1 == cert2);
305  }
306 
307 std::string X509_Certificate::to_string() const
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";
357  if(constraints == NO_CONSTRAINTS)
358  out << " None\n";
359  else
360  {
361  if(constraints & DIGITAL_SIGNATURE)
362  out << " Digital Signature\n";
363  if(constraints & NON_REPUDIATION)
364  out << " Non-Repuidation\n";
365  if(constraints & KEY_ENCIPHERMENT)
366  out << " Key Encipherment\n";
367  if(constraints & DATA_ENCIPHERMENT)
368  out << " Data Encipherment\n";
369  if(constraints & KEY_AGREEMENT)
370  out << " Key Agreement\n";
371  if(constraints & KEY_CERT_SIGN)
372  out << " Cert Sign\n";
373  if(constraints & CRL_SIGN)
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
bool operator!=(const OctetString &s1, const OctetString &s2)
Definition: symkey.cpp:106
MemoryVector< byte > tbs_bits
Definition: x509_obj.h:102
bool operator==(const X509_Certificate &other) const
Definition: x509cert.cpp:290
BER_Decoder & decode(bool &)
Definition: ber_dec.cpp:338
Public_Key * load_key(DataSource &source)
Definition: x509_key.cpp:43
std::vector< std::string > split_on(const std::string &str, char delim)
Definition: parsing.cpp:152
bool is_CA_cert() const
Definition: x509cert.cpp:205
Key_Constraints constraints() const
Definition: x509cert.cpp:225
void add_attribute(const std::string &, const std::string &)
Definition: x509_dn.cpp:47
static SecureVector< byte > encode(const BigInt &n, Base base=Binary)
Definition: big_code.cpp:64
void contents_to(Data_Store &, Data_Store &) const
Definition: x509_ext.cpp:150
u32bit path_limit() const
Definition: x509cert.cpp:217
MemoryVector< byte > authority_key_id() const
Definition: x509cert.cpp:250
std::string get1(const std::string &) const
Definition: datastor.cpp:87
AlgorithmIdentifier sig_algo
Definition: x509_obj.h:101
X509_DN create_dn(const Data_Store &info)
Definition: x509cert.cpp:414
std::string end_time() const
Definition: x509cert.cpp:170
AlternativeName create_alt_name(const Data_Store &info)
Definition: x509cert.cpp:442
std::string to_string() const
Definition: x509cert.cpp:307
std::string lookup(const OID &oid)
Definition: oids.cpp:31
ASN1_Tag
Definition: asn1_int.h:19
std::string start_time() const
Definition: x509cert.cpp:162
std::string PEM_encode(const Public_Key &key)
Definition: x509_key.cpp:34
SecureVector< byte > value
Definition: asn1_int.h:83
MemoryVector< byte > serial_number() const
Definition: x509cert.cpp:266
bool matches(DataSource &source, const std::string &extra, size_t search_range)
Definition: pem.cpp:116
std::multimap< std::string, std::string > search_with(const Matcher &) const
Definition: datastor.cpp:46
std::vector< std::string > policies() const
Definition: x509cert.cpp:242
MemoryVector< byte > sig
Definition: x509_obj.h:102
MemoryVector< byte > subject_key_id() const
Definition: x509cert.cpp:258
SecureVector< byte > put_in_sequence(const MemoryRegion< byte > &contents)
Definition: asn1_int.cpp:34
ASN1_Tag class_tag
Definition: asn1_int.h:82
std::string encode(const byte der[], size_t length, const std::string &label, size_t width)
Definition: pem.cpp:19
MemoryVector< byte > get1_memvec(const std::string &) const
Definition: datastor.cpp:103
u32bit get1_u32bit(const std::string &, u32bit=0) const
Definition: datastor.cpp:120
bool has_value(const std::string &) const
Definition: datastor.cpp:37
ASN1_Tag type_tag
Definition: asn1_int.h:82
BER_Decoder & verify_end()
Definition: ber_dec.cpp:160
X509_DN issuer_dn() const
Definition: x509cert.cpp:274
std::vector< std::string > subject_info(const std::string &name) const
Definition: x509cert.cpp:179
std::vector< std::string > ex_constraints() const
Definition: x509cert.cpp:234
static std::string deref_info_field(const std::string &)
Definition: x509_dn.cpp:126
std::string to_string(u64bit n, size_t min_len)
Definition: parsing.cpp:42
std::string readable_string() const
Definition: asn1_tm.cpp:216
std::vector< std::string > issuer_info(const std::string &name) const
Definition: x509cert.cpp:188
Public_Key * subject_public_key() const
Definition: x509cert.cpp:196
std::multimap< std::string, std::string > contents() const
Definition: x509_dn.cpp:89
X509_DN subject_dn() const
Definition: x509cert.cpp:282
u32bit x509_version() const
Definition: x509cert.cpp:154
Key_Constraints
Definition: pubkey_enums.h:18
std::vector< std::string > get(const std::string &) const
Definition: datastor.cpp:72
AlgorithmIdentifier signature_algorithm() const
Definition: x509_obj.cpp:140
unsigned int u32bit
Definition: types.h:32
void add(const std::multimap< std::string, std::string > &)
Definition: datastor.cpp:161
OID oid
Definition: x509_ext.cpp:446
void hex_encode(char output[], const byte input[], size_t input_length, bool uppercase)
Definition: hex.cpp:14