monotone

monotone Mtn Source Tree

Root/botan/x509_obj.cpp

1/*************************************************
2* X.509 SIGNED Object Source File *
3* (C) 1999-2006 The Botan Project *
4*************************************************/
5
6#include <botan/x509_obj.h>
7#include <botan/x509_key.h>
8#include <botan/look_pk.h>
9#include <botan/oids.h>
10#include <botan/der_enc.h>
11#include <botan/ber_dec.h>
12#include <botan/parsing.h>
13#include <botan/pem.h>
14#include <algorithm>
15#include <memory>
16
17namespace Botan {
18
19/*************************************************
20* Create a generic X.509 object *
21*************************************************/
22X509_Object::X509_Object(DataSource& stream, const std::string& labels)
23 {
24 init(stream, labels);
25 }
26
27/*************************************************
28* Createa a generic X.509 object *
29*************************************************/
30X509_Object::X509_Object(const std::string& file, const std::string& labels)
31 {
32 DataSource_Stream stream(file, true);
33 init(stream, labels);
34 }
35
36/*************************************************
37* Read a PEM or BER X.509 object *
38*************************************************/
39void X509_Object::init(DataSource& in, const std::string& labels)
40 {
41 PEM_labels_allowed = split_on(labels, '/');
42 if(PEM_labels_allowed.size() < 1)
43 throw Invalid_Argument("Bad labels argument to X509_Object");
44
45 PEM_label_pref = PEM_labels_allowed[0];
46 std::sort(PEM_labels_allowed.begin(), PEM_labels_allowed.end());
47
48 try {
49 if(ASN1::maybe_BER(in) && !PEM_Code::matches(in))
50 decode_info(in);
51 else
52 {
53 std::string got_label;
54 DataSource_Memory ber(PEM_Code::decode(in, got_label));
55
56 if(!std::binary_search(PEM_labels_allowed.begin(),
57 PEM_labels_allowed.end(), got_label))
58 throw Decoding_Error("Invalid PEM label: " + got_label);
59 decode_info(ber);
60 }
61 }
62 catch(Decoding_Error)
63 {
64 throw Decoding_Error(PEM_label_pref + " decoding failed");
65 }
66 }
67
68/*************************************************
69* Read a BER encoded X.509 object *
70*************************************************/
71void X509_Object::decode_info(DataSource& source)
72 {
73 BER_Decoder(source)
74 .start_cons(SEQUENCE)
75 .start_cons(SEQUENCE)
76 .raw_bytes(tbs_bits)
77 .end_cons()
78 .decode(sig_algo)
79 .decode(sig, BIT_STRING)
80 .verify_end()
81 .end_cons();
82 }
83
84/*************************************************
85* Return a BER or PEM encoded X.509 object *
86*************************************************/
87void X509_Object::encode(Pipe& out, X509_Encoding encoding) const
88 {
89 SecureVector<byte> der = DER_Encoder()
90 .start_cons(SEQUENCE)
91 .start_cons(SEQUENCE)
92 .raw_bytes(tbs_bits)
93 .end_cons()
94 .encode(sig_algo)
95 .encode(sig, BIT_STRING)
96 .end_cons()
97 .get_contents();
98
99 if(encoding == PEM)
100 out.write(PEM_Code::encode(der, PEM_label_pref));
101 else
102 out.write(der);
103 }
104
105/*************************************************
106* Return a BER encoded X.509 object *
107*************************************************/
108SecureVector<byte> X509_Object::BER_encode() const
109 {
110 Pipe ber;
111 ber.start_msg();
112 encode(ber, RAW_BER);
113 ber.end_msg();
114 return ber.read_all();
115 }
116
117/*************************************************
118* Return a PEM encoded X.509 object *
119*************************************************/
120std::string X509_Object::PEM_encode() const
121 {
122 Pipe pem;
123 pem.start_msg();
124 encode(pem, PEM);
125 pem.end_msg();
126 return pem.read_all_as_string();
127 }
128
129/*************************************************
130* Return the TBS data *
131*************************************************/
132SecureVector<byte> X509_Object::tbs_data() const
133 {
134 return ASN1::put_in_sequence(tbs_bits);
135 }
136
137/*************************************************
138* Return the signature of this object *
139*************************************************/
140SecureVector<byte> X509_Object::signature() const
141 {
142 return sig;
143 }
144
145/*************************************************
146* Return the algorithm used to sign this object *
147*************************************************/
148AlgorithmIdentifier X509_Object::signature_algorithm() const
149 {
150 return sig_algo;
151 }
152
153/*************************************************
154* Check the signature on an object *
155*************************************************/
156bool X509_Object::check_signature(Public_Key& pub_key) const
157 {
158 try {
159 std::vector<std::string> sig_info =
160 split_on(OIDS::lookup(sig_algo.oid), '/');
161
162 if(sig_info.size() != 2 || sig_info[0] != pub_key.algo_name())
163 return false;
164
165 std::string padding = sig_info[1];
166 Signature_Format format =
167 (pub_key.message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363;
168
169 std::auto_ptr<PK_Verifier> verifier;
170
171 if(dynamic_cast<PK_Verifying_with_MR_Key*>(&pub_key))
172 {
173 PK_Verifying_with_MR_Key& sig_key =
174 dynamic_cast<PK_Verifying_with_MR_Key&>(pub_key);
175 verifier.reset(get_pk_verifier(sig_key, padding, format));
176 }
177 else if(dynamic_cast<PK_Verifying_wo_MR_Key*>(&pub_key))
178 {
179 PK_Verifying_wo_MR_Key& sig_key =
180 dynamic_cast<PK_Verifying_wo_MR_Key&>(pub_key);
181 verifier.reset(get_pk_verifier(sig_key, padding, format));
182 }
183 else
184 return false;
185
186 return verifier->verify_message(tbs_data(), signature());
187 }
188 catch(...)
189 {
190 return false;
191 }
192 }
193
194/*************************************************
195* Apply the X.509 SIGNED macro *
196*************************************************/
197MemoryVector<byte> X509_Object::make_signed(PK_Signer* signer,
198 const AlgorithmIdentifier& algo,
199 const MemoryRegion<byte>& tbs_bits)
200 {
201 return DER_Encoder()
202 .start_cons(SEQUENCE)
203 .raw_bytes(tbs_bits)
204 .encode(algo)
205 .encode(signer->sign_message(tbs_bits), BIT_STRING)
206 .end_cons()
207 .get_contents();
208 }
209
210/*************************************************
211* Try to decode the actual information *
212*************************************************/
213void X509_Object::do_decode()
214 {
215 try {
216 force_decode();
217 }
218 catch(Decoding_Error& e)
219 {
220 const std::string what = e.what();
221 throw Decoding_Error(PEM_label_pref + " decoding failed (" +
222 what.substr(23, std::string::npos) + ")");
223 }
224 catch(Invalid_Argument& e)
225 {
226 const std::string what = e.what();
227 throw Decoding_Error(PEM_label_pref + " decoding failed (" +
228 what.substr(7, std::string::npos) + ")");
229 }
230 }
231
232}

Archive Download this file

Branches

Tags

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