monotone

monotone Mtn Source Tree

Root/botan/x509cert.cpp

1/*************************************************
2* X.509 Certificates Source File *
3* (C) 1999-2006 The Botan Project *
4*************************************************/
5
6#include <botan/x509cert.h>
7#include <botan/x509_ext.h>
8#include <botan/der_enc.h>
9#include <botan/ber_dec.h>
10#include <botan/stl_util.h>
11#include <botan/parsing.h>
12#include <botan/bigint.h>
13#include <botan/oids.h>
14#include <botan/pem.h>
15#include <algorithm>
16
17namespace Botan {
18
19namespace {
20
21/*************************************************
22* Lookup each OID in the vector *
23*************************************************/
24std::vector<std::string> lookup_oids(const std::vector<std::string>& in)
25 {
26 std::vector<std::string> out;
27
28 std::vector<std::string>::const_iterator i = in.begin();
29 while(i != in.end())
30 {
31 out.push_back(OIDS::lookup(OID(*i)));
32 ++i;
33 }
34 return out;
35 }
36
37}
38
39/*************************************************
40* X509_Certificate Constructor *
41*************************************************/
42X509_Certificate::X509_Certificate(DataSource& in) :
43 X509_Object(in, "CERTIFICATE/X509 CERTIFICATE")
44 {
45 self_signed = false;
46 do_decode();
47 }
48
49/*************************************************
50* X509_Certificate Constructor *
51*************************************************/
52X509_Certificate::X509_Certificate(const std::string& in) :
53 X509_Object(in, "CERTIFICATE/X509 CERTIFICATE")
54 {
55 self_signed = false;
56 do_decode();
57 }
58
59/*************************************************
60* Decode the TBSCertificate data *
61*************************************************/
62void X509_Certificate::force_decode()
63 {
64 u32bit version;
65 BigInt serial_bn;
66 AlgorithmIdentifier sig_algo_inner;
67 X509_DN dn_issuer, dn_subject;
68 X509_Time start, end;
69
70 BER_Decoder tbs_cert(tbs_bits);
71
72 tbs_cert.decode_optional(version, ASN1_Tag(0),
73 ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC))
74 .decode(serial_bn)
75 .decode(sig_algo_inner)
76 .decode(dn_issuer)
77 .start_cons(SEQUENCE)
78 .decode(start)
79 .decode(end)
80 .verify_end()
81 .end_cons()
82 .decode(dn_subject);
83
84 if(version > 2)
85 throw Decoding_Error("Unknown X.509 cert version " + to_string(version));
86 if(sig_algo != sig_algo_inner)
87 throw Decoding_Error("Algorithm identifier mismatch");
88
89 self_signed = (dn_subject == dn_issuer);
90
91 subject.add(dn_subject.contents());
92 issuer.add(dn_issuer.contents());
93
94 BER_Object public_key = tbs_cert.get_next_object();
95 if(public_key.type_tag != SEQUENCE || public_key.class_tag != CONSTRUCTED)
96 throw BER_Bad_Tag("X509_Certificate: Unexpected tag for public key",
97 public_key.type_tag, public_key.class_tag);
98
99 MemoryVector<byte> v2_issuer_key_id, v2_subject_key_id;
100
101 tbs_cert.decode_optional_string(v2_issuer_key_id, BIT_STRING, 1);
102 tbs_cert.decode_optional_string(v2_subject_key_id, BIT_STRING, 2);
103
104 BER_Object v3_exts_data = tbs_cert.get_next_object();
105 if(v3_exts_data.type_tag == 3 &&
106 v3_exts_data.class_tag == ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC))
107 {
108 Extensions extensions;
109
110 BER_Decoder(v3_exts_data.value).decode(extensions).verify_end();
111
112 extensions.contents_to(subject, issuer);
113 }
114 else if(v3_exts_data.type_tag != NO_OBJECT)
115 throw BER_Bad_Tag("Unknown tag in X.509 cert",
116 v3_exts_data.type_tag, v3_exts_data.class_tag);
117
118 if(tbs_cert.more_items())
119 throw Decoding_Error("TBSCertificate has more items that expected");
120
121 subject.add("X509.Certificate.version", version);
122 subject.add("X509.Certificate.serial", BigInt::encode(serial_bn));
123 subject.add("X509.Certificate.start", start.readable_string());
124 subject.add("X509.Certificate.end", end.readable_string());
125
126 issuer.add("X509.Certificate.v2.key_id", v2_issuer_key_id);
127 subject.add("X509.Certificate.v2.key_id", v2_subject_key_id);
128
129 subject.add("X509.Certificate.public_key",
130 PEM_Code::encode(
131 ASN1::put_in_sequence(public_key.value),
132 "PUBLIC KEY"
133 )
134 );
135
136 if(is_CA_cert() &&
137 !subject.has_value("X509v3.BasicConstraints.path_constraint"))
138 {
139 u32bit limit = (x509_version() < 3) ? NO_CERT_PATH_LIMIT : 0;
140 subject.add("X509v3.BasicConstraints.path_constraint", limit);
141 }
142 }
143
144/*************************************************
145* Return the X.509 version in use *
146*************************************************/
147u32bit X509_Certificate::x509_version() const
148 {
149 return (subject.get1_u32bit("X509.Certificate.version") + 1);
150 }
151
152/*************************************************
153* Return the time this cert becomes valid *
154*************************************************/
155std::string X509_Certificate::start_time() const
156 {
157 return subject.get1("X509.Certificate.start");
158 }
159
160/*************************************************
161* Return the time this cert becomes invalid *
162*************************************************/
163std::string X509_Certificate::end_time() const
164 {
165 return subject.get1("X509.Certificate.end");
166 }
167
168/*************************************************
169* Return information about the subject *
170*************************************************/
171std::vector<std::string>
172X509_Certificate::subject_info(const std::string& what) const
173 {
174 return subject.get(X509_DN::deref_info_field(what));
175 }
176
177/*************************************************
178* Return information about the issuer *
179*************************************************/
180std::vector<std::string>
181X509_Certificate::issuer_info(const std::string& what) const
182 {
183 return issuer.get(X509_DN::deref_info_field(what));
184 }
185
186/*************************************************
187* Return the public key in this certificate *
188*************************************************/
189Public_Key* X509_Certificate::subject_public_key() const
190 {
191 DataSource_Memory source(subject.get1("X509.Certificate.public_key"));
192 return X509::load_key(source);
193 }
194
195/*************************************************
196* Check if the certificate is for a CA *
197*************************************************/
198bool X509_Certificate::is_CA_cert() const
199 {
200 if(!subject.get1_u32bit("X509v3.BasicConstraints.is_ca"))
201 return false;
202 if((constraints() & KEY_CERT_SIGN) || (constraints() == NO_CONSTRAINTS))
203 return true;
204 return false;
205 }
206
207/*************************************************
208* Return the path length constraint *
209*************************************************/
210u32bit X509_Certificate::path_limit() const
211 {
212 return subject.get1_u32bit("X509v3.BasicConstraints.path_constraint", 0);
213 }
214
215/*************************************************
216* Return the key usage constraints *
217*************************************************/
218Key_Constraints X509_Certificate::constraints() const
219 {
220 return Key_Constraints(subject.get1_u32bit("X509v3.KeyUsage",
221 NO_CONSTRAINTS));
222 }
223
224/*************************************************
225* Return the list of extended key usage OIDs *
226*************************************************/
227std::vector<std::string> X509_Certificate::ex_constraints() const
228 {
229 return lookup_oids(subject.get("X509v3.ExtendedKeyUsage"));
230 }
231
232/*************************************************
233* Return the list of certificate policies *
234*************************************************/
235std::vector<std::string> X509_Certificate::policies() const
236 {
237 return lookup_oids(subject.get("X509v3.CertificatePolicies"));
238 }
239
240/*************************************************
241* Return the authority key id *
242*************************************************/
243MemoryVector<byte> X509_Certificate::authority_key_id() const
244 {
245 return issuer.get1_memvec("X509v3.AuthorityKeyIdentifier");
246 }
247
248/*************************************************
249* Return the subject key id *
250*************************************************/
251MemoryVector<byte> X509_Certificate::subject_key_id() const
252 {
253 return subject.get1_memvec("X509v3.SubjectKeyIdentifier");
254 }
255
256/*************************************************
257* Return the certificate serial number *
258*************************************************/
259MemoryVector<byte> X509_Certificate::serial_number() const
260 {
261 return subject.get1_memvec("X509.Certificate.serial");
262 }
263
264/*************************************************
265* Return the distinguished name of the issuer *
266*************************************************/
267X509_DN X509_Certificate::issuer_dn() const
268 {
269 return create_dn(issuer);
270 }
271
272/*************************************************
273* Return the distinguished name of the subject *
274*************************************************/
275X509_DN X509_Certificate::subject_dn() const
276 {
277 return create_dn(subject);
278 }
279
280/*************************************************
281* Compare two certificates for equality *
282*************************************************/
283bool X509_Certificate::operator==(const X509_Certificate& other) const
284 {
285 return (sig == other.sig &&
286 sig_algo == other.sig_algo &&
287 self_signed == other.self_signed &&
288 issuer == other.issuer &&
289 subject == other.subject);
290 }
291
292/*************************************************
293* X.509 Certificate Comparison *
294*************************************************/
295bool operator!=(const X509_Certificate& cert1, const X509_Certificate& cert2)
296 {
297 return !(cert1 == cert2);
298 }
299
300/*************************************************
301* Create and populate a X509_DN *
302*************************************************/
303X509_DN create_dn(const Data_Store& info)
304 {
305 class DN_Matcher : public Data_Store::Matcher
306 {
307 public:
308 bool operator()(const std::string& key, const std::string&) const
309 {
310 if(key.find("X520.") != std::string::npos)
311 return true;
312 return false;
313 }
314 };
315
316 std::multimap<std::string, std::string> names
317 = info.search_with(DN_Matcher());
318
319 X509_DN dn;
320
321 std::multimap<std::string, std::string>::iterator j;
322 for(j = names.begin(); j != names.end(); ++j)
323 dn.add_attribute(j->first, j->second);
324
325 return dn;
326 }
327
328/*************************************************
329* Create and populate an AlternativeName *
330*************************************************/
331AlternativeName create_alt_name(const Data_Store& info)
332 {
333 class AltName_Matcher : public Data_Store::Matcher
334 {
335 public:
336 bool operator()(const std::string& key, const std::string&) const
337 {
338 for(u32bit j = 0; j != matches.size(); j++)
339 if(key.compare(matches[j]) == 0)
340 return true;
341 return false;
342 }
343
344 AltName_Matcher(const std::string& match_any_of)
345 {
346 matches = split_on(match_any_of, '/');
347 }
348 private:
349 std::vector<std::string> matches;
350 };
351
352 std::multimap<std::string, std::string> names
353 = info.search_with(AltName_Matcher("RFC882/DNS/URI"));
354
355 AlternativeName alt_name;
356
357 std::multimap<std::string, std::string>::iterator j;
358 for(j = names.begin(); j != names.end(); ++j)
359 alt_name.add_attribute(j->first, j->second);
360
361 return alt_name;
362 }
363
364}

Archive Download this file

Branches

Tags

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