Botan  2.0.1
Crypto and TLS for C++11
x509_obj.cpp
Go to the documentation of this file.
1 /*
2 * X.509 SIGNED Object
3 * (C) 1999-2007 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
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 
18 namespace Botan {
19 
20 /*
21 * Create a generic X.509 object
22 */
23 X509_Object::X509_Object(DataSource& stream, const std::string& labels)
24  {
25  init(stream, labels);
26  }
27 
28 #if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
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 #endif
38 
39 /*
40 * Create a generic X.509 object
41 */
42 X509_Object::X509_Object(const std::vector<uint8_t>& vec, const std::string& labels)
43  {
44  DataSource_Memory stream(vec.data(), vec.size());
45  init(stream, labels);
46  }
47 
48 /*
49 * Read a PEM or BER X.509 object
50 */
51 void X509_Object::init(DataSource& in, const std::string& labels)
52  {
53  m_PEM_labels_allowed = split_on(labels, '/');
54  if(m_PEM_labels_allowed.size() < 1)
55  throw Invalid_Argument("Bad labels argument to X509_Object");
56 
57  m_PEM_label_pref = m_PEM_labels_allowed[0];
58  std::sort(m_PEM_labels_allowed.begin(), m_PEM_labels_allowed.end());
59 
60  try {
61  if(ASN1::maybe_BER(in) && !PEM_Code::matches(in))
62  {
63  BER_Decoder dec(in);
64  decode_from(dec);
65  }
66  else
67  {
68  std::string got_label;
69  DataSource_Memory ber(PEM_Code::decode(in, got_label));
70 
71  if(!std::binary_search(m_PEM_labels_allowed.begin(),
72  m_PEM_labels_allowed.end(), got_label))
73  throw Decoding_Error("Invalid PEM label: " + got_label);
74 
75  BER_Decoder dec(ber);
76  decode_from(dec);
77  }
78  }
79  catch(Decoding_Error& e)
80  {
81  throw Decoding_Error(m_PEM_label_pref + " decoding failed: " + e.what());
82  }
83  }
84 
85 
87  {
91  .end_cons()
94  .end_cons();
95  }
96 
97 /*
98 * Read a BER encoded X.509 object
99 */
101  {
102  from.start_cons(SEQUENCE)
105  .end_cons()
108  .end_cons();
109  }
110 
111 /*
112 * Return a BER encoded X.509 object
113 */
114 std::vector<uint8_t> 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(), m_PEM_label_pref);
127  }
128 
129 /*
130 * Return the TBS data
131 */
132 std::vector<uint8_t> X509_Object::tbs_data() const
133  {
135  }
136 
137 /*
138 * Return the signature of this object
139 */
140 std::vector<uint8_t> X509_Object::signature() const
141  {
142  return m_sig;
143  }
144 
145 /*
146 * Return the algorithm used to sign this object
147 */
149  {
150  return m_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  if(!pub_key)
180  throw Exception("No key provided for " + m_PEM_label_pref + " signature check");
181  std::unique_ptr<const Public_Key> key(pub_key);
182  return check_signature(*key);
183 }
184 
185 /*
186 * Check the signature on an object
187 */
188 bool X509_Object::check_signature(const Public_Key& pub_key) const
189  {
190  try {
191  std::vector<std::string> sig_info =
193 
194  if(sig_info.size() != 2 || sig_info[0] != pub_key.algo_name())
195  return false;
196 
197  std::string padding = sig_info[1];
198  Signature_Format format =
199  (pub_key.message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363;
200 
201  PK_Verifier verifier(pub_key, padding, format);
202 
203  return verifier.verify_message(tbs_data(), signature());
204  }
205  catch(std::exception&)
206  {
207  return false;
208  }
209  }
210 
211 /*
212 * Apply the X.509 SIGNED macro
213 */
214 std::vector<uint8_t> X509_Object::make_signed(PK_Signer* signer,
216  const AlgorithmIdentifier& algo,
217  const secure_vector<uint8_t>& tbs_bits)
218  {
219  return DER_Encoder()
221  .raw_bytes(tbs_bits)
222  .encode(algo)
223  .encode(signer->sign_message(tbs_bits, rng), BIT_STRING)
224  .end_cons()
226  }
227 
228 /*
229 * Try to decode the actual information
230 */
232  {
233  try {
234  force_decode();
235  }
236  catch(Decoding_Error& e)
237  {
238  throw Decoding_Error(m_PEM_label_pref + " decoding failed (" +
239  e.what() + ")");
240  }
241  catch(Invalid_Argument& e)
242  {
243  throw Decoding_Error(m_PEM_label_pref + " decoding failed (" +
244  e.what() + ")");
245  }
246  }
247 
248 }
std::vector< std::string > parse_algorithm_name(const std::string &namex)
Definition: parsing.cpp:85
AlgorithmIdentifier m_sig_algo
Definition: x509_obj.h:109
secure_vector< uint8_t > decode(DataSource &source, std::string &label)
Definition: pem.cpp:68
std::vector< uint8_t > get_contents_unlocked()
Definition: der_enc.h:27
bool verify_message(const uint8_t msg[], size_t msg_length, const uint8_t sig[], size_t sig_length)
Definition: pubkey.cpp:280
void encode_into(class DER_Encoder &to) const override
Definition: x509_obj.cpp:86
std::string encode(const uint8_t der[], size_t length, const std::string &label, size_t width)
Definition: pem.cpp:43
std::string as_string() const
Definition: asn1_oid.cpp:50
static std::vector< uint8_t > make_signed(class PK_Signer *signer, RandomNumberGenerator &rng, const AlgorithmIdentifier &alg_id, const secure_vector< uint8_t > &tbs)
Definition: x509_obj.cpp:214
Signature_Format
Definition: pubkey.h:29
std::vector< std::string > split_on(const std::string &str, char delim)
Definition: parsing.cpp:138
virtual std::string algo_name() const =0
BER_Decoder & decode(bool &v)
Definition: ber_dec.cpp:376
bool maybe_BER(DataSource &source)
Definition: asn1_obj.cpp:55
DER_Encoder & end_cons()
Definition: der_enc.cpp:147
bool check_signature(const Public_Key &key) const
Definition: x509_obj.cpp:188
X509_Object()=default
std::vector< uint8_t > sign_message(const uint8_t in[], size_t length, RandomNumberGenerator &rng)
Definition: pubkey.h:209
DER_Encoder & raw_bytes(const uint8_t val[], size_t len)
Definition: der_enc.cpp:195
void decode_from(class BER_Decoder &from) override
Definition: x509_obj.cpp:100
DER_Encoder & encode(bool b)
Definition: der_enc.cpp:216
AlgorithmIdentifier signature_algorithm() const
Definition: x509_obj.cpp:148
std::vector< uint8_t > m_tbs_bits
Definition: x509_obj.h:110
BER_Decoder & end_cons()
Definition: ber_dec.cpp:272
std::string lookup(const OID &oid)
Definition: oids.cpp:18
std::vector< uint8_t > signature() const
Definition: x509_obj.cpp:140
std::vector< uint8_t > tbs_data() const
Definition: x509_obj.cpp:132
const char * what() const BOTAN_NOEXCEPT override
Definition: exceptn.h:26
BER_Decoder start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Definition: ber_dec.cpp:258
Definition: alg_id.cpp:13
bool matches(DataSource &source, const std::string &extra, size_t search_range)
Definition: pem.cpp:140
std::vector< uint8_t > BER_encode() const
Definition: x509_obj.cpp:114
std::vector< uint8_t > put_in_sequence(const std::vector< uint8_t > &contents)
Definition: asn1_obj.cpp:35
std::string hash_used_for_signature() const
Definition: x509_obj.cpp:156
DER_Encoder & start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Definition: der_enc.cpp:137
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:121
BER_Decoder & raw_bytes(secure_vector< uint8_t > &v)
Definition: ber_dec.cpp:178
std::string PEM_encode() const
Definition: x509_obj.cpp:124
std::vector< uint8_t > m_sig
Definition: x509_obj.h:110
virtual size_t message_parts() const
Definition: pk_keys.h:103