Botan 3.0.0
Crypto and TLS for C&
x509_ca.cpp
Go to the documentation of this file.
1/*
2* X.509 Certificate Authority
3* (C) 1999-2010,2023 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/x509_key.h>
10#include <botan/pkcs10.h>
11#include <botan/x509_ext.h>
12#include <botan/pubkey.h>
13#include <botan/der_enc.h>
14#include <botan/bigint.h>
15
16namespace Botan {
17
18/*
19* Load the certificate and private key
20*/
22 const Private_Key& key,
23 std::string_view hash_fn,
24 std::string_view padding_method,
26 m_ca_cert(cert)
27 {
28 if(!m_ca_cert.is_CA_cert())
29 throw Invalid_Argument("X509_CA: This certificate is not for a CA");
30
31 m_signer = X509_Object::choose_sig_format(key, rng, hash_fn, padding_method);
32 m_ca_sig_algo = m_signer->algorithm_identifier();
33 m_hash_fn = m_signer->hash_function();
34 }
35
36X509_CA::~X509_CA() = default;
37
39 const X509_Certificate& ca_cert,
40 std::string_view hash_fn)
41 {
42 const auto constraints =
44
45 auto key = req.subject_public_key();
46 if(!constraints.compatible_with(*key))
47 throw Invalid_Argument("The requested key constraints are incompatible with the algorithm");
48
49 Extensions extensions = req.extensions();
50
51 extensions.replace(
52 std::make_unique<Cert_Extension::Basic_Constraints>(req.is_CA(), req.path_limit()),
53 true);
54
55 if(!constraints.empty())
56 {
57 extensions.replace(std::make_unique<Cert_Extension::Key_Usage>(constraints), true);
58 }
59
60 extensions.replace(std::make_unique<Cert_Extension::Authority_Key_ID>(ca_cert.subject_key_id()));
61 extensions.replace(std::make_unique<Cert_Extension::Subject_Key_ID>(req.raw_public_key(), hash_fn));
62
63 extensions.replace(
64 std::make_unique<Cert_Extension::Subject_Alternative_Name>(req.subject_alt_name()));
65
66 extensions.replace(
67 std::make_unique<Cert_Extension::Extended_Key_Usage>(req.ex_constraints()));
68
69 return extensions;
70 }
71
74 const BigInt& serial_number,
75 const X509_Time& not_before,
76 const X509_Time& not_after) const
77 {
78 auto extensions = choose_extensions(req, m_ca_cert, m_hash_fn);
79
80 return make_cert(*m_signer, rng, serial_number,
82 not_before, not_after,
83 ca_certificate().subject_dn(), req.subject_dn(),
84 extensions);
85 }
86
87/*
88* Sign a PKCS #10 certificate request
89*/
92 const X509_Time& not_before,
93 const X509_Time& not_after) const
94 {
95 auto extensions = choose_extensions(req, m_ca_cert, m_hash_fn);
96
97 return make_cert(*m_signer, rng, algorithm_identifier(),
98 req.raw_public_key(),
99 not_before, not_after,
100 ca_certificate().subject_dn(), req.subject_dn(),
101 extensions);
102 }
103
106 const AlgorithmIdentifier& sig_algo,
107 const std::vector<uint8_t>& pub_key,
108 const X509_Time& not_before,
109 const X509_Time& not_after,
110 const X509_DN& issuer_dn,
111 const X509_DN& subject_dn,
112 const Extensions& extensions)
113 {
114 const size_t SERIAL_BITS = 128;
115 BigInt serial_no(rng, SERIAL_BITS);
116
117 return make_cert(signer, rng, serial_no, sig_algo, pub_key,
118 not_before, not_after, issuer_dn, subject_dn, extensions);
119 }
120
121/*
122* Create a new certificate
123*/
126 const BigInt& serial_no,
127 const AlgorithmIdentifier& sig_algo,
128 const std::vector<uint8_t>& pub_key,
129 const X509_Time& not_before,
130 const X509_Time& not_after,
131 const X509_DN& issuer_dn,
132 const X509_DN& subject_dn,
133 const Extensions& extensions)
134 {
135 const size_t X509_CERT_VERSION = 3;
136
137 // clang-format off
139 signer, rng, sig_algo,
140 DER_Encoder().start_sequence()
141 .start_explicit(0)
142 .encode(X509_CERT_VERSION-1)
143 .end_explicit()
144
145 .encode(serial_no)
146
147 .encode(sig_algo)
148 .encode(issuer_dn)
149
150 .start_sequence()
151 .encode(not_before)
152 .encode(not_after)
153 .end_cons()
154
155 .encode(subject_dn)
156 .raw_bytes(pub_key)
157
158 .start_explicit(3)
159 .start_sequence()
160 .encode(extensions)
161 .end_cons()
162 .end_explicit()
163 .end_cons()
164 .get_contents()
165 ));
166 // clang-format on
167 }
168
169/*
170* Create a new, empty CRL
171*/
173 uint32_t next_update) const
174 {
175 return new_crl(rng,
176 std::chrono::system_clock::now(),
177 std::chrono::seconds(next_update));
178 }
179
180/*
181* Update a CRL with new entries
182*/
184 const std::vector<CRL_Entry>& new_revoked,
186 uint32_t next_update) const
187 {
188 return update_crl(crl, new_revoked, rng,
189 std::chrono::system_clock::now(),
190 std::chrono::seconds(next_update));
191 }
192
193
195 std::chrono::system_clock::time_point issue_time,
196 std::chrono::seconds next_update) const
197 {
198 std::vector<CRL_Entry> empty;
199 return make_crl(empty, 1, rng, issue_time, next_update);
200 }
201
203 const std::vector<CRL_Entry>& new_revoked,
205 std::chrono::system_clock::time_point issue_time,
206 std::chrono::seconds next_update) const
207 {
208 std::vector<CRL_Entry> revoked = last_crl.get_revoked();
209
210 std::copy(new_revoked.begin(), new_revoked.end(),
211 std::back_inserter(revoked));
212
213 return make_crl(revoked, last_crl.crl_number() + 1, rng, issue_time, next_update);
214 }
215
216/*
217* Create a CRL
218*/
219X509_CRL X509_CA::make_crl(const std::vector<CRL_Entry>& revoked,
220 uint32_t crl_number,
222 std::chrono::system_clock::time_point issue_time,
223 std::chrono::seconds next_update) const
224 {
225 const size_t X509_CRL_VERSION = 2;
226
227 auto expire_time = issue_time + next_update;
228
229 Extensions extensions;
230 extensions.add(std::make_unique<Cert_Extension::Authority_Key_ID>(m_ca_cert.subject_key_id()));
231 extensions.add(std::make_unique<Cert_Extension::CRL_Number>(crl_number));
232
233 // clang-format off
234 const std::vector<uint8_t> crl = X509_Object::make_signed(
235 *m_signer, rng, m_ca_sig_algo,
236 DER_Encoder().start_sequence()
237 .encode(X509_CRL_VERSION-1)
238 .encode(m_ca_sig_algo)
239 .encode(m_ca_cert.subject_dn())
240 .encode(X509_Time(issue_time))
241 .encode(X509_Time(expire_time))
242 .encode_if(!revoked.empty(),
244 .start_sequence()
245 .encode_list(revoked)
246 .end_cons()
247 )
248 .start_explicit(0)
249 .start_sequence()
250 .encode(extensions)
251 .end_cons()
252 .end_explicit()
253 .end_cons()
254 .get_contents());
255 // clang-format on
256
257 return X509_CRL(crl);
258 }
259
260}
void replace(std::unique_ptr< Certificate_Extension > extn, bool critical=false)
Definition: x509_ext.cpp:159
void add(std::unique_ptr< Certificate_Extension > extn, bool critical=false)
Definition: x509_ext.cpp:118
static Key_Constraints ca_constraints()
Definition: pkix_enums.h:149
std::unique_ptr< Public_Key > subject_public_key() const
Definition: pkcs10.cpp:224
const X509_DN & subject_dn() const
Definition: pkcs10.cpp:208
std::vector< OID > ex_constraints() const
Definition: pkcs10.cpp:262
size_t path_limit() const
Definition: pkcs10.cpp:288
const std::vector< uint8_t > & raw_public_key() const
Definition: pkcs10.cpp:216
Key_Constraints constraints() const
Definition: pkcs10.cpp:249
bool is_CA() const
Definition: pkcs10.cpp:275
const AlternativeName & subject_alt_name() const
Definition: pkcs10.cpp:233
const Extensions & extensions() const
Definition: pkcs10.cpp:241
X509_CRL new_crl(RandomNumberGenerator &rng, std::chrono::system_clock::time_point issue_time, std::chrono::seconds next_update) const
Definition: x509_ca.cpp:194
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:104
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:202
const AlgorithmIdentifier algorithm_identifier() const
Definition: x509_ca.h:34
X509_CA(const X509_Certificate &ca_certificate, const Private_Key &key, std::string_view hash_fn, std::string_view padding_method, RandomNumberGenerator &rng)
Definition: x509_ca.cpp:21
const X509_Certificate & ca_certificate() const
Definition: x509_ca.h:39
static Extensions choose_extensions(const PKCS10_Request &req, const X509_Certificate &ca_certificate, std::string_view hash_fn)
Definition: x509_ca.cpp:38
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:90
const std::vector< CRL_Entry > & get_revoked() const
Definition: x509_crl.cpp:215
uint32_t crl_number() const
Definition: x509_crl.cpp:239
bool is_CA_cert() const
Definition: x509cert.cpp:431
const X509_DN & subject_dn() const
Definition: x509cert.cpp:416
const std::vector< uint8_t > & subject_key_id() const
Definition: x509cert.cpp:395
static std::unique_ptr< PK_Signer > choose_sig_format(const Private_Key &key, RandomNumberGenerator &rng, std::string_view hash_fn, std::string_view padding_algo)
Definition: x509_obj.cpp:244
static std::vector< uint8_t > make_signed(PK_Signer &signer, RandomNumberGenerator &rng, const AlgorithmIdentifier &alg_id, const secure_vector< uint8_t > &tbs)
Definition: x509_obj.cpp:146
Definition: alg_id.cpp:12
ASN1_Time X509_Time
Definition: asn1_obj.h:422