Coverage Report

Created: 2021-02-21 07:20

/src/botan/src/lib/x509/x509_obj.cpp
Line
Count
Source (jump to first uncovered line)
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/internal/parsing.h>
13
#include <botan/pem.h>
14
#include <botan/internal/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
75
   {
31
75
   const AlgorithmIdentifier default_hash("SHA-160", AlgorithmIdentifier::USE_NULL_PARAM);
32
75
   const AlgorithmIdentifier default_mgf("MGF1", default_hash.BER_encode());
33
34
75
   Pss_params pss_parameter;
35
75
   BER_Decoder(encoded_pss_params)
36
75
      .start_sequence()
37
75
         .decode_optional(pss_parameter.hash_algo, ASN1_Type(0), ASN1_Class::ExplicitContextSpecific, default_hash)
38
75
         .decode_optional(pss_parameter.mask_gen_algo, ASN1_Type(1), ASN1_Class::ExplicitContextSpecific, default_mgf)
39
75
         .decode_optional(pss_parameter.salt_len, ASN1_Type(2), ASN1_Class::ExplicitContextSpecific, size_t(20))
40
75
         .decode_optional(pss_parameter.trailer_field, ASN1_Type(3), ASN1_Class::ExplicitContextSpecific, size_t(1))
41
75
      .end_cons();
42
43
75
   BER_Decoder(pss_parameter.mask_gen_algo.get_parameters()).decode(pss_parameter.mask_gen_hash);
44
45
75
   return pss_parameter;
46
75
   }
47
}
48
49
/*
50
* Read a PEM or BER X.509 object
51
*/
52
void X509_Object::load_data(DataSource& in)
53
20.2k
   {
54
20.2k
   try {
55
20.2k
      if(ASN1::maybe_BER(in) && !PEM_Code::matches(in))
56
13.9k
         {
57
13.9k
         BER_Decoder dec(in);
58
13.9k
         decode_from(dec);
59
13.9k
         }
60
6.29k
      else
61
6.29k
         {
62
6.29k
         std::string got_label;
63
6.29k
         DataSource_Memory ber(PEM_Code::decode(in, got_label));
64
65
6.29k
         if(got_label != PEM_label())
66
165
            {
67
165
            bool is_alternate = false;
68
165
            for(std::string alt_label : alternate_PEM_labels())
69
165
               {
70
165
               if(got_label == alt_label)
71
1
                  {
72
1
                  is_alternate = true;
73
1
                  break;
74
1
                  }
75
165
               }
76
77
165
            if(!is_alternate)
78
164
               throw Decoding_Error("Unexpected PEM label for " + PEM_label() + " of " + got_label);
79
6.13k
            }
80
81
6.13k
         BER_Decoder dec(ber);
82
6.13k
         decode_from(dec);
83
6.13k
         }
84
20.2k
      }
85
20.2k
   catch(Decoding_Error& e)
86
7.38k
      {
87
7.38k
      throw Decoding_Error(PEM_label() + " decoding", e);
88
7.38k
      }
89
20.2k
   }
90
91
92
void X509_Object::encode_into(DER_Encoder& to) const
93
11.7k
   {
94
11.7k
   to.start_sequence()
95
11.7k
         .start_sequence()
96
11.7k
            .raw_bytes(signed_body())
97
11.7k
         .end_cons()
98
11.7k
         .encode(signature_algorithm())
99
11.7k
         .encode(signature(), ASN1_Type::BitString)
100
11.7k
      .end_cons();
101
11.7k
   }
102
103
/*
104
* Read a BER encoded X.509 object
105
*/
106
void X509_Object::decode_from(BER_Decoder& from)
107
19.3k
   {
108
19.3k
   from.start_sequence()
109
19.3k
         .start_sequence()
110
19.3k
            .raw_bytes(m_tbs_bits)
111
19.3k
         .end_cons()
112
19.3k
         .decode(m_sig_algo)
113
19.3k
         .decode(m_sig, ASN1_Type::BitString)
114
19.3k
      .end_cons();
115
116
19.3k
   force_decode();
117
19.3k
   }
118
119
/*
120
* Return a PEM encoded X.509 object
121
*/
122
std::string X509_Object::PEM_encode() const
123
0
   {
124
0
   return PEM_Code::encode(BER_encode(), PEM_label());
125
0
   }
126
127
/*
128
* Return the TBS data
129
*/
130
std::vector<uint8_t> X509_Object::tbs_data() const
131
7.41k
   {
132
7.41k
   return ASN1::put_in_sequence(m_tbs_bits);
133
7.41k
   }
