monotone

monotone Mtn Source Tree

Root/botan/x509cert.cpp

1/*************************************************
2* X.509 Certificates Source File *
3* (C) 1999-2005 The Botan Project *
4*************************************************/
5
6#include <botan/x509cert.h>
7#include <botan/parsing.h>
8#include <botan/bigint.h>
9#include <botan/conf.h>
10#include <botan/oids.h>
11
12namespace Botan {
13
14namespace {
15
16/*************************************************
17* Get information from the DistinguishedName *
18*************************************************/
19void load_info(std::multimap<std::string, std::string>& names,
20 const X509_DN& dn_info)
21 {
22 typedef std::multimap<OID, std::string>::const_iterator rdn_iter;
23 std::multimap<OID, std::string> attr = dn_info.get_attributes();
24
25 for(rdn_iter j = attr.begin(); j != attr.end(); j++)
26 {
27 const std::string oid_name = OIDS::lookup(j->first);
28
29 if(oid_name == "PKCS9.EmailAddress")
30 multimap_insert(names, std::string("RFC822"), j->second);
31 else
32 multimap_insert(names, oid_name, j->second);
33 }
34 }
35
36/*************************************************
37* Get information from the alternative name *
38*************************************************/
39void load_info(std::multimap<std::string, std::string>& names,
40 const AlternativeName& alt_info)
41 {
42 typedef std::multimap<std::string, std::string>::const_iterator rdn_iter;
43 std::multimap<std::string, std::string> attr = alt_info.get_attributes();
44
45 for(rdn_iter j = attr.begin(); j != attr.end(); j++)
46 multimap_insert(names, j->first, j->second);
47
48 typedef std::multimap<OID, ASN1_String>::const_iterator on_iter;
49 std::multimap<OID, ASN1_String> othernames = alt_info.get_othernames();
50 for(on_iter j = othernames.begin(); j != othernames.end(); j++)
51 multimap_insert(names, OIDS::lookup(j->first), j->second.value());
52
53 }
54
55/*************************************************
56* Get some information from names *
57*************************************************/
58std::string get_info(const std::multimap<std::string, std::string>& names,
59 const std::string& info)
60 {
61 typedef std::multimap<std::string, std::string>::const_iterator rdn_iter;
62
63 const std::string what = X509_DN::deref_info_field(info);
64 std::pair<rdn_iter, rdn_iter> range = names.equal_range(what);
65
66 std::vector<std::string> results;
67 for(rdn_iter j = range.first; j != range.second; j++)
68 {
69 if(std::find(results.begin(), results.end(), j->second) == results.end())
70 results.push_back(j->second);
71 }
72
73 std::string value;
74 for(u32bit j = 0; j != results.size(); j++)
75 value += results[j] + '/';
76 if(value.size())
77 value.erase(value.size() - 1, 1);
78 return value;
79 }
80
81/*************************************************
82* Create and populate a X509_DN *
83*************************************************/
84X509_DN create_dn(const std::multimap<std::string, std::string>& names)
85 {
86 typedef std::multimap<std::string, std::string>::const_iterator rdn_iter;
87
88 X509_DN new_dn;
89 for(rdn_iter j = names.begin(); j != names.end(); j++)
90 {
91 const std::string oid = j->first;
92 const std::string value = j->second;
93 if(!OIDS::have_oid(oid))
94 continue;
95 new_dn.add_attribute(oid, j->second);
96 }
97 return new_dn;
98 }
99
100}
101
102/*************************************************
103* X509_Certificate Constructor *
104*************************************************/
105X509_Certificate::X509_Certificate(DataSource& in) :
106 X509_Object(in, "CERTIFICATE/X509 CERTIFICATE")
107 {
108 is_ca = false;
109 version = max_path_len = 0;
110 constraints_value = NO_CONSTRAINTS;
111 do_decode();
112 }
113
114/*************************************************
115* X509_Certificate Constructor *
116*************************************************/
117X509_Certificate::X509_Certificate(const std::string& in) :
118 X509_Object(in, "CERTIFICATE/X509 CERTIFICATE")
119 {
120 is_ca = false;
121 version = max_path_len = 0;
122 constraints_value = NO_CONSTRAINTS;
123 do_decode();
124 }
125
126/*************************************************
127* Decode the TBSCertificate data *
128*************************************************/
129void X509_Certificate::force_decode()
130 {
131 BER_Decoder tbs_cert(tbs_bits);
132
133 BER::decode_optional(tbs_cert, version, ASN1_Tag(0),
134 ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC));
135
136 if(version > 2)
137 throw Decoding_Error("Unknown X.509 cert version " + to_string(version));
138 if(version < 2)
139 {
140 is_ca = Config::get_bool("x509/v1_assume_ca");
141 max_path_len = NO_CERT_PATH_LIMIT;
142 }
143
144 BER::decode(tbs_cert, serial);
145
146 AlgorithmIdentifier sig_algo_inner;
147 BER::decode(tbs_cert, sig_algo_inner);
148
149 if(sig_algo != sig_algo_inner)
150 throw Decoding_Error("Algorithm identifier mismatch");
151
152 X509_DN dn_issuer;
153 BER::decode(tbs_cert, dn_issuer);
154 load_info(issuer, dn_issuer);
155
156 BER_Decoder validity = BER::get_subsequence(tbs_cert);
157 BER::decode(validity, start);
158 BER::decode(validity, end);
159 validity.verify_end();
160
161 X509_DN dn_subject;
162 BER::decode(tbs_cert, dn_subject);
163 load_info(subject, dn_subject);
164
165 BER_Object public_key = tbs_cert.get_next_object();
166 if(public_key.type_tag != SEQUENCE || public_key.class_tag != CONSTRUCTED)
167 throw BER_Bad_Tag("X509_Certificate: Unexpected tag for public key",
168 public_key.type_tag, public_key.class_tag);
169 pub_key = DER::put_in_sequence(public_key.value);
170
171 BER::decode_optional_string(tbs_cert, v2_issuer_key_id, BIT_STRING,
172 ASN1_Tag(1), CONTEXT_SPECIFIC);
173 BER::decode_optional_string(tbs_cert, v2_subject_key_id, BIT_STRING,
174 ASN1_Tag(2), CONTEXT_SPECIFIC);
175
176 BER_Object v3_exts_data = tbs_cert.get_next_object();
177 if(v3_exts_data.type_tag == 3 &&
178 v3_exts_data.class_tag == ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC))
179 {
180 BER_Decoder v3_exts_decoder(v3_exts_data.value);
181 BER_Decoder sequence = BER::get_subsequence(v3_exts_decoder);
182
183 while(sequence.more_items())
184 {
185 Extension extn;
186 BER::decode(sequence, extn);
187 handle_v3_extension(extn);
188 }
189 sequence.verify_end();
190 v3_exts_decoder.verify_end();
191 }
192 else if(v3_exts_data.type_tag != NO_OBJECT)
193 throw BER_Bad_Tag("Unknown tag in X.509 cert",
194 v3_exts_data.type_tag, v3_exts_data.class_tag);
195
196 if(tbs_cert.more_items())
197 throw Decoding_Error("TBSCertificate has more items that expected");
198 }
199
200/*************************************************
201* Decode a particular v3 extension *
202*************************************************/
203void X509_Certificate::handle_v3_extension(const Extension& extn)
204 {
205 BER_Decoder value(extn.value);
206
207 if(extn.oid == OIDS::lookup("X509v3.KeyUsage"))
208 BER::decode(value, constraints_value);
209 else if(extn.oid == OIDS::lookup("X509v3.ExtendedKeyUsage"))
210 {
211 BER_Decoder key_usage = BER::get_subsequence(value);
212 while(key_usage.more_items())
213 {
214 OID usage_oid;
215 BER::decode(key_usage, usage_oid);
216 ex_constraints_list.push_back(usage_oid);
217 }
218 std::sort(ex_constraints_list.begin(), ex_constraints_list.end());
219 }
220 else if(extn.oid == OIDS::lookup("X509v3.BasicConstraints"))
221 {
222 BER_Decoder basic_constraints = BER::get_subsequence(value);
223 BER::decode_optional(basic_constraints, is_ca,
224 BOOLEAN, UNIVERSAL, false);
225 BER::decode_optional(basic_constraints, max_path_len,
226 INTEGER, UNIVERSAL, NO_CERT_PATH_LIMIT);
227 }
228 else if(extn.oid == OIDS::lookup("X509v3.SubjectKeyIdentifier"))
229 BER::decode(value, v3_subject_key_id, OCTET_STRING);
230 else if(extn.oid == OIDS::lookup("X509v3.AuthorityKeyIdentifier"))
231 {
232 BER_Decoder key_id = BER::get_subsequence(value);
233 BER::decode_optional_string(key_id, v3_issuer_key_id, OCTET_STRING,
234 ASN1_Tag(0), CONTEXT_SPECIFIC);
235 }
236 else if(extn.oid == OIDS::lookup("X509v3.SubjectAlternativeName"))
237 {
238 AlternativeName alt_name;
239 BER::decode(value, alt_name);
240 load_info(subject, alt_name);
241 }
242 else if(extn.oid == OIDS::lookup("X509v3.IssuerAlternativeName"))
243 {
244 AlternativeName alt_name;
245 BER::decode(value, alt_name);
246 load_info(issuer, alt_name);
247 }
248 else if(extn.oid == OIDS::lookup("X509v3.CertificatePolicies"))
249 {
250 BER_Decoder ber_policies = BER::get_subsequence(value);
251 while(ber_policies.more_items())
252 {
253 OID oid;
254 BER_Decoder policy = BER::get_subsequence(ber_policies);
255 BER::decode(policy, oid);
256
257 if(extn.critical && policy.more_items())
258 throw Decoding_Error("X.509 v3 critical policy has qualifiers");
259
260 policies_list.push_back(oid);
261 }
262 }
263 else
264 {
265 if(extn.critical)
266 throw Decoding_Error("Unknown critical X.509 v3 extension: " +
267 extn.oid.as_string());
268 return;
269 }
270
271 value.verify_end();
272 }
273
274/*************************************************
275* Return the X.509 version in use *
276*************************************************/
277u32bit X509_Certificate::x509_version() const
278 {
279 return (version + 1);
280 }
281
282/*************************************************
283* Return the time this cert becomes valid *
284*************************************************/
285std::string X509_Certificate::start_time() const
286 {
287 return start.readable_string();
288 }
289
290/*************************************************
291* Return the time this cert becomes invalid *
292*************************************************/
293std::string X509_Certificate::end_time() const
294 {
295 return end.readable_string();
296 }
297
298/*************************************************
299* Return information about the subject *
300*************************************************/
301std::string X509_Certificate::subject_info(const std::string& info) const
302 {
303 return get_info(subject, info);
304 }
305
306/*************************************************
307* Return information about the issuer *
308*************************************************/
309std::string X509_Certificate::issuer_info(const std::string& info) const
310 {
311 return get_info(issuer, info);
312 }
313
314/*************************************************
315* Return the public key in this certificate *
316*************************************************/
317X509_PublicKey* X509_Certificate::subject_public_key() const
318 {
319 return X509::load_key(pub_key);
320 }
321
322/*************************************************
323* Check if the certificate is self-signed *
324*************************************************/
325bool X509_Certificate::self_signed() const
326 {
327 return (create_dn(issuer) == create_dn(subject));
328 }
329
330/*************************************************
331* Check if the certificate has a SKID *
332*************************************************/
333bool X509_Certificate::has_SKID() const
334 {
335 if(v3_subject_key_id.has_items())
336 return true;
337 return false;
338 }
339
340/*************************************************
341* Check if the certificate is for a CA *
342*************************************************/
343bool X509_Certificate::is_CA_cert() const
344 {
345 if(!is_ca) return false;
346 if((constraints_value & KEY_CERT_SIGN) ||
347 (constraints_value == NO_CONSTRAINTS))
348 return true;
349 return false;
350 }
351
352/*************************************************
353* Return the path length constraint *
354*************************************************/
355u32bit X509_Certificate::path_limit() const
356 {
357 return max_path_len;
358 }
359
360/*************************************************
361* Return the key usage constraints *
362*************************************************/
363Key_Constraints X509_Certificate::constraints() const
364 {
365 return constraints_value;
366 }
367
368/*************************************************
369* Return the list of extended key usage OIDs *
370*************************************************/
371std::vector<OID> X509_Certificate::ex_constraints() const
372 {
373 return ex_constraints_list;
374 }
375
376/*************************************************
377* Return the list of certificate policies *
378*************************************************/
379std::vector<OID> X509_Certificate::policies() const
380 {
381 return policies_list;
382 }
383
384/*************************************************
385* Return the authority key id *
386*************************************************/
387MemoryVector<byte> X509_Certificate::authority_key_id() const
388 {
389 return v3_issuer_key_id;
390 }
391
392/*************************************************
393* Return the subject key id *
394*************************************************/
395MemoryVector<byte> X509_Certificate::subject_key_id() const
396 {
397 return v3_subject_key_id;
398 }
399
400/*************************************************
401* Return the certificate serial number *
402*************************************************/
403MemoryVector<byte> X509_Certificate::serial_number() const
404 {
405 return BigInt::encode(serial);
406 }
407
408/*************************************************
409* Return the certificate serial number *
410*************************************************/
411BigInt X509_Certificate::serial_number_bn() const
412 {
413 return serial;
414 }
415
416/*************************************************
417* Return the distinguished name of the issuer *
418*************************************************/
419X509_DN X509_Certificate::issuer_dn() const
420 {
421 return create_dn(issuer);
422 }
423
424/*************************************************
425* Return the distinguished name of the subject *
426*************************************************/
427X509_DN X509_Certificate::subject_dn() const
428 {
429 return create_dn(subject);
430 }
431
432/*************************************************
433* Compare two certificates for equality *
434*************************************************/
435bool X509_Certificate::operator==(const X509_Certificate& cert) const
436 {
437 if(sig != cert.sig || pub_key != cert.pub_key || sig_algo != cert.sig_algo)
438 return false;
439 if(issuer != cert.issuer || subject != cert.subject)
440 return false;
441 if(serial != cert.serial || version != cert.version)
442 return false;
443 if(start != cert.start || end != cert.end)
444 return false;
445 return true;
446 }
447
448/*************************************************
449* X.509 Certificate Comparison *
450*************************************************/
451bool operator!=(const X509_Certificate& cert1, const X509_Certificate& cert2)
452 {
453 return !(cert1 == cert2);
454 }
455
456}

Archive Download this file

Branches

Tags

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