Botan  2.18.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,2020 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/der_enc.h>
11 #include <botan/ber_dec.h>
12 #include <botan/parsing.h>
13 #include <botan/pem.h>
14 #include <botan/emsa.h>
15 #include <algorithm>
16 
17 namespace Botan {
18 
19 namespace {
20 struct Pss_params
21  {
22  AlgorithmIdentifier hash_algo;
23  AlgorithmIdentifier mask_gen_algo;
24  AlgorithmIdentifier mask_gen_hash; // redundant: decoded mask_gen_algo.parameters
25  size_t salt_len;
26  size_t trailer_field;
27  };
28 
29 Pss_params decode_pss_params(const std::vector<uint8_t>& encoded_pss_params)
30  {
31  const AlgorithmIdentifier default_hash("SHA-160", AlgorithmIdentifier::USE_NULL_PARAM);
32  const AlgorithmIdentifier default_mgf("MGF1", default_hash.BER_encode());
33 
34  Pss_params pss_parameter;
35  BER_Decoder(encoded_pss_params)
36  .start_cons(SEQUENCE)
37  .decode_optional(pss_parameter.hash_algo, ASN1_Tag(0), PRIVATE, default_hash)
38  .decode_optional(pss_parameter.mask_gen_algo, ASN1_Tag(1), PRIVATE, default_mgf)
39  .decode_optional(pss_parameter.salt_len, ASN1_Tag(2), PRIVATE, size_t(20))
40  .decode_optional(pss_parameter.trailer_field, ASN1_Tag(3), PRIVATE, size_t(1))
41  .end_cons();
42 
43  BER_Decoder(pss_parameter.mask_gen_algo.get_parameters()).decode(pss_parameter.mask_gen_hash);
44 
45  return pss_parameter;
46  }
47 }
48 
49 /*
50 * Read a PEM or BER X.509 object
51 */
53  {
54  try {
55  if(ASN1::maybe_BER(in) && !PEM_Code::matches(in))
56  {
57  BER_Decoder dec(in);
58  decode_from(dec);
59  }
60  else
61  {
62  std::string got_label;
63  DataSource_Memory ber(PEM_Code::decode(in, got_label));
64 
65  if(got_label != PEM_label())
66  {
67  bool is_alternate = false;
68  for(std::string alt_label : alternate_PEM_labels())
69  {
70  if(got_label == alt_label)
71  {
72  is_alternate = true;
73  break;
74  }
75  }
76 
77  if(!is_alternate)
78  throw Decoding_Error("Unexpected PEM label for " + PEM_label() + " of " + got_label);
79  }
80 
81  BER_Decoder dec(ber);
82  decode_from(dec);
83  }
84  }
85  catch(Decoding_Error& e)
86  {
87  throw Decoding_Error(PEM_label() + " decoding", e);
88  }
89  }
90 
91 
93  {
97  .end_cons()
100  .end_cons();
101  }
102 
103 /*
104 * Read a BER encoded X.509 object
105 */
107  {
108  from.start_cons(SEQUENCE)
110  .raw_bytes(m_tbs_bits)
111  .end_cons()
112  .decode(m_sig_algo)
113  .decode(m_sig, BIT_STRING)
114  .end_cons();
115 
116  force_decode();
117  }
118 
119 /*
120 * Return a PEM encoded X.509 object
121 */
122 std::string X509_Object::PEM_encode() const
123  {
125  }
126 
127 /*
128 * Return the TBS data
129 */
130 std::vector<uint8_t> X509_Object::tbs_data() const
131  {
132  return ASN1::put_in_sequence(m_tbs_bits);
133  }
134 
135 /*
136 * Return the hash used in generating the signature
137 */
139  {
140  const OID& oid = m_sig_algo.get_oid();
141  const std::vector<std::string> sig_info = split_on(oid.to_formatted_string(), '/');
142 
143  if(sig_info.size() == 1 && sig_info[0] == "Ed25519")
144  return "SHA-512";
145  else if(sig_info.size() != 2)
146  throw Internal_Error("Invalid name format found for " + oid.to_string());
147 
148  if(sig_info[1] == "EMSA4")
149  {
150  const OID hash_oid = decode_pss_params(signature_algorithm().get_parameters()).hash_algo.get_oid();
151  return hash_oid.to_formatted_string();
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 Invalid_Argument("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(m_sig_algo.get_oid().to_formatted_string(), '/');
188 
189  if(sig_info.size() < 1 || sig_info.size() > 2 || sig_info[0] != pub_key.algo_name())
191 
192  const std::string pub_key_algo = sig_info[0];
193  std::string padding;
194  if(sig_info.size() == 2)
195  padding = sig_info[1];
196  else if(pub_key_algo == "Ed25519" || pub_key_algo == "XMSS")
197  padding = "Pure";
198  else
200 
201  const Signature_Format format = pub_key.default_x509_signature_format();
202 
203  if(padding == "EMSA4")
204  {
205  // "MUST contain RSASSA-PSS-params"
206  if(signature_algorithm().get_parameters().empty())
207  {
209  }
210 
211  Pss_params pss_parameter = decode_pss_params(signature_algorithm().get_parameters());
212 
213  // hash_algo must be SHA1, SHA2-224, SHA2-256, SHA2-384 or SHA2-512
214  const std::string hash_algo = pss_parameter.hash_algo.get_oid().to_formatted_string();
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 = pss_parameter.mask_gen_algo.get_oid().to_formatted_string();
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.get_oid() != pss_parameter.hash_algo.get_oid())
233  {
235  }
236 
237  if(pss_parameter.trailer_field != 1)
238  {
240  }
241 
242  padding += "(" + hash_algo + "," + mgf_algo + "," + std::to_string(pss_parameter.salt_len) + ")";
243  }
244  else
245  {
246  /*
247  * For all other signature types the signature parameters should
248  * be either NULL or empty. In theory there is some distinction between
249  * these but in practice they seem to be used somewhat interchangeably.
250  *
251  * The various RFCs all have prescriptions of what is allowed:
252  * RSA - NULL (RFC 3279)
253  * DSA - empty (RFC 3279)
254  * ECDSA - empty (RFC 3279)
255  * GOST - empty (RFC 4491)
256  * Ed25519 - empty (RFC 8410)
257  * XMSS - empty (draft-vangeest-x509-hash-sigs)
258  *
259  * But in practice we find RSA with empty and ECDSA will NULL all
260  * over the place so it's not really possible to enforce. For Ed25519
261  * and XMSS because they are new we attempt to enforce.
262  */
263  if(pub_key_algo == "Ed25519" || pub_key_algo == "XMSS")
264  {
265  if(!signature_algorithm().parameters_are_empty())
266  {
268  }
269  }
270  else
271  {
272  if(!signature_algorithm().parameters_are_null_or_empty())
273  {
275  }
276  }
277  }
278 
279  try
280  {
281  PK_Verifier verifier(pub_key, padding, format);
282  const bool valid = verifier.verify_message(tbs_data(), signature());
283 
284  if(valid)
286  else
288  }
289  catch(Algorithm_Not_Found&)
290  {
292  }
293  catch(...)
294  {
295  // This shouldn't happen, fallback to generic signature error
297  }
298  }
299 
300 /*
301 * Apply the X.509 SIGNED macro
302 */
303 std::vector<uint8_t> X509_Object::make_signed(PK_Signer* signer,
305  const AlgorithmIdentifier& algo,
306  const secure_vector<uint8_t>& tbs_bits)
307  {
308  const std::vector<uint8_t> signature = signer->sign_message(tbs_bits, rng);
309 
310  std::vector<uint8_t> output;
311  DER_Encoder(output)
313  .raw_bytes(tbs_bits)
314  .encode(algo)
316  .end_cons();
317 
318  return output;
319  }
320 
321 namespace {
322 
323 std::string choose_sig_algo(AlgorithmIdentifier& sig_algo,
324  const Private_Key& key,
325  const std::string& hash_fn,
326  const std::string& user_specified)
327  {
328  const std::string algo_name = key.algo_name();
329  std::string padding;
330 
331  // check algo_name and set default
332  if(algo_name == "RSA")
333  {
334  // set to EMSA3 for compatibility reasons, originally it was the only option
335  padding = "EMSA3(" + hash_fn + ")";
336  }
337  else if(algo_name == "DSA" ||
338  algo_name == "ECDSA" ||
339  algo_name == "ECGDSA" ||
340  algo_name == "ECKCDSA" ||
341  algo_name == "GOST-34.10" ||
342  algo_name == "GOST-34.10-2012-256" ||
343  algo_name == "GOST-34.10-2012-512")
344  {
345  padding = "EMSA1(" + hash_fn + ")";
346  }
347  else if(algo_name == "Ed25519")
348  {
349  padding = "Pure";
350  }
351  else if(algo_name == "XMSS")
352  {
353  if(user_specified.empty() == true)
354  {
355  throw Invalid_Argument("XMSS requires padding scheme");
356  }
357  padding = user_specified;
358  sig_algo = AlgorithmIdentifier(OID::from_string("XMSS"), AlgorithmIdentifier::USE_EMPTY_PARAM);
359  return padding;
360  }
361  else
362  {
363  throw Invalid_Argument("Unknown X.509 signing key type: " + algo_name);
364  }
365 
366  if(user_specified.empty() == false)
367  {
368  padding = user_specified;
369  }
370 
371  if(padding != "Pure")
372  {
373  // try to construct an EMSA object from the padding options or default
374  std::unique_ptr<EMSA> emsa;
375  try
376  {
377  emsa.reset(get_emsa(padding));
378  }
379  /*
380  * get_emsa will throw if opts contains {"padding",<valid_padding>} but
381  * <valid_padding> does not specify a hash function.
382  * Omitting it is valid since it needs to be identical to hash_fn.
383  * If it still throws, something happened that we cannot repair here,
384  * e.g. the algorithm/padding combination is not supported.
385  */
386  catch(...)
387  {
388  emsa.reset(get_emsa(padding + "(" + hash_fn + ")"));
389  }
390 
391  if(!emsa)
392  {
393  throw Invalid_Argument("Could not parse padding scheme " + padding);
394  }
395 
396  sig_algo = emsa->config_for_x509(key, hash_fn);
397  return emsa->name();
398  }
399  else
400  {
401  sig_algo = AlgorithmIdentifier(OID::from_string("Ed25519"), AlgorithmIdentifier::USE_EMPTY_PARAM);
402  return "Pure";
403  }
404  }
405 
406 }
407 
408 /*
409 * Choose a signing format for the key
410 */
411 std::unique_ptr<PK_Signer> X509_Object::choose_sig_format(AlgorithmIdentifier& sig_algo,
412  const Private_Key& key,
414  const std::string& hash_fn,
415  const std::string& padding_algo)
416  {
417  const Signature_Format format = key.default_x509_signature_format();
418 
419  const std::string emsa = choose_sig_algo(sig_algo, key, hash_fn, padding_algo);
420 
421  return std::unique_ptr<PK_Signer>(new PK_Signer(key, rng, emsa, format));
422  }
423 
424 }
Certificate_Status_Code verify_signature(const Public_Key &key) const
Definition: x509_obj.cpp:184
const AlgorithmIdentifier & signature_algorithm() const
Definition: x509_obj.h:47
bool verify_message(const uint8_t msg[], size_t msg_length, const uint8_t sig[], size_t sig_length)
Definition: pubkey.cpp:331
std::vector< std::string > split_on(const std::string &str, char delim)
Definition: parsing.cpp:148
void encode_into(class DER_Encoder &to) const override
Definition: x509_obj.cpp:92
virtual std::vector< std::string > alternate_PEM_labels() const
Definition: x509_obj.h:113
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:303
AlgorithmIdentifier mask_gen_hash
Definition: x509_obj.cpp:24
Signature_Format
Definition: pk_keys.h:23
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:23
virtual std::string algo_name() const =0
bool maybe_BER(DataSource &source)
Definition: asn1_obj.cpp:222
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:213
ASN1_Tag
Definition: asn1_obj.h:25
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:214
DER_Encoder & raw_bytes(const uint8_t val[], size_t len)
Definition: der_enc.cpp:228
virtual Signature_Format default_x509_signature_format() const
Definition: pk_keys.h:125
void decode_from(class BER_Decoder &from) override
Definition: x509_obj.cpp:106
std::string to_string() const
Definition: asn1_oid.cpp:98
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:411
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:37
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:130
const std::vector< uint8_t > & signed_body() const
Definition: x509_obj.h:42
secure_vector< uint8_t > decode(DataSource &source, std::string &label)
Definition: pem.cpp:68
size_t salt_len
Definition: x509_obj.cpp:25
void load_data(DataSource &src)
Definition: x509_obj.cpp:52
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:95
Definition: alg_id.cpp:13
AlgorithmIdentifier hash_algo
Definition: x509_obj.cpp:22
std::vector< uint8_t > put_in_sequence(const std::vector< uint8_t > &contents)
Definition: asn1_obj.cpp:195
size_t trailer_field
Definition: x509_obj.cpp:26
std::string hash_used_for_signature() const
Definition: x509_obj.cpp:138
std::string to_formatted_string() const
Definition: asn1_oid.cpp:111
const OID & get_oid() const
Definition: asn1_obj.h:445
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:65
Certificate_Status_Code
Definition: pkix_enums.h:17
std::string PEM_encode() const
Definition: x509_obj.cpp:122
static OID from_string(const std::string &str)
Definition: asn1_oid.cpp:62