134
135
/*
136
* Return the hash used in generating the signature
137
*/
138
std::string X509_Object::hash_used_for_signature() const
139
0
   {
140
0
   const OID& oid = m_sig_algo.get_oid();
141
0
   const std::vector<std::string> sig_info = split_on(oid.to_formatted_string(), '/');
142
143
0
   if(sig_info.size() == 1 && sig_info[0] == "Ed25519")
144
0
      return "SHA-512";
145
0
   else if(sig_info.size() != 2)
146
0
      throw Internal_Error("Invalid name format found for " + oid.to_string());
147
148
0
   if(sig_info[1] == "EMSA4")
149
0
      {
150
0
      const OID hash_oid = decode_pss_params(signature_algorithm().get_parameters()).hash_algo.get_oid();
151
0
      return hash_oid.to_formatted_string();
152
0
      }
153
0
   else
154
0
      {
155
0
      const std::vector<std::string> pad_and_hash =
156
0
         parse_algorithm_name(sig_info[1]);
157
158
0
      if(pad_and_hash.size() != 2)
159
0
         {
160
0
         throw Internal_Error("Invalid name format " + sig_info[1]);
161
0
         }
162
163
0
      return pad_and_hash[1];
164
0
      }
165
0
   }
166
167
/*
168
* Check the signature on an object
169
*/
170
bool X509_Object::check_signature(const Public_Key* pub_key) const
171
0
   {
172
0
   if(!pub_key)
173
0
      throw Invalid_Argument("No key provided for " + PEM_label() + " signature check");
174
0
   std::unique_ptr<const Public_Key> key(pub_key);
175
0
   return check_signature(*key);
176
0
   }
177
178
bool X509_Object::check_signature(const Public_Key& pub_key) const
179
0
   {
180
0
   const Certificate_Status_Code code = verify_signature(pub_key);
181
0
   return (code == Certificate_Status_Code::VERIFIED);
182
0
   }
183
184
Certificate_Status_Code X509_Object::verify_signature(const Public_Key& pub_key) const
185
7.50k
   {
186
7.50k
   const std::vector<std::string> sig_info =
187
7.50k
      split_on(m_sig_algo.get_oid().to_formatted_string(), '/');
188
189
7.50k
   if(sig_info.size() < 1 || sig_info.size() > 2 || sig_info[0] != pub_key.algo_name())
190
71
      return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS;
191
192
7.43k
   const std::string pub_key_algo = sig_info[0];
193
7.43k
   std::string padding;
194
7.43k
   if(sig_info.size() == 2)
195
7.33k
      padding = sig_info[1];
196
97
   else if(pub_key_algo == "Ed25519" || pub_key_algo == "XMSS")
197
95
      padding = "Pure";
198
2
   else
199
2
      return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS;
200
201
7.43k
   const Signature_Format format = pub_key.default_x509_signature_format();
202
203
7.43k
   if(padding == "EMSA4")
204
75
      {
205
      // "MUST contain RSASSA-PSS-params"
206
75
      if(signature_algorithm().get_parameters().empty())
207
0
         {
208
0
         return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS;
209
0
         }
210
211
75
      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
75
      const std::string hash_algo = pss_parameter.hash_algo.get_oid().to_formatted_string();
215
75
      if(hash_algo != "SHA-160" &&
216
68
         hash_algo != "SHA-224" &&
217
68
         hash_algo != "SHA-256" &&
218
2
         hash_algo != "SHA-384" &&
219
1
         hash_algo != "SHA-512")
220
1
         {
221
1
         return Certificate_Status_Code::UNTRUSTED_HASH;
222
1
         }
223
224
74
      const std::string mgf_algo = pss_parameter.mask_gen_algo.get_oid().to_formatted_string();
225
74
      if(mgf_algo != "MGF1")
226
1
         {
227
1
         return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS;
228
1
         }
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
73
      if(pss_parameter.mask_gen_hash.get_oid() != pss_parameter.hash_algo.get_oid())
233
1
         {
234
1
         return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS;
235
1
         }
236
237
72
      if(pss_parameter.trailer_field != 1)
238
1
         {
239
1
         return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS;
240
1
         }
241
242
71
      padding += "(" + hash_algo + "," + mgf_algo + "," + std::to_string(pss_parameter.salt_len) + ")";
243
71
      }
244
7.35k
   else
245
7.35k
      {
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
7.35k
      if(pub_key_algo == "Ed25519" || pub_key_algo == "XMSS")
264
95
         {
265
95
         if(!signature_algorithm().parameters_are_empty())
266
0
            {
267
0
            return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS;
268
0
            }
269
7.26k
         }
270
7.26k
      else
271
7.26k
         {
272
7.26k
         if(!signature_algorithm().parameters_are_null_or_empty())
273
6
            {
274
6
            return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS;
275
6
            }
276
7.42k
         }
277
7.35k
      }
278
279
7.42k
   try
280
7.42k
      {
281
7.42k
      PK_Verifier verifier(pub_key, padding, format);
282
7.42k
      const bool valid = verifier.verify_message(tbs_data(), signature());
283
284
7.42k
      if(valid)
285
5.31k
         return Certificate_Status_Code::VERIFIED;
286
2.10k
      else
287
2.10k
         return Certificate_Status_Code::SIGNATURE_ERROR;
288
0
      }
289
0
   catch(Algorithm_Not_Found&)
290
0
      {
291
0
      return Certificate_Status_Code::SIGNATURE_ALGO_UNKNOWN;
292
0
      }
293
7
   catch(...)
294
7
      {
295
      // This shouldn't happen, fallback to generic signature error
296
7
      return Certificate_Status_Code::SIGNATURE_ERROR;
297
7
      }
298
7.42k
   }
