monotone

monotone Mtn Source Tree

Root/botan/x509_ca.cpp

1/*************************************************
2* X.509 Certificate Authority Source File *
3* (C) 1999-2007 The Botan Project *
4*************************************************/
5
6#include <botan/x509_ca.h>
7#include <botan/x509stor.h>
8#include <botan/der_enc.h>
9#include <botan/ber_dec.h>
10#include <botan/config.h>
11#include <botan/lookup.h>
12#include <botan/look_pk.h>
13#include <botan/numthry.h>
14#include <botan/oids.h>
15#include <botan/util.h>
16#include <algorithm>
17#include <typeinfo>
18#include <iterator>
19#include <memory>
20#include <set>
21
22namespace Botan {
23
24/*************************************************
25* Load the certificate and private key *
26*************************************************/
27X509_CA::X509_CA(const X509_Certificate& c,
28 const Private_Key& key) : cert(c)
29 {
30 const Private_Key* key_pointer = &key;
31 if(!dynamic_cast<const PK_Signing_Key*>(key_pointer))
32 throw Invalid_Argument("X509_CA: " + key.algo_name() + " cannot sign");
33
34 if(!cert.is_CA_cert())
35 throw Invalid_Argument("X509_CA: This certificate is not for a CA");
36
37 signer = choose_sig_format(key, ca_sig_algo);
38 }
39
40/*************************************************
41* Sign a PKCS #10 certificate request *
42*************************************************/
43X509_Certificate X509_CA::sign_request(const PKCS10_Request& req,
44 u32bit expire_time) const
45 {
46 if(req.is_CA() && !global_config().option_as_bool("x509/ca/allow_ca"))
47 throw Policy_Violation("X509_CA: Attempted to sign new CA certificate");
48
49 Key_Constraints constraints;
50 if(req.is_CA())
51 constraints = Key_Constraints(KEY_CERT_SIGN | CRL_SIGN);
52 else
53 {
54 std::auto_ptr<Public_Key> key(req.subject_public_key());
55 constraints = X509::find_constraints(*key, req.constraints());
56 }
57
58 Extensions extensions;
59
60 extensions.add(new Cert_Extension::Authority_Key_ID(cert.subject_key_id()));
61 extensions.add(new Cert_Extension::Subject_Key_ID(req.raw_public_key()));
62
63 extensions.add(
64 new Cert_Extension::Basic_Constraints(req.is_CA(), req.path_limit()));
65
66 extensions.add(new Cert_Extension::Key_Usage(constraints));
67 extensions.add(
68 new Cert_Extension::Extended_Key_Usage(req.ex_constraints()));
69
70 extensions.add(
71 new Cert_Extension::Subject_Alternative_Name(req.subject_alt_name()));
72
73 /*
74 extensions.add(
75 new Cert_Extension::Issuer_Alternative_Name(issuer_alt));
76 */
77
78 if(expire_time == 0)
79 expire_time = global_config().option_as_time("x509/ca/default_expire");
80
81 const u64bit current_time = system_time();
82
83 return make_cert(signer, ca_sig_algo, req.raw_public_key(),
84 X509_Time(current_time),
85 X509_Time(current_time + expire_time),
86 cert.subject_dn(), req.subject_dn(),
87 extensions);
88 }
89
90/*************************************************
91* Create a new certificate *
92*************************************************/
93X509_Certificate X509_CA::make_cert(PK_Signer* signer,
94 const AlgorithmIdentifier& sig_algo,
95 const MemoryRegion<byte>& pub_key,
96 const X509_Time& not_before,
97 const X509_Time& not_after,
98 const X509_DN& issuer_dn,
99 const X509_DN& subject_dn,
100 const Extensions& extensions)
101 {
102 const u32bit X509_CERT_VERSION = 3;
103 const u32bit SERIAL_BITS = 128;
104
105 DataSource_Memory source(X509_Object::make_signed(signer, sig_algo,
106 DER_Encoder().start_cons(SEQUENCE)
107 .start_explicit(0)
108 .encode(X509_CERT_VERSION-1)
109 .end_explicit()
110
111 .encode(random_integer(SERIAL_BITS))
112 .encode(sig_algo)
113 .encode(issuer_dn)
114
115 .start_cons(SEQUENCE)
116 .encode(not_before)
117 .encode(not_after)
118 .end_cons()
119
120 .encode(subject_dn)
121 .raw_bytes(pub_key)
122
123 .start_explicit(3)
124 .start_cons(SEQUENCE)
125 .encode(extensions)
126 .end_cons()
127 .end_explicit()
128 .end_cons()
129 .get_contents()
130 ));
131
132 return X509_Certificate(source);
133 }
134
135/*************************************************
136* Create a new, empty CRL *
137*************************************************/
138X509_CRL X509_CA::new_crl(u32bit next_update) const
139 {
140 std::vector<CRL_Entry> empty;
141 return make_crl(empty, 1, next_update);
142 }
143
144/*************************************************
145* Update a CRL with new entries *
146*************************************************/
147X509_CRL X509_CA::update_crl(const X509_CRL& crl,
148 const std::vector<CRL_Entry>& new_revoked,
149 u32bit next_update) const
150 {
151 std::vector<CRL_Entry> already_revoked = crl.get_revoked();
152 std::vector<CRL_Entry> all_revoked;
153
154 X509_Store store;
155 store.add_cert(cert, true);
156 if(store.add_crl(crl) != VERIFIED)
157 throw Invalid_Argument("X509_CA::update_crl: Invalid CRL provided");
158
159 std::set<SecureVector<byte> > removed_from_crl;
160 for(u32bit j = 0; j != new_revoked.size(); ++j)
161 {
162 if(new_revoked[j].reason_code() == DELETE_CRL_ENTRY)
163 removed_from_crl.insert(new_revoked[j].serial_number());
164 else
165 all_revoked.push_back(new_revoked[j]);
166 }
167
168 for(u32bit j = 0; j != already_revoked.size(); ++j)
169 {
170 std::set<SecureVector<byte> >::const_iterator i;
171 i = removed_from_crl.find(already_revoked[j].serial_number());
172
173 if(i == removed_from_crl.end())
174 all_revoked.push_back(already_revoked[j]);
175 }
176 std::sort(all_revoked.begin(), all_revoked.end());
177
178 std::vector<CRL_Entry> cert_list;
179 std::unique_copy(all_revoked.begin(), all_revoked.end(),
180 std::back_inserter(cert_list));
181
182 return make_crl(cert_list, crl.crl_number() + 1, next_update);
183 }
184
185/*************************************************
186* Create a CRL *
187*************************************************/
188X509_CRL X509_CA::make_crl(const std::vector<CRL_Entry>& revoked,
189 u32bit crl_number, u32bit next_update) const
190 {
191 const u32bit X509_CRL_VERSION = 2;
192
193 if(next_update == 0)
194 next_update = global_config().option_as_time("x509/crl/next_update");
195
196 const u64bit current_time = system_time();
197
198 Extensions extensions;
199 extensions.add(
200 new Cert_Extension::Authority_Key_ID(cert.subject_key_id()));
201 extensions.add(new Cert_Extension::CRL_Number(crl_number));
202
203 DataSource_Memory source(X509_Object::make_signed(signer, ca_sig_algo,
204 DER_Encoder().start_cons(SEQUENCE)
205 .encode(X509_CRL_VERSION-1)
206 .encode(ca_sig_algo)
207 .encode(cert.issuer_dn())
208 .encode(X509_Time(current_time))
209 .encode(X509_Time(current_time + next_update))
210 .encode_if(revoked.size() > 0,
211 DER_Encoder()
212 .start_cons(SEQUENCE)
213 .encode_list(revoked)
214 .end_cons()
215 )
216 .start_explicit(0)
217 .start_cons(SEQUENCE)
218 .encode(extensions)
219 .end_cons()
220 .end_explicit()
221 .end_cons()
222 .get_contents()
223 ));
224
225 return X509_CRL(source);
226 }
227
228/*************************************************
229* Return the CA's certificate *
230*************************************************/
231X509_Certificate X509_CA::ca_certificate() const
232 {
233 return cert;
234 }
235
236/*************************************************
237* X509_CA Destructor *
238*************************************************/
239X509_CA::~X509_CA()
240 {
241 delete signer;
242 }
243
244/*************************************************
245* Choose a signing format for the key *
246*************************************************/
247PK_Signer* choose_sig_format(const Private_Key& key,
248 AlgorithmIdentifier& sig_algo)
249 {
250 std::string padding;
251 Signature_Format format;
252 Config::choose_sig_format(key.algo_name(), padding, format);
253
254 sig_algo.oid = OIDS::lookup(key.algo_name() + "/" + padding);
255
256 std::auto_ptr<X509_Encoder> encoding(key.x509_encoder());
257 if(!encoding.get())
258 throw Encoding_Error("Key " + key.algo_name() + " does not support "
259 "X.509 encoding");
260
261 sig_algo.parameters = encoding->alg_id().parameters;
262
263 const PK_Signing_Key& sig_key = dynamic_cast<const PK_Signing_Key&>(key);
264
265 return get_pk_signer(sig_key, padding, format);
266 }
267
268}

Archive Download this file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status