Coverage Report

Created: 2020-11-21 08:34

/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
70
   {
31
70
   const AlgorithmIdentifier default_hash("SHA-160", AlgorithmIdentifier::USE_NULL_PARAM);
32
70
   const AlgorithmIdentifier default_mgf("MGF1", default_hash.BER_encode());
33
34
70
   Pss_params pss_parameter;
35
70
   BER_Decoder(encoded_pss_params)
36
70
      .start_cons(SEQUENCE)
37
70
         .decode_optional(pss_parameter.hash_algo, ASN1_Tag(0), PRIVATE, default_hash)
38
70
         .decode_optional(pss_parameter.mask_gen_algo, ASN1_Tag(1), PRIVATE, default_mgf)
39
70
         .decode_optional(pss_parameter.salt_len, ASN1_Tag(2), PRIVATE, size_t(20))
40
70
         .decode_optional(pss_parameter.trailer_field, ASN1_Tag(3), PRIVATE, size_t(1))
41
70
      .end_cons();
42
43
70
   BER_Decoder(pss_parameter.mask_gen_algo.get_parameters()).decode(pss_parameter.mask_gen_hash);
44
45
70
   return pss_parameter;
46
70
   }
47
}
48
49
/*
50
* Read a PEM or BER X.509 object
51
*/
52
void X509_Object::load_data(DataSource& in)
53
19.9k
   {
54
19.9k
   try {
55
19.9k
      if(ASN1::maybe_BER(in) && !PEM_Code::matches(in))
56
13.5k
         {
57
13.5k
         BER_Decoder dec(in);
58
13.5k
         decode_from(dec);
59
13.5k
         }
60
6.37k
      else
61
6.37k
         {
62
6.37k
         std::string got_label;
63
6.37k
         DataSource_Memory ber(PEM_Code::decode(in, got_label));
64
65
6.37k
         if(got_label != PEM_label())
66
180
            {
67
180
            bool is_alternate = false;
68
180
            for(std::string alt_label : alternate_PEM_labels())
69
180
               {
70
180
               if(got_label == alt_label)
71
4
                  {
72
4
                  is_alternate = true;
73
4
                  break;
74
4
                  }
75
180
               }
76
77
180
            if(!is_alternate)
78
176
               throw Decoding_Error("Unexpected PEM label for " + PEM_label() + " of " + got_label);
79
6.19k
            }
80
81
6.19k
         BER_Decoder dec(ber);
82
6.19k
         decode_from(dec);
83
6.19k
         }
84
19.9k
      }
85
19.9k
   catch(Decoding_Error& e)
86
7.03k
      {
87
7.03k
      throw Decoding_Error(PEM_label() + " decoding", e);
88
7.03k
      }
89
19.9k
   }
90
91
92
void X509_Object::encode_into(DER_Encoder& to) const
93
11.6k
   {
94
11.6k
   to.start_cons(SEQUENCE)
95
11.6k
         .start_cons(SEQUENCE)
96
11.6k
            .raw_bytes(signed_body())
97
11.6k
         .end_cons()
98
11.6k
         .encode(signature_algorithm())
99
11.6k
         .encode(signature(), BIT_STRING)
100
11.6k
      .end_cons();
101
11.6k
   }
