Botan  1.11.4
x509_obj.cpp
Go to the documentation of this file.
1 /*
2 * X.509 SIGNED Object
3 * (C) 1999-2007 Jack Lloyd
4 *
5 * Distributed under the terms of the Botan license
6 */
7 
8 #include <botan/x509_obj.h>
9 #include <botan/x509_key.h>
10 #include <botan/pubkey.h>
11 #include <botan/oids.h>
12 #include <botan/der_enc.h>
13 #include <botan/ber_dec.h>
14 #include <botan/parsing.h>
15 #include <botan/pem.h>
16 #include <algorithm>
17 #include <memory>
18 
19 namespace Botan {
20 
21 /*
22 * Create a generic X.509 object
23 */
24 X509_Object::X509_Object(DataSource& stream, const std::string& labels)
25  {
26  init(stream, labels);
27  }
28 
29 /*
30 * Create a generic X.509 object
31 */
32 X509_Object::X509_Object(const std::string& file, const std::string& labels)
33  {
34  DataSource_Stream stream(file, true);
35  init(stream, labels);
36  }
37 
38 /*
39 * Create a generic X.509 object
40 */
41 X509_Object::X509_Object(const std::vector<byte>& vec, const std::string& labels)
42  {
43  DataSource_Memory stream(&vec[0], vec.size());
44  init(stream, labels);
45  }
46 
47 /*
48 * Read a PEM or BER X.509 object
49 */
50 void X509_Object::init(DataSource& in, const std::string& labels)
51  {
52  PEM_labels_allowed = split_on(labels, '/');
53  if(PEM_labels_allowed.size() < 1)
54  throw Invalid_Argument("Bad labels argument to X509_Object");
55 
56  PEM_label_pref = PEM_labels_allowed[0];
57  std::sort(PEM_labels_allowed.begin(), PEM_labels_allowed.end());
58 
59  try {
60  if(ASN1::maybe_BER(in) && !PEM_Code::matches(in))
61  {
62  BER_Decoder dec(in);
63  decode_from(dec);
64  }
65  else
66  {
67  std::string got_label;
68  DataSource_Memory ber(PEM_Code::decode(in, got_label));
69 
70  if(!std::binary_search(PEM_labels_allowed.begin(),
71  PEM_labels_allowed.end(), got_label))
72  throw Decoding_Error("Invalid PEM label: " + got_label);
73 
74  BER_Decoder dec(ber);
75  decode_from(dec);
76  }
77  }
78  catch(Decoding_Error& e)
79  {
80  throw Decoding_Error(PEM_label_pref + " decoding failed: " + e.what());
81  }
82  }
83 
84 
86  {
90  .end_cons()
93  .end_cons();
94  }
95 
96 /*
97 * Read a BER encoded X.509 object
98 */
100  {
101  from.start_cons(SEQUENCE)
104  .end_cons()
105  .decode(sig_algo)
107  .verify_end()
108  .end_cons();
109  }
110 
111 /*
112 * Return a BER encoded X.509 object
113 */
114 std::vector<byte> X509_Object::BER_encode() const
115  {
116  DER_Encoder der;
117  encode_into(der);
118  return der.get_contents_unlocked();
119  }
120 
121 /*
122 * Return a PEM encoded X.509 object
123 */
124 std::string X509_Object::PEM_encode() const
125  {
126  return PEM_Code::encode(BER_encode(), PEM_label_pref);
127  }
128 
129 /*
130 * Return the TBS data
131 */
132 std::vector<byte> X509_Object::tbs_data() const
133  {
135  }
136 
137 /*
138 * Return the signature of this object
139 */
140 std::vector<byte> X509_Object::signature() const
141  {
142  return sig;
143  }
144 
145 /*
146 * Return the algorithm used to sign this object
147 */
149  {
150  return sig_algo;
151  }
152 
153 /*
154 * Return the hash used in generating the signature
155 */
157  {
158  std::vector<std::string> sig_info =
160 
161  if(sig_info.size() != 2)
162  throw Internal_Error("Invalid name format found for " +
164 
165  std::vector<std::string> pad_and_hash =
166  parse_algorithm_name(sig_info[1]);
167 
168  if(pad_and_hash.size() != 2)
169  throw Internal_Error("Invalid name format " + sig_info[1]);
170 
171  return pad_and_hash[1];
172  }
173 
174 /*
175 * Check the signature on an object
176 */
177 bool X509_Object::check_signature(const Public_Key* pub_key) const
178  {
179  std::unique_ptr<const Public_Key> key(pub_key);
180  return check_signature(*key);
181  }
182 
183 /*
184 * Check the signature on an object
185 */
186 bool X509_Object::check_signature(const Public_Key& pub_key) const
187  {
188  try {
189  std::vector<std::string> sig_info =
191 
192  if(sig_info.size() != 2 || sig_info[0] != pub_key.algo_name())
193  return false;
194 
195  std::string padding = sig_info[1];
196  Signature_Format format =
197  (pub_key.message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363;
198 
199  PK_Verifier verifier(pub_key, padding, format);
200 
201  return verifier.verify_message(tbs_data(), signature());
202  }
203  catch(std::exception& e)
204  {
205  return false;
206  }
207  }
208 
209 /*
210 * Apply the X.509 SIGNED macro
211 */
212 std::vector<byte> X509_Object::make_signed(PK_Signer* signer,
214  const AlgorithmIdentifier& algo,
215  const secure_vector<byte>& tbs_bits)
216  {
217  return DER_Encoder()
219  .raw_bytes(tbs_bits)
220  .encode(algo)
221  .encode(signer->sign_message(tbs_bits, rng), BIT_STRING)
222  .end_cons()
224  }
225 
226 /*
227 * Try to decode the actual information
228 */
230  {
231  try {
232  force_decode();
233  }
234  catch(Decoding_Error& e)
235  {
236  throw Decoding_Error(PEM_label_pref + " decoding failed (" +
237  e.what() + ")");
238  }
239  catch(Invalid_Argument& e)
240  {
241  throw Decoding_Error(PEM_label_pref + " decoding failed (" +
242  e.what() + ")");
243  }
244  }
245 
246 }