Botan  1.10.9
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 * Createa 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 * Read a PEM or BER X.509 object
40 */
41 void X509_Object::init(DataSource& in, const std::string& labels)
42  {
43  PEM_labels_allowed = split_on(labels, '/');
44  if(PEM_labels_allowed.size() < 1)
45  throw Invalid_Argument("Bad labels argument to X509_Object");
46 
47  PEM_label_pref = PEM_labels_allowed[0];
48  std::sort(PEM_labels_allowed.begin(), PEM_labels_allowed.end());
49 
50  try {
51  if(ASN1::maybe_BER(in) && !PEM_Code::matches(in))
52  decode_info(in);
53  else
54  {
55  std::string got_label;
56  DataSource_Memory ber(PEM_Code::decode(in, got_label));
57 
58  if(!std::binary_search(PEM_labels_allowed.begin(),
59  PEM_labels_allowed.end(), got_label))
60  throw Decoding_Error("Invalid PEM label: " + got_label);
61  decode_info(ber);
62  }
63  }
64  catch(Decoding_Error& e)
65  {
66  throw Decoding_Error(PEM_label_pref + " decoding failed: " + e.what());
67  }
68  }
69 
70 /*
71 * Read a BER encoded X.509 object
72 */
73 void X509_Object::decode_info(DataSource& source)
74  {
75  BER_Decoder(source)
76  .start_cons(SEQUENCE)
77  .start_cons(SEQUENCE)
78  .raw_bytes(tbs_bits)
79  .end_cons()
80  .decode(sig_algo)
81  .decode(sig, BIT_STRING)
82  .verify_end()
83  .end_cons();
84  }
85 
86 /*
87 * Return a BER or PEM encoded X.509 object
88 */
89 void X509_Object::encode(Pipe& out, X509_Encoding encoding) const
90  {
91  if(encoding == PEM)
92  out.write(this->PEM_encode());
93  else
94  out.write(this->BER_encode());
95  }
96 
97 /*
98 * Return a BER encoded X.509 object
99 */
101  {
102  return DER_Encoder()
106  .end_cons()
107  .encode(sig_algo)
109  .end_cons()
110  .get_contents();
111  }
112 
113 /*
114 * Return a PEM encoded X.509 object
115 */
116 std::string X509_Object::PEM_encode() const
117  {
118  return PEM_Code::encode(BER_encode(), PEM_label_pref);
119  }
120 
121 /*
122 * Return the TBS data
123 */
125  {
127  }
128 
129 /*
130 * Return the signature of this object
131 */
133  {
134  return sig;
135  }
136 
137 /*
138 * Return the algorithm used to sign this object
139 */
141  {
142  return sig_algo;
143  }
144 
145 /*
146 * Return the hash used in generating the signature
147 */
149  {
150  std::vector<std::string> sig_info =
152 
153  if(sig_info.size() != 2)
154  throw Internal_Error("Invalid name format found for " +
156 
157  std::vector<std::string> pad_and_hash =
158  parse_algorithm_name(sig_info[1]);
159 
160  if(pad_and_hash.size() != 2)
161  throw Internal_Error("Invalid name format " + sig_info[1]);
162 
163  return pad_and_hash[1];
164  }
165 
166 /*
167 * Check the signature on an object
168 */
170  {
171  std::auto_ptr<Public_Key> key(pub_key);
172  return check_signature(*key);
173  }
174 
175 /*
176 * Check the signature on an object
177 */
179  {
180  try {
181  std::vector<std::string> sig_info =
183 
184  if(sig_info.size() != 2 || sig_info[0] != pub_key.algo_name())
185  return false;
186 
187  std::string padding = sig_info[1];
188  Signature_Format format =
189  (pub_key.message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363;
190 
191  PK_Verifier verifier(pub_key, padding, format);
192 
193  return verifier.verify_message(tbs_data(), signature());
194  }
195  catch(...)
196  {
197  return false;
198  }
199  }
200 
201 /*
202 * Apply the X.509 SIGNED macro
203 */
206  const AlgorithmIdentifier& algo,
207  const MemoryRegion<byte>& tbs_bits)
208  {
209  return DER_Encoder()
211  .raw_bytes(tbs_bits)
212  .encode(algo)
213  .encode(signer->sign_message(tbs_bits, rng), BIT_STRING)
214  .end_cons()
215  .get_contents();
216  }
217 
218 /*
219 * Try to decode the actual information
220 */
222  {
223  try {
224  force_decode();
225  }
226  catch(Decoding_Error& e)
227  {
228  throw Decoding_Error(PEM_label_pref + " decoding failed (" +
229  e.what() + ")");
230  }
231  catch(Invalid_Argument& e)
232  {
233  throw Decoding_Error(PEM_label_pref + " decoding failed (" +
234  e.what() + ")");
235  }
236  }
237 
238 }
std::vector< std::string > parse_algorithm_name(const std::string &namex)
Definition: parsing.cpp:96
SecureVector< byte > get_contents()
Definition: der_enc.cpp:122
MemoryVector< byte > tbs_bits
Definition: x509_obj.h:102
std::string hash_used_for_signature() const
Definition: x509_obj.cpp:148
DER_Encoder & raw_bytes(const byte val[], size_t len)
Definition: der_enc.cpp:188
void write(const byte in[], size_t length)
Definition: pipe_rw.cpp:34
void encode(Pipe &out, X509_Encoding encoding=PEM) const
Definition: x509_obj.cpp:89
Signature_Format
Definition: pubkey.h:24
std::vector< std::string > split_on(const std::string &str, char delim)
Definition: parsing.cpp:152
X509_Encoding
Definition: pubkey_enums.h:67
virtual std::string algo_name() const =0
std::invalid_argument Invalid_Argument
Definition: exceptn.h:20
bool maybe_BER(DataSource &source)
Definition: asn1_int.cpp:55
DER_Encoder & end_cons()
Definition: der_enc.cpp:145
bool check_signature(class Public_Key &key) const
Definition: x509_obj.cpp:178
SecureVector< byte > decode(DataSource &source, std::string &label)
Definition: pem.cpp:56
DER_Encoder & encode(bool b)
Definition: der_enc.cpp:209
std::string PEM_encode() const
Definition: x509_obj.cpp:116
RandomNumberGenerator * rng
Definition: global_rng.cpp:165
SecureVector< byte > sign_message(const byte in[], size_t length, RandomNumberGenerator &rng)
Definition: pubkey.cpp:160
AlgorithmIdentifier sig_algo
Definition: x509_obj.h:101
std::string lookup(const OID &oid)
Definition: oids.cpp:31
virtual size_t message_parts() const
Definition: pk_keys.h:50
bool verify_message(const byte msg[], size_t msg_length, const byte sig[], size_t sig_length)
Definition: pubkey.cpp:283
MemoryVector< byte > signature() const
Definition: x509_obj.cpp:132
bool matches(DataSource &source, const std::string &extra, size_t search_range)
Definition: pem.cpp:116
static MemoryVector< byte > make_signed(class PK_Signer *signer, RandomNumberGenerator &rng, const AlgorithmIdentifier &alg_id, const MemoryRegion< byte > &tbs)
Definition: x509_obj.cpp:204
MemoryVector< byte > sig
Definition: x509_obj.h:102
SecureVector< byte > put_in_sequence(const MemoryRegion< byte > &contents)
Definition: asn1_int.cpp:34
std::string encode(const byte der[], size_t length, const std::string &label, size_t width)
Definition: pem.cpp:19
std::string as_string() const
Definition: asn1_oid.cpp:50
MemoryVector< byte > BER_encode() const
Definition: x509_obj.cpp:100
DER_Encoder & start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Definition: der_enc.cpp:135
MemoryVector< byte > tbs_data() const
Definition: x509_obj.cpp:124
AlgorithmIdentifier signature_algorithm() const
Definition: x509_obj.cpp:140