102
103
/*
104
* Read a BER encoded X.509 object
105
*/
106
void X509_Object::decode_from(BER_Decoder& from)
107
18.9k
   {
108
18.9k
   from.start_cons(SEQUENCE)
109
18.9k
         .start_cons(SEQUENCE)
110
18.9k
            .raw_bytes(m_tbs_bits)
111
18.9k
         .end_cons()
112
18.9k
         .decode(m_sig_algo)
113
18.9k
         .decode(m_sig, BIT_STRING)
114
18.9k
      .end_cons();
115
116
18.9k
   force_decode();
117
18.9k
   }
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.29k
   {
132
7.29k
   return ASN1::put_in_sequence(m_tbs_bits);
133
7.29k
   }
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.35k
   {
186
7.35k
   const std::vector<std::string> sig_info =
187
7.35k
      split_on(m_sig_algo.get_oid().to_formatted_string(), '/');
188
189
7.35k
   if(sig_info.size() < 1 || sig_info.size() > 2 || sig_info[0] != pub_key.algo_name())
190
40
      return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS;
191
192
7.31k
   const std::string pub_key_algo = sig_info[0];
193
7.31k
   std::string padding;
194
7.31k
   if(sig_info.size() == 2)
195
7.23k
      padding = sig_info[1];
196
81
   else if(pub_key_algo == "Ed25519" || pub_key_algo == "XMSS")
197
78
      padding = "Pure";
198
3
   else
199
3
      return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS;
200
201
7.31k
   const Signature_Format format = pub_key.default_x509_signature_format();
202
203
7.31k
   if(padding == "EMSA4")
204
70
      {
205
      // "MUST contain RSASSA-PSS-params"
206
70
      if(signature_algorithm().get_parameters().empty())
207
0
         {
208
0
         return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS;
209
0
         }
210
211
70
      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
70
      const std::string hash_algo = pss_parameter.hash_algo.get_oid().to_formatted_string();
215
70
      if(hash_algo != "SHA-160" &&
216
61
         hash_algo != "SHA-224" &&
217
61
         hash_algo != "SHA-256" &&
218
3
         hash_algo != "SHA-384" &&
219
2
         hash_algo != "SHA-512")
220
1
         {
221
1
         return Certificate_Status_Code::UNTRUSTED_HASH;
222
1
         }
223
224
69
      const std::string mgf_algo = pss_parameter.mask_gen_algo.get_oid().to_formatted_string();
225
69
      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
68
      if(pss_parameter.mask_gen_hash.get_oid() != pss_parameter.hash_algo.get_oid())
233
3
         {
234
3
         return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS;
235
3
         }
236
237
65
      if(pss_parameter.trailer_field != 1)
238
0
         {
239
0
         return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS;
240
0
         }
241
242
65
      padding += "(" + hash_algo + "," + mgf_algo + "," + std::to_string(pss_parameter.salt_len) + ")";
243
65
      }
244
7.24k
   else
245
7.24k
      {
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.24k
      if(pub_key_algo == "Ed25519" || pub_key_algo == "XMSS")
264
78
         {
265
78
         if(!signature_algorithm().parameters_are_empty())
266
0
            {
267
0
            return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS;
268
0
            }
269
7.16k
         }
270
7.16k
      else
271
7.16k
         {
272
7.16k
         if(!signature_algorithm().parameters_are_null_or_empty())
273
8
            {
274
8
            return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS;
275
8
            }
276
7.29k
         }
277
7.24k
      }
278
279
7.29k
   try
280
7.29k
      {
281
7.29k
      PK_Verifier verifier(pub_key, padding, format);
282
7.29k
      const bool valid = verifier.verify_message(tbs_data(), signature());
283
284
7.29k
      if(valid)
285
5.33k
         return Certificate_Status_Code::VERIFIED;
286
1.96k
      else
287
1.96k
         return Certificate_Status_Code::SIGNATURE_ERROR;
288
1
      }
289
1
   catch(Algorithm_Not_Found&)
290
1
      {
291
1
      return Certificate_Status_Code::SIGNATURE_ALGO_UNKNOWN;
292
1
      }
293
15
   catch(...)
294
15
      {
295
      // This shouldn't happen, fallback to generic signature error
296
15
      return Certificate_Status_Code::SIGNATURE_ERROR;
297
15
      }
298
7.29k
   }
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_cons(SEQUENCE)
313
0
         .raw_bytes(tbs_bits)
314
0
         .encode(algo)
315
0
         .encode(signature, BIT_STRING)
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
}