Botan  2.7.0
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/pubkey.h>
10 #include <botan/oids.h>
11 #include <botan/der_enc.h>
12 #include <botan/ber_dec.h>
13 #include <botan/parsing.h>
14 #include <botan/pem.h>
15 #include <botan/emsa.h>
16 #include <algorithm>
17 
18 namespace Botan {
19 
20 namespace {
21 struct Pss_params
22  {
23  AlgorithmIdentifier hash_algo;
24  AlgorithmIdentifier mask_gen_algo;
25  AlgorithmIdentifier mask_gen_hash; // redundant: decoded mask_gen_algo.parameters
26  size_t salt_len;
27  size_t trailer_field;
28  };
29 
30 Pss_params decode_pss_params(const std::vector<uint8_t>& encoded_pss_params)
31  {
32  const AlgorithmIdentifier default_hash("SHA-160", AlgorithmIdentifier::USE_NULL_PARAM);
33  const AlgorithmIdentifier default_mgf("MGF1", default_hash.BER_encode());
34 
35  Pss_params pss_parameter;
36  BER_Decoder(encoded_pss_params)
37  .start_cons(SEQUENCE)
38  .decode_optional(pss_parameter.hash_algo, ASN1_Tag(0), PRIVATE, default_hash)
39  .decode_optional(pss_parameter.mask_gen_algo, ASN1_Tag(1), PRIVATE, default_mgf)
40  .decode_optional(pss_parameter.salt_len, ASN1_Tag(2), PRIVATE, size_t(20))
41  .decode_optional(pss_parameter.trailer_field, ASN1_Tag(3), PRIVATE, size_t(1))
42  .end_cons();
43 
44  BER_Decoder(pss_parameter.mask_gen_algo.get_parameters()).decode(pss_parameter.mask_gen_hash);
45 
46  return pss_parameter;
47  }
48 }
49 
50 /*
51 * Read a PEM or BER X.509 object
52 */
54  {
55  try {
56  if(ASN1::maybe_BER(in) && !PEM_Code::matches(in))
57  {
58  BER_Decoder dec(in);
59  decode_from(dec);
60  }
61  else
62  {
63  std::string got_label;
64  DataSource_Memory ber(PEM_Code::decode(in, got_label));
65 
66  if(got_label != PEM_label())
67  {
68  bool is_alternate = false;
69  for(std::string alt_label : alternate_PEM_labels())
70  {
71  if(got_label == alt_label)
72  {
73  is_alternate = true;
74  break;
75  }
76  }
77 
78  if(!is_alternate)
79  throw Decoding_Error("Unexpected PEM label for " + PEM_label() + " of " + got_label);
80  }
81 
82  BER_Decoder dec(ber);
83  decode_from(dec);
84  }
85  }
86  catch(Decoding_Error& e)
87  {
88  throw Decoding_Error(PEM_label() + " decoding failed: " + e.what());
89  }
90  }
91 
92 
94  {
98  .end_cons()
101  .end_cons();
102  }
103 
104 /*
105 * Read a BER encoded X.509 object
106 */
108  {
109  from.start_cons(SEQUENCE)
111  .raw_bytes(m_tbs_bits)
112  .end_cons()
113  .decode(m_sig_algo)
114  .decode(m_sig, BIT_STRING)
115  .end_cons();
116 
117  force_decode();
118  }
119 
120 /*
121 * Return a PEM encoded X.509 object
122 */
123 std::string X509_Object::PEM_encode() const
124  {
126  }
127 
128 /*
129 * Return the TBS data
130 */
131 std::vector<uint8_t> X509_Object::tbs_data() const
132  {
133  return ASN1::put_in_sequence(m_tbs_bits);
134  }
135 
136 /*
137 * Return the hash used in generating the signature
138 */
140  {
141  const OID& oid = m_sig_algo.get_oid();
142  const std::vector<std::string> sig_info = split_on(OIDS::lookup(oid), '/');
143 
144  if(sig_info.size() == 1 && sig_info[0] == "Ed25519")
145  return "SHA-512";
146  else if(sig_info.size() != 2)
147  throw Internal_Error("Invalid name format found for " + oid.as_string());
148 
149  if(sig_info[1] == "EMSA4")
150  {
151  return OIDS::lookup(decode_pss_params(signature_algorithm().get_parameters()).hash_algo.get_oid());
152  }
153  else
154  {
155  const std::vector<std::string> pad_and_hash =
156  parse_algorithm_name(sig_info[1]);
157 
158  if(pad_and_hash.size() != 2)
159  {
160  throw Internal_Error("Invalid name format " + sig_info[1]);
161  }
162 
163  return pad_and_hash[1];
164  }
165  }
166 
167 /*
168 * Check the signature on an object
169 */
170 bool X509_Object::check_signature(const Public_Key* pub_key) const
171  {
172  if(!pub_key)
173  throw Exception("No key provided for " + PEM_label() + " signature check");
174  std::unique_ptr<const Public_Key> key(pub_key);
175  return check_signature(*key);
176  }
177 
178 bool X509_Object::check_signature(const Public_Key& pub_key) const
179  {
180  const Certificate_Status_Code code = verify_signature(pub_key);
181  return (code == Certificate_Status_Code::VERIFIED);
182  }
183 
185  {
186  const std::vector<std::string> sig_info =
187  split_on(OIDS::lookup(m_sig_algo.get_oid()), '/');
188 
189  if(sig_info.size() < 1 || sig_info.size() > 2 || sig_info[0] != pub_key.algo_name())
191 
192  std::string padding;
193  if(sig_info.size() == 2)
194  padding = sig_info[1];
195  else if(sig_info[0] == "Ed25519")
196  padding = "Pure";
197  else
199 
200  const Signature_Format format =
201  (pub_key.message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363;
202 
203  if(padding == "EMSA4")
204  {
205  // "MUST contain RSASSA-PSS-params"
206  if(signature_algorithm().parameters.empty())
207  {
209  }
210 
211  Pss_params pss_parameter = decode_pss_params(signature_algorithm().parameters);
212 
213  // hash_algo must be SHA1, SHA2-224, SHA2-256, SHA2-384 or SHA2-512
214  const std::string hash_algo = OIDS::lookup(pss_parameter.hash_algo.oid);
215  if(hash_algo != "SHA-160" &&
216  hash_algo != "SHA-224" &&
217  hash_algo != "SHA-256" &&
218  hash_algo != "SHA-384" &&
219  hash_algo != "SHA-512")
220  {
222  }
223 
224  const std::string mgf_algo = OIDS::lookup(pss_parameter.mask_gen_algo.oid);
225  if(mgf_algo != "MGF1")
226  {
228  }
229 
230  // For MGF1, it is strongly RECOMMENDED that the underlying hash function be the same as the one identified by hashAlgorithm
231  // Must be SHA1, SHA2-224, SHA2-256, SHA2-384 or SHA2-512
232  if(pss_parameter.mask_gen_hash.oid != pss_parameter.hash_algo.oid)
233  {
235  }
236 
237  if(pss_parameter.trailer_field != 1)
238  {
240  }
241 
242  // salt_len is actually not used for verification. Length is inferred from the signature
243  padding += "(" + hash_algo + "," + mgf_algo + "," + std::to_string(pss_parameter.salt_len) + ")";
244  }
245 
246  try
247  {
248  PK_Verifier verifier(pub_key, padding, format);
249  const bool valid = verifier.verify_message(tbs_data(), signature());
250 
251  if(valid)
253  else
255  }
256  catch(Algorithm_Not_Found&)
257  {
259  }
260  catch(...)
261  {
262  // This shouldn't happen, fallback to generic signature error
264  }
265  }
266 
267 /*
268 * Apply the X.509 SIGNED macro
269 */
270 std::vector<uint8_t> X509_Object::make_signed(PK_Signer* signer,
272  const AlgorithmIdentifier& algo,
273  const secure_vector<uint8_t>& tbs_bits)
274  {
275  const std::vector<uint8_t> signature = signer->sign_message(tbs_bits, rng);
276 
277  std::vector<uint8_t> output;
278  DER_Encoder(output)
280  .raw_bytes(tbs_bits)
281  .encode(algo)
283  .end_cons();
284 
285  return output;
286  }
287 
288 namespace {
289 
290 std::string choose_sig_algo(AlgorithmIdentifier& sig_algo,
291  const Private_Key& key,
292  const std::string& hash_fn,
293  const std::string& user_specified)
294  {
295  const std::string algo_name = key.algo_name();
296  std::string padding;
297 
298  // check algo_name and set default
299  if(algo_name == "RSA")
300  {
301  // set to EMSA3 for compatibility reasons, originally it was the only option
302  padding = "EMSA3(" + hash_fn + ")";
303  }
304  else if(algo_name == "DSA" ||
305  algo_name == "ECDSA" ||
306  algo_name == "ECGDSA" ||
307  algo_name == "ECKCDSA" ||
308  algo_name == "GOST-34.10")
309  {
310  padding = "EMSA1(" + hash_fn + ")";
311  }
312  else if(algo_name == "Ed25519")
313  {
314  padding = "Pure";
315  }
316  else
317  {
318  throw Invalid_Argument("Unknown X.509 signing key type: " + algo_name);
319  }
320 
321  if(user_specified.empty() == false)
322  {
323  padding = user_specified;
324  }
325 
326  if(padding != "Pure")
327  {
328  // try to construct an EMSA object from the padding options or default
329  std::unique_ptr<EMSA> emsa;
330  try
331  {
332  emsa.reset(get_emsa(padding));
333  }
334  /*
335  * get_emsa will throw if opts contains {"padding",<valid_padding>} but
336  * <valid_padding> does not specify a hash function.
337  * Omitting it is valid since it needs to be identical to hash_fn.
338  * If it still throws, something happened that we cannot repair here,
339  * e.g. the algorithm/padding combination is not supported.
340  */
341  catch(...)
342  {
343  emsa.reset(get_emsa(padding + "(" + hash_fn + ")"));
344  }
345 
346  if(!emsa)
347  {
348  throw Invalid_Argument("Could not parse padding scheme " + padding);
349  }
350 
351  sig_algo = emsa->config_for_x509(key, hash_fn);
352  return emsa->name();
353  }
354  else
355  {
356  sig_algo = AlgorithmIdentifier(OIDS::lookup("Ed25519"), AlgorithmIdentifier::USE_EMPTY_PARAM);
357  return "Pure";
358  }
359  }
360 
361 }
362 
363 /*
364 * Choose a signing format for the key
365 */
366 std::unique_ptr<PK_Signer> X509_Object::choose_sig_format(AlgorithmIdentifier& sig_algo,
367  const Private_Key& key,
369  const std::string& hash_fn,
370  const std::string& padding_algo)
371  {
372  const Signature_Format format = (key.message_parts() > 1) ? DER_SEQUENCE : IEEE_1363;
373 
374  const std::string emsa = choose_sig_algo(sig_algo, key, hash_fn, padding_algo);
375 
376  return std::unique_ptr<PK_Signer>(new PK_Signer(key, rng, emsa, format));
377  }
378 
379 }
Certificate_Status_Code verify_signature(const Public_Key &key) const
Definition: x509_obj.cpp:184
const AlgorithmIdentifier & signature_algorithm() const
Definition: x509_obj.h:48
bool verify_message(const uint8_t msg[], size_t msg_length, const uint8_t sig[], size_t sig_length)
Definition: pubkey.cpp:293
std::vector< uint8_t > parameters
Definition: alg_id.h:46
std::vector< std::string > split_on(const std::string &str, char delim)
Definition: parsing.cpp:144
void encode_into(class DER_Encoder &to) const override
Definition: x509_obj.cpp:93
std::string as_string() const
Definition: asn1_oid.h:48
virtual std::vector< std::string > alternate_PEM_labels() const
Definition: x509_obj.h:114
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:270
AlgorithmIdentifier mask_gen_hash
Definition: x509_obj.cpp:25
Signature_Format
Definition: pubkey.h:27
virtual std::string PEM_label() const =0
std::vector< uint8_t > BER_encode() const
Definition: asn1_obj.cpp:16
AlgorithmIdentifier mask_gen_algo
Definition: x509_obj.cpp:24
virtual std::string algo_name() const =0
bool maybe_BER(DataSource &source)
Definition: asn1_obj.cpp:219
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:210
ASN1_Tag
Definition: asn1_obj.h:22
BER_Decoder & raw_bytes(std::vector< uint8_t, Alloc > &out)
Definition: ber_dec.h:156
DER_Encoder & end_cons()
Definition: der_enc.cpp:191
bool check_signature(const Public_Key &key) const
Definition: x509_obj.cpp:178
BER_Decoder & decode(bool &out)
Definition: ber_dec.h:170
std::vector< uint8_t > sign_message(const uint8_t in[], size_t length, RandomNumberGenerator &rng)
Definition: pubkey.h:207
DER_Encoder & raw_bytes(const uint8_t val[], size_t len)
Definition: der_enc.cpp:228
void decode_from(class BER_Decoder &from) override
Definition: x509_obj.cpp:107
DER_Encoder & encode(bool b)
Definition: der_enc.cpp:285
static std::unique_ptr< PK_Signer > choose_sig_format(AlgorithmIdentifier &sig_algo, const Private_Key &key, RandomNumberGenerator &rng, const std::string &hash_fn, const std::string &padding_algo)
Definition: x509_obj.cpp:366
std::string encode(const uint8_t der[], size_t length, const std::string &label, size_t width)
Definition: pem.cpp:43
const std::vector< uint8_t > & signature() const
Definition: x509_obj.h:38
BER_Decoder & end_cons()
Definition: ber_dec.cpp:300
bool matches(DataSource &source, const std::string &extra, size_t search_range)
Definition: pem.cpp:142
std::vector< uint8_t > tbs_data() const
Definition: x509_obj.cpp:131
const char * what() const BOTAN_NOEXCEPT override
Definition: exceptn.h:25
const std::vector< uint8_t > & signed_body() const
Definition: x509_obj.h:43
secure_vector< uint8_t > decode(DataSource &source, std::string &label)
Definition: pem.cpp:68
size_t salt_len
Definition: x509_obj.cpp:26
void load_data(DataSource &src)
Definition: x509_obj.cpp:53
BER_Decoder start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Definition: ber_dec.cpp:290
std::vector< std::string > parse_algorithm_name(const std::string &namex)
Definition: parsing.cpp:91
Definition: alg_id.cpp:13
AlgorithmIdentifier hash_algo
Definition: x509_obj.cpp:23
std::vector< uint8_t > put_in_sequence(const std::vector< uint8_t > &contents)
Definition: asn1_obj.cpp:192
size_t trailer_field
Definition: x509_obj.cpp:27
std::string hash_used_for_signature() const
Definition: x509_obj.cpp:139
const OID & get_oid() const
Definition: alg_id.h:37
DER_Encoder & start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Definition: der_enc.cpp:181
EMSA * get_emsa(const std::string &algo_spec)
Definition: emsa.cpp:44
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:88
Certificate_Status_Code
Definition: cert_status.h:18
std::string lookup(const OID &oid)
Definition: oids.cpp:113
std::string PEM_encode() const
Definition: x509_obj.cpp:123
virtual size_t message_parts() const
Definition: pk_keys.h:107