Botan  1.11.10
x509_ca.cpp
Go to the documentation of this file.
1 /*
2 * X.509 Certificate Authority
3 * (C) 1999-2010 Jack Lloyd
4 *
5 * Distributed under the terms of the Botan license
6 */
7 
8 #include <botan/x509_ca.h>
9 #include <botan/pubkey.h>
10 #include <botan/der_enc.h>
11 #include <botan/ber_dec.h>
12 #include <botan/bigint.h>
13 #include <botan/parsing.h>
14 #include <botan/lookup.h>
15 #include <botan/oids.h>
16 #include <botan/key_constraint.h>
17 #include <algorithm>
18 #include <typeinfo>
19 #include <iterator>
20 #include <set>
21 
22 namespace Botan {
23 
24 /*
25 * Load the certificate and private key
26 */
28  const Private_Key& key,
29  const std::string& hash_fn) : cert(c)
30  {
31  if(!cert.is_CA_cert())
32  throw Invalid_Argument("X509_CA: This certificate is not for a CA");
33 
34  signer = choose_sig_format(key, hash_fn, ca_sig_algo);
35  }
36 
37 /*
38 * X509_CA Destructor
39 */
41  {
42  delete signer;
43  }
44 
45 /*
46 * Sign a PKCS #10 certificate request
47 */
50  const X509_Time& not_before,
51  const X509_Time& not_after)
52  {
53  Key_Constraints constraints;
54  if(req.is_CA())
55  constraints = Key_Constraints(KEY_CERT_SIGN | CRL_SIGN);
56  else
57  {
58  std::unique_ptr<Public_Key> key(req.subject_public_key());
59  constraints = find_constraints(*key, req.constraints());
60  }
61 
62  Extensions extensions;
63 
64  extensions.add(
66  true);
67 
68  extensions.add(new Cert_Extension::Key_Usage(constraints), true);
69 
70  extensions.add(new Cert_Extension::Authority_Key_ID(cert.subject_key_id()));
71  extensions.add(new Cert_Extension::Subject_Key_ID(req.raw_public_key()));
72 
73  extensions.add(
75 
76  extensions.add(
78 
79  return make_cert(signer, rng, ca_sig_algo,
80  req.raw_public_key(),
81  not_before, not_after,
82  cert.subject_dn(), req.subject_dn(),
83  extensions);
84  }
85 
86 /*
87 * Create a new certificate
88 */
91  const AlgorithmIdentifier& sig_algo,
92  const std::vector<byte>& pub_key,
93  const X509_Time& not_before,
94  const X509_Time& not_after,
95  const X509_DN& issuer_dn,
96  const X509_DN& subject_dn,
97  const Extensions& extensions)
98  {
99  const size_t X509_CERT_VERSION = 3;
100  const size_t SERIAL_BITS = 128;
101 
102  BigInt serial_no(rng, SERIAL_BITS);
103 
104  const std::vector<byte> cert = X509_Object::make_signed(
105  signer, rng, sig_algo,
106  DER_Encoder().start_cons(SEQUENCE)
107  .start_explicit(0)
108  .encode(X509_CERT_VERSION-1)
109  .end_explicit()
110 
111  .encode(serial_no)
112 
113  .encode(sig_algo)
114  .encode(issuer_dn)
115 
116  .start_cons(SEQUENCE)
117  .encode(not_before)
118  .encode(not_after)
119  .end_cons()
120 
121  .encode(subject_dn)
122  .raw_bytes(pub_key)
123 
124  .start_explicit(3)
125  .start_cons(SEQUENCE)
126  .encode(extensions)
127  .end_cons()
128  .end_explicit()
129  .end_cons()
130  .get_contents());
131 
132  return X509_Certificate(cert);
133  }
134 
135 /*
136 * Create a new, empty CRL
137 */
139  u32bit next_update) const
140  {
141  std::vector<CRL_Entry> empty;
142  return make_crl(empty, 1, next_update, rng);
143  }
144 
145 /*
146 * Update a CRL with new entries
147 */
149  const std::vector<CRL_Entry>& new_revoked,
151  u32bit next_update) const
152  {
153  std::vector<CRL_Entry> revoked = crl.get_revoked();
154 
155  std::copy(new_revoked.begin(), new_revoked.end(),
156  std::back_inserter(revoked));
157 
158  return make_crl(revoked, crl.crl_number() + 1, next_update, rng);
159  }
160 
161 /*
162 * Create a CRL
163 */
164 X509_CRL X509_CA::make_crl(const std::vector<CRL_Entry>& revoked,
165  u32bit crl_number, u32bit next_update,
166  RandomNumberGenerator& rng) const
167  {
168  const size_t X509_CRL_VERSION = 2;
169 
170  if(next_update == 0)
171  next_update = timespec_to_u32bit("7d");
172 
173  // Totally stupid: ties encoding logic to the return of std::time!!
174  auto current_time = std::chrono::system_clock::now();
175  auto expire_time = current_time + std::chrono::seconds(next_update);
176 
177  Extensions extensions;
178  extensions.add(
180  extensions.add(new Cert_Extension::CRL_Number(crl_number));
181 
182  const std::vector<byte> crl = X509_Object::make_signed(
183  signer, rng, ca_sig_algo,
184  DER_Encoder().start_cons(SEQUENCE)
185  .encode(X509_CRL_VERSION-1)
186  .encode(ca_sig_algo)
187  .encode(cert.issuer_dn())
188  .encode(X509_Time(current_time))
189  .encode(X509_Time(expire_time))
190  .encode_if(revoked.size() > 0,
191  DER_Encoder()
193  .encode_list(revoked)
194  .end_cons()
195  )
196  .start_explicit(0)
197  .start_cons(SEQUENCE)
198  .encode(extensions)
199  .end_cons()
200  .end_explicit()
201  .end_cons()
202  .get_contents());
203 
204  return X509_CRL(crl);
205  }
206 
207 /*
208 * Return the CA's certificate
209 */
211  {
212  return cert;
213  }
214 
215 /*
216 * Choose a signing format for the key
217 */
219  const std::string& hash_fn,
220  AlgorithmIdentifier& sig_algo)
221  {
222  std::string padding;
223 
224  const std::string algo_name = key.algo_name();
225 
226  const HashFunction* proto_hash = retrieve_hash(hash_fn);
227  if(!proto_hash)
228  throw Algorithm_Not_Found(hash_fn);
229 
230  if(key.max_input_bits() < proto_hash->output_length()*8)
231  throw Invalid_Argument("Key is too small for chosen hash function");
232 
233  if(algo_name == "RSA")
234  padding = "EMSA3";
235  else if(algo_name == "DSA")
236  padding = "EMSA1";
237  else if(algo_name == "ECDSA")
238  padding = "EMSA1_BSI";
239  else
240  throw Invalid_Argument("Unknown X.509 signing key type: " + algo_name);
241 
242  Signature_Format format =
243  (key.message_parts() > 1) ? DER_SEQUENCE : IEEE_1363;
244 
245  padding = padding + '(' + proto_hash->name() + ')';
246 
247  sig_algo.oid = OIDS::lookup(algo_name + "/" + padding);
248  sig_algo.parameters = key.algorithm_identifier().parameters;
249 
250  return new PK_Signer(key, padding, format);
251  }
252 
253 }
u32bit crl_number() const
Definition: x509_crl.cpp:170
DER_Encoder & encode_list(const std::vector< T > &values)
Definition: der_enc.h:85
X509_CRL new_crl(RandomNumberGenerator &rng, u32bit next_update=0) const
Definition: x509_ca.cpp:138
X509_CA(const X509_Certificate &ca_certificate, const Private_Key &key, const std::string &hash_fn)
Definition: x509_ca.cpp:27
std::vector< OID > ex_constraints() const
Definition: pkcs10.cpp:182
Public_Key * subject_public_key() const
Definition: pkcs10.cpp:157
bool is_CA() const
Definition: pkcs10.cpp:195
virtual AlgorithmIdentifier algorithm_identifier() const =0
std::vector< byte > raw_public_key() const
Definition: pkcs10.cpp:148
Signature_Format
Definition: pubkey.h:24
bool is_CA_cert() const
Definition: x509cert.cpp:222
virtual std::string name() const =0
virtual std::string algo_name() const =0
std::invalid_argument Invalid_Argument
Definition: exceptn.h:20
DER_Encoder & end_cons()
Definition: der_enc.cpp:145
X509_CRL update_crl(const X509_CRL &last_crl, const std::vector< CRL_Entry > &new_entries, RandomNumberGenerator &rng, u32bit next_update=0) const
Definition: x509_ca.cpp:148
void add(Certificate_Extension *extn, bool critical=false)
Definition: x509_ext.cpp:77
std::string algo_name
Definition: ossl_md.cpp:41
std::vector< byte > parameters
Definition: alg_id.h:36
AlternativeName subject_alt_name() const
Definition: pkcs10.cpp:166
static std::vector< byte > make_signed(class PK_Signer *signer, RandomNumberGenerator &rng, const AlgorithmIdentifier &alg_id, const secure_vector< byte > &tbs)
Definition: x509_obj.cpp:211
Key_Constraints find_constraints(const Public_Key &pub_key, Key_Constraints limits)
std::string lookup(const OID &oid)
Definition: oids.cpp:111
uint32_t u32bit
Definition: types.h:32
virtual size_t message_parts() const
Definition: pk_keys.h:61
X509_Certificate ca_certificate() const
Definition: x509_ca.cpp:210
X509_DN subject_dn() const
Definition: pkcs10.cpp:140
std::vector< byte > subject_key_id() const
Definition: x509cert.cpp:300
Key_Constraints constraints() const
Definition: pkcs10.cpp:174
std::vector< CRL_Entry > get_revoked() const
Definition: x509_crl.cpp:146
std::string encode(const byte der[], size_t length, const std::string &label, size_t width)
Definition: pem.cpp:19
static X509_Certificate make_cert(PK_Signer *signer, RandomNumberGenerator &rng, const AlgorithmIdentifier &sig_algo, const std::vector< byte > &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:89
X509_DN issuer_dn() const
Definition: x509cert.cpp:316
u32bit timespec_to_u32bit(const std::string &timespec)
Definition: parsing.cpp:24
DER_Encoder & start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Definition: der_enc.cpp:135
const HashFunction * retrieve_hash(const std::string &algo_spec)
Definition: lookup.h:55
virtual size_t max_input_bits() const =0
u32bit path_limit() const
Definition: pkcs10.cpp:203
X509_Certificate sign_request(const PKCS10_Request &req, RandomNumberGenerator &rng, const X509_Time &not_before, const X509_Time &not_after)
Definition: x509_ca.cpp:48
X509_DN subject_dn() const
Definition: x509cert.cpp:329
virtual size_t output_length() const =0
PK_Signer * choose_sig_format(const Private_Key &key, const std::string &hash_fn, AlgorithmIdentifier &sig_algo)
Definition: x509_ca.cpp:218