299
300
/*
301
* Apply the X.509 SIGNED macro
302
*/
303
std::vector<uint8_t> X509_Object::make_signed(PK_Signer* signer,
304
                                            RandomNumberGenerator& rng,
305
                                            const AlgorithmIdentifier& algo,
306
                                            const secure_vector<uint8_t>& tbs_bits)
307
0
   {
308
0
   const std::vector<uint8_t> signature = signer->sign_message(tbs_bits, rng);
309
310
0
   std::vector<uint8_t> output;
311
0
   DER_Encoder(output)
312
0
      .start_sequence()
313
0
         .raw_bytes(tbs_bits)
314
0
         .encode(algo)
315
0
         .encode(signature, ASN1_Type::BitString)
316
0
      .end_cons();
317
318
0
   return output;
319
0
   }
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
0
   {
328
0
   const std::string algo_name = key.algo_name();
329
0
   std::string padding;
330
331
   // check algo_name and set default
332
0
   if(algo_name == "RSA")
333
0
      {
334
      // set to EMSA3 for compatibility reasons, originally it was the only option
335
0
      padding = "EMSA3(" + hash_fn + ")";
336
0
      }
337
0
   else if(algo_name == "DSA" ||
338
0
           algo_name == "ECDSA" ||
339
0
           algo_name == "ECGDSA" ||
340
0
           algo_name == "ECKCDSA" ||
341
0
           algo_name == "GOST-34.10" ||
342
0
           algo_name == "GOST-34.10-2012-256" ||
343
0
           algo_name == "GOST-34.10-2012-512")
344
0
      {
345
0
      padding = "EMSA1(" + hash_fn + ")";
346
0
      }
347
0
   else if(algo_name == "Ed25519")
348
0
      {
349
0
      padding = "Pure";
350
0
      }
351
0
   else if(algo_name == "XMSS")
352
0
      {
353
0
      if(user_specified.empty() == true)
354
0
         {
355
0
         throw Invalid_Argument("XMSS requires padding scheme");
356
0
         }
357
0
      padding = user_specified;
358
0
      sig_algo = AlgorithmIdentifier(OID::from_string("XMSS"), AlgorithmIdentifier::USE_EMPTY_PARAM);
359
0
      return padding;
360
0
      }
361
0
   else
362
0
      {
363
0
      throw Invalid_Argument("Unknown X.509 signing key type: " + algo_name);
364
0
      }
365
366
0
   if(user_specified.empty() == false)
367
0
      {
368
0
      padding = user_specified;
369
0
      }
370
371
0
   if(padding != "Pure")
372
0
      {
373
      // try to construct an EMSA object from the padding options or default
374
0
      std::unique_ptr<EMSA> emsa;
375
0
      try
376
0
         {
377
0
         emsa.reset(get_emsa(padding));
378
0
         }
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
0
      catch(...)
387
0
         {
388
0
         emsa.reset(get_emsa(padding + "(" + hash_fn + ")"));
389
0
         }
390
391
0
      if(!emsa)
392
0
         {
393
0
         throw Invalid_Argument("Could not parse padding scheme " + padding);
394
0
         }
395
396
0
      sig_algo = emsa->config_for_x509(key, hash_fn);
397
0
      return emsa->name();
398
0
      }
399
0
   else
400
0
      {
401
0
      sig_algo = AlgorithmIdentifier(OID::from_string("Ed25519"), AlgorithmIdentifier::USE_EMPTY_PARAM);
402
0
      return "Pure";
403
0
      }
404
0
   }
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,
413
                                                          RandomNumberGenerator& rng,
414
                                                          const std::string& hash_fn,
415
                                                          const std::string& padding_algo)
416
0
   {
417
0
   const Signature_Format format = key.default_x509_signature_format();
418
419
0
   const std::string emsa = choose_sig_algo(sig_algo, key, hash_fn, padding_algo);
420
421
0
   return std::unique_ptr<PK_Signer>(new PK_Signer(key, rng, emsa, format));
422
0
   }
423
424
}