Botan  2.7.0
Crypto and TLS for C++11
x509_ca.cpp
Go to the documentation of this file.
1 /*
2 * X.509 Certificate Authority
3 * (C) 1999-2010 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/x509_ca.h>
9 #include <botan/x509self.h>
10 #include <botan/pkcs10.h>
11 #include <botan/pubkey.h>
12 #include <botan/der_enc.h>
13 #include <botan/bigint.h>
14 #include <botan/parsing.h>
15 #include <botan/oids.h>
16 #include <botan/hash.h>
17 #include <botan/key_constraint.h>
18 #include <botan/emsa.h>
19 #include <botan/scan_name.h>
20 #include <algorithm>
21 #include <iterator>
22 #include <map>
23 
24 namespace Botan {
25 
26 /*
27 * Load the certificate and private key
28 */
30  const Private_Key& key,
31  const std::string& hash_fn,
32  RandomNumberGenerator& rng) :
33  m_ca_cert(c),
34  m_hash_fn(hash_fn)
35  {
36  if(!m_ca_cert.is_CA_cert())
37  throw Invalid_Argument("X509_CA: This certificate is not for a CA");
38 
39  std::map<std::string,std::string> opts;
40  // constructor without additional options: use the padding used in the CA certificate
41  // sig_oid_str = <sig_alg>/<padding>, so padding with all its options will look
42  // like a cipher mode to the scanner
43  std::string sig_oid_str = OIDS::lookup(c.signature_algorithm().oid);
44  SCAN_Name scanner(sig_oid_str);
45  std::string pad = scanner.cipher_mode();
46  if(!pad.empty())
47  opts.insert({"padding",pad});
48 
49  m_signer.reset(choose_sig_format(key, opts, rng, hash_fn, m_ca_sig_algo));
50  }
51 
52 /*
53 * Load the certificate and private key, and additional options
54 */
55 X509_CA::X509_CA(const X509_Certificate& ca_certificate,
56  const Private_Key& key,
57  const std::map<std::string,std::string>& opts,
58  const std::string& hash_fn,
59  RandomNumberGenerator& rng) : m_ca_cert(ca_certificate), m_hash_fn(hash_fn)
60  {
61  if(!m_ca_cert.is_CA_cert())
62  throw Invalid_Argument("X509_CA: This certificate is not for a CA");
63 
64  m_signer.reset(choose_sig_format(key, opts, rng, hash_fn, m_ca_sig_algo));
65  }
66 
67 /*
68 * X509_CA Destructor
69 */
71  {
72  /* for unique_ptr */
73  }
74 
75 namespace {
76 
77 Extensions choose_extensions(const PKCS10_Request& req,
78  const X509_Certificate& ca_cert,
79  const std::string& hash_fn)
80  {
81  Key_Constraints constraints;
82  if(req.is_CA())
83  {
84  constraints = Key_Constraints(KEY_CERT_SIGN | CRL_SIGN);
85  }
86  else
87  {
88  std::unique_ptr<Public_Key> key(req.subject_public_key());
90  constraints = req.constraints();
91  }
92 
93  Extensions extensions = req.extensions();
94 
95  extensions.replace(
96  new Cert_Extension::Basic_Constraints(req.is_CA(), req.path_limit()),
97  true);
98 
99  if(constraints != NO_CONSTRAINTS)
100  {
101  extensions.replace(new Cert_Extension::Key_Usage(constraints), true);
102  }
103 
104  extensions.replace(new Cert_Extension::Authority_Key_ID(ca_cert.subject_key_id()));
105  extensions.replace(new Cert_Extension::Subject_Key_ID(req.raw_public_key(), hash_fn));
106 
107  extensions.replace(
108  new Cert_Extension::Subject_Alternative_Name(req.subject_alt_name()));
109 
110  extensions.replace(
111  new Cert_Extension::Extended_Key_Usage(req.ex_constraints()));
112 
113  return extensions;
114  }
115 
116 }
117 
120  const BigInt& serial_number,
121  const X509_Time& not_before,
122  const X509_Time& not_after) const
123  {
124  auto extensions = choose_extensions(req, m_ca_cert, m_hash_fn);
125 
126  return make_cert(m_signer.get(), rng, serial_number,
127  m_ca_sig_algo, req.raw_public_key(),
128  not_before, not_after,
129  m_ca_cert.subject_dn(), req.subject_dn(),
130  extensions);
131  }
132 
133 /*
134 * Sign a PKCS #10 certificate request
135 */
138  const X509_Time& not_before,
139  const X509_Time& not_after) const
140  {
141  auto extensions = choose_extensions(req, m_ca_cert, m_hash_fn);
142 
143  return make_cert(m_signer.get(), rng, m_ca_sig_algo,
144  req.raw_public_key(),
145  not_before, not_after,
146  m_ca_cert.subject_dn(), req.subject_dn(),
147  extensions);
148  }
149 
152  const AlgorithmIdentifier& sig_algo,
153  const std::vector<uint8_t>& pub_key,
154  const X509_Time& not_before,
155  const X509_Time& not_after,
156  const X509_DN& issuer_dn,
157  const X509_DN& subject_dn,
158  const Extensions& extensions)
159  {
160  const size_t SERIAL_BITS = 128;
161  BigInt serial_no(rng, SERIAL_BITS);
162 
163  return make_cert(signer, rng, serial_no, sig_algo, pub_key,
164  not_before, not_after, issuer_dn, subject_dn, extensions);
165  }
166 
167 /*
168 * Create a new certificate
169 */
172  const BigInt& serial_no,
173  const AlgorithmIdentifier& sig_algo,
174  const std::vector<uint8_t>& pub_key,
175  const X509_Time& not_before,
176  const X509_Time& not_after,
177  const X509_DN& issuer_dn,
178  const X509_DN& subject_dn,
179  const Extensions& extensions)
180  {
181  const size_t X509_CERT_VERSION = 3;
182 
183  // clang-format off
185  signer, rng, sig_algo,
186  DER_Encoder().start_cons(SEQUENCE)
187  .start_explicit(0)
188  .encode(X509_CERT_VERSION-1)
189  .end_explicit()
190 
191  .encode(serial_no)
192 
193  .encode(sig_algo)
194  .encode(issuer_dn)
195 
196  .start_cons(SEQUENCE)
197  .encode(not_before)
198  .encode(not_after)
199  .end_cons()
200 
201  .encode(subject_dn)
202  .raw_bytes(pub_key)
203 
204  .start_explicit(3)
205  .start_cons(SEQUENCE)
206  .encode(extensions)
207  .end_cons()
208  .end_explicit()
209  .end_cons()
210  .get_contents()
211  ));
212  // clang-format on
213  }
214 
215 /*
216 * Create a new, empty CRL
217 */
219  uint32_t next_update) const
220  {
221  return new_crl(rng,
222  std::chrono::system_clock::now(),
223  std::chrono::seconds(next_update));
224  }
225 
226 /*
227 * Update a CRL with new entries
228 */
230  const std::vector<CRL_Entry>& new_revoked,
232  uint32_t next_update) const
233  {
234  return update_crl(crl, new_revoked, rng,
235  std::chrono::system_clock::now(),
236  std::chrono::seconds(next_update));
237  }
238 
239 
241  std::chrono::system_clock::time_point issue_time,
242  std::chrono::seconds next_update) const
243  {
244  std::vector<CRL_Entry> empty;
245  return make_crl(empty, 1, rng, issue_time, next_update);
246  }
247 
249  const std::vector<CRL_Entry>& new_revoked,
251  std::chrono::system_clock::time_point issue_time,
252  std::chrono::seconds next_update) const
253  {
254  std::vector<CRL_Entry> revoked = last_crl.get_revoked();
255 
256  std::copy(new_revoked.begin(), new_revoked.end(),
257  std::back_inserter(revoked));
258 
259  return make_crl(revoked, last_crl.crl_number() + 1, rng, issue_time, next_update);
260  }
261 
262 /*
263 * Create a CRL
264 */
265 X509_CRL X509_CA::make_crl(const std::vector<CRL_Entry>& revoked,
266  uint32_t crl_number,
268  std::chrono::system_clock::time_point issue_time,
269  std::chrono::seconds next_update) const
270  {
271  const size_t X509_CRL_VERSION = 2;
272 
273  auto expire_time = issue_time + next_update;
274 
275  Extensions extensions;
276  extensions.add(new Cert_Extension::Authority_Key_ID(m_ca_cert.subject_key_id()));
277  extensions.add(new Cert_Extension::CRL_Number(crl_number));
278 
279  // clang-format off
280  const std::vector<uint8_t> crl = X509_Object::make_signed(
281  m_signer.get(), rng, m_ca_sig_algo,
283  .encode(X509_CRL_VERSION-1)
284  .encode(m_ca_sig_algo)
285  .encode(m_ca_cert.subject_dn())
286  .encode(X509_Time(issue_time))
287  .encode(X509_Time(expire_time))
288  .encode_if(revoked.size() > 0,
289  DER_Encoder()
291  .encode_list(revoked)
292  .end_cons()
293  )
294  .start_explicit(0)
295  .start_cons(SEQUENCE)
296  .encode(extensions)
297  .end_cons()
298  .end_explicit()
299  .end_cons()
300  .get_contents());
301  // clang-format on
302 
303  return X509_CRL(crl);
304  }
305 
306 /*
307 * Return the CA's certificate
308 */
310  {
311  return m_ca_cert;
312  }
313 
314 /*
315 * Choose a signing format for the key
316 */
317 
320  const std::string& hash_fn,
321  AlgorithmIdentifier& sig_algo)
322  {
323  return X509_Object::choose_sig_format(sig_algo, key, rng, hash_fn, "").release();
324  }
325 
327  const std::map<std::string,std::string>& opts,
329  const std::string& hash_fn,
330  AlgorithmIdentifier& sig_algo)
331  {
332  std::string padding;
333  if(opts.count("padding"))
334  padding = opts.at("padding");
335  return X509_Object::choose_sig_format(sig_algo, key, rng, hash_fn, padding).release();
336  }
337 
338 }
DER_Encoder & encode_list(const std::vector< T > &values)
Definition: der_enc.h:122
X509_Certificate sign_request(const PKCS10_Request &req, RandomNumberGenerator &rng, const X509_Time &not_before, const X509_Time &not_after) const
Definition: x509_ca.cpp:136
const AlternativeName & subject_alt_name() const
Definition: pkcs10.cpp:245
static X509_Certificate make_cert(PK_Signer *signer, RandomNumberGenerator &rng, const AlgorithmIdentifier &sig_algo, const std::vector< uint8_t > &pub_key, const X509_Time &not_before, const X509_Time &not_after, const X509_DN &issuer_dn, const X509_DN &subject_dn, const Extensions &extensions)
Definition: x509_ca.cpp:150
const AlgorithmIdentifier & signature_algorithm() const
Definition: x509_obj.h:48
const std::vector< uint8_t > & raw_public_key() const
Definition: pkcs10.cpp:228
size_t path_limit() const
Definition: pkcs10.cpp:300
static std::vector< uint8_t > make_signed(class PK_Signer *signer, RandomNumberGenerator &rng, const AlgorithmIdentifier &alg_id, const secure_vector< uint8_t > &tbs)
Definition: x509_obj.cpp:270
X509_Certificate ca_certificate() const
Definition: x509_ca.cpp:309
X509_CRL update_crl(const X509_CRL &last_crl, const std::vector< CRL_Entry > &new_entries, RandomNumberGenerator &rng, std::chrono::system_clock::time_point issue_time, std::chrono::seconds next_update) const
Definition: x509_ca.cpp:248
void replace(Certificate_Extension *extn, bool critical=false)
Definition: x509_ext.cpp:149
DER_Encoder & end_cons()
Definition: der_enc.cpp:191
const std::vector< uint8_t > & subject_key_id() const
Definition: x509cert.cpp:407
const Extensions & extensions() const
Definition: pkcs10.cpp:253
bool is_CA_cert() const
Definition: x509cert.cpp:443
void add(Certificate_Extension *extn, bool critical=false)
Definition: x509_ext.cpp:122
X509_CA(const X509_Certificate &ca_certificate, const Private_Key &key, const std::string &hash_fn, RandomNumberGenerator &rng)
Definition: x509_ca.cpp:29
DER_Encoder & encode(bool b)
Definition: der_enc.cpp:285
static std::unique_ptr< PK_Signer > choose_sig_format(AlgorithmIdentifier &sig_algo, const Private_Key &key, RandomNumberGenerator &rng, const std::string &hash_fn, const std::string &padding_algo)
Definition: x509_obj.cpp:366
std::string encode(const uint8_t der[], size_t length, const std::string &label, size_t width)
Definition: pem.cpp:43
const X509_DN & subject_dn() const
Definition: x509cert.cpp:428
X509_CRL new_crl(RandomNumberGenerator &rng, std::chrono::system_clock::time_point issue_time, std::chrono::seconds next_update) const
Definition: x509_ca.cpp:240
bool is_CA() const
Definition: pkcs10.cpp:287
Key_Constraints constraints() const
Definition: pkcs10.cpp:261
Definition: alg_id.cpp:13
void verify_cert_constraints_valid_for_key_type(const Public_Key &pub_key, Key_Constraints constraints)
PK_Signer * choose_sig_format(const Private_Key &key, RandomNumberGenerator &rng, const std::string &hash_fn, AlgorithmIdentifier &sig_algo)
Definition: x509_ca.cpp:318
const X509_DN & subject_dn() const
Definition: pkcs10.cpp:220
DER_Encoder & start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Definition: der_enc.cpp:181
uint32_t crl_number() const
Definition: x509_crl.cpp:240
Public_Key * subject_public_key() const
Definition: pkcs10.cpp:236
const std::vector< CRL_Entry > & get_revoked() const
Definition: x509_crl.cpp:216
std::string lookup(const OID &oid)
Definition: oids.cpp:113
std::vector< OID > ex_constraints() const
Definition: pkcs10.cpp:274