monotone

monotone Mtn Source Tree

Root/botan/x509_ca.cpp

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

Archive Download this file

Branches

Tags

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