~ubuntu-branches/debian/sid/botan/sid

« back to all changes in this revision

Viewing changes to src/lib/x509/x509_obj.cpp

  • Committer: Package Import Robot
  • Author(s): Laszlo Boszormenyi (GCS)
  • Date: 2018-03-01 22:23:25 UTC
  • mfrom: (1.2.2)
  • Revision ID: package-import@ubuntu.com-20180301222325-7p7vc45gu3hta34d
Tags: 2.4.0-2
* Don't remove .doctrees from the manual if it doesn't exist.
* Don't specify parallel to debhelper.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 <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
   Pss_params pss_parameter;
 
32
   BER_Decoder(encoded_pss_params)
 
33
      .start_cons(SEQUENCE)
 
34
         .decode_optional(pss_parameter.hash_algo, ASN1_Tag(0), PRIVATE, AlgorithmIdentifier("SHA-160",
 
35
                    AlgorithmIdentifier::USE_NULL_PARAM))
 
36
         .decode_optional(pss_parameter.mask_gen_algo, ASN1_Tag(1), PRIVATE,
 
37
                    AlgorithmIdentifier("MGF1", DER_Encoder().encode(AlgorithmIdentifier("SHA-160",
 
38
                                        AlgorithmIdentifier::USE_NULL_PARAM)).get_contents_unlocked()))
 
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
*/
 
52
void X509_Object::load_data(DataSource& in)
 
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 failed: " + e.what());
 
88
      }
 
89
   }
 
90
 
 
91
 
 
92
void X509_Object::encode_into(DER_Encoder& to) const
 
93
   {
 
94
   to.start_cons(SEQUENCE)
 
95
         .start_cons(SEQUENCE)
 
96
            .raw_bytes(signed_body())
 
97
         .end_cons()
 
98
         .encode(signature_algorithm())
 
99
         .encode(signature(), BIT_STRING)
 
100
      .end_cons();
 
101
   }
 
102
 
 
103
/*
 
104
* Read a BER encoded X.509 object
 
105
*/
 
106
void X509_Object::decode_from(BER_Decoder& from)
 
107
   {
 
108
   from.start_cons(SEQUENCE)
 
109
         .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 BER encoded X.509 object
 
121
*/
 
122
std::vector<uint8_t> X509_Object::BER_encode() const
 
123
   {
 
124
   DER_Encoder der;
 
125
   encode_into(der);
 
126
   return der.get_contents_unlocked();
 
127
   }
 
128
 
 
129
/*
 
130
* Return a PEM encoded X.509 object
 
131
*/
 
132
std::string X509_Object::PEM_encode() const
 
133
   {
 
134
   return PEM_Code::encode(BER_encode(), PEM_label());
 
135
   }
 
136
 
 
137
/*
 
138
* Return the TBS data
 
139
*/
 
140
std::vector<uint8_t> X509_Object::tbs_data() const
 
141
   {
 
142
   return ASN1::put_in_sequence(m_tbs_bits);
 
143
   }
 
144
 
 
145
/*
 
146
* Return the hash used in generating the signature
 
147
*/
 
148
std::string X509_Object::hash_used_for_signature() const
 
149
   {
 
150
   const OID& oid = m_sig_algo.get_oid();
 
151
   std::vector<std::string> sig_info = split_on(OIDS::lookup(oid), '/');
 
152
 
 
153
   if(sig_info.size() != 2)
 
154
      throw Internal_Error("Invalid name format found for " +
 
155
                           oid.as_string());
 
156
 
 
157
   if(sig_info[1] == "EMSA4")
 
158
      {
 
159
      return OIDS::lookup(decode_pss_params(signature_algorithm().get_parameters()).hash_algo.get_oid());
 
160
      }
 
161
   else
 
162
      {
 
163
      std::vector<std::string> pad_and_hash =
 
164
         parse_algorithm_name(sig_info[1]);
 
165
 
 
166
      if(pad_and_hash.size() != 2)
 
167
         {
 
168
         throw Internal_Error("Invalid name format " + sig_info[1]);
 
169
         }
 
170
 
 
171
      return pad_and_hash[1];
 
172
      }
 
173
   }
 
174
 
 
175
/*
 
176
* Check the signature on an object
 
177
*/
 
178
bool X509_Object::check_signature(const Public_Key* pub_key) const
 
179
   {
 
180
   if(!pub_key)
 
181
      throw Exception("No key provided for " + PEM_label() + " signature check");
 
182
   std::unique_ptr<const Public_Key> key(pub_key);
 
183
   return check_signature(*key);
 
184
   }
 
185
 
 
186
bool X509_Object::check_signature(const Public_Key& pub_key) const
 
187
   {
 
188
   const Certificate_Status_Code code = verify_signature(pub_key);
 
189
   return (code == Certificate_Status_Code::VERIFIED);
 
190
   }
 
191
 
 
192
Certificate_Status_Code X509_Object::verify_signature(const Public_Key& pub_key) const
 
193
   {
 
194
   const std::vector<std::string> sig_info =
 
195
      split_on(OIDS::lookup(m_sig_algo.get_oid()), '/');
 
196
 
 
197
   if(sig_info.size() != 2 || sig_info[0] != pub_key.algo_name())
 
198
      return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS;
 
199
 
 
200
   std::string padding = sig_info[1];
 
201
   const Signature_Format format =
 
202
      (pub_key.message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363;
 
203
 
 
204
   if(padding == "EMSA4")
 
205
      {
 
206
      // "MUST contain RSASSA-PSS-params"
 
207
      if(signature_algorithm().parameters.empty())
 
208
         {
 
209
         return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS;
 
210
         }
 
211
 
 
212
      Pss_params pss_parameter = decode_pss_params(signature_algorithm().parameters);
 
213
 
 
214
      // hash_algo must be SHA1, SHA2-224, SHA2-256, SHA2-384 or SHA2-512
 
215
      const std::string hash_algo = OIDS::lookup(pss_parameter.hash_algo.oid);
 
216
      if(hash_algo != "SHA-160" &&
 
217
         hash_algo != "SHA-224" &&
 
218
         hash_algo != "SHA-256" &&
 
219
         hash_algo != "SHA-384" &&
 
220
         hash_algo != "SHA-512")
 
221
         {
 
222
         return Certificate_Status_Code::UNTRUSTED_HASH;
 
223
         }
 
224
 
 
225
      const std::string mgf_algo = OIDS::lookup(pss_parameter.mask_gen_algo.oid);
 
226
      if(mgf_algo != "MGF1")
 
227
         {
 
228
         return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS;
 
229
         }
 
230
 
 
231
      // For MGF1, it is strongly RECOMMENDED that the underlying hash function be the same as the one identified by hashAlgorithm
 
232
      // Must be SHA1, SHA2-224, SHA2-256, SHA2-384 or SHA2-512
 
233
      if(pss_parameter.mask_gen_hash.oid != pss_parameter.hash_algo.oid)
 
234
         {
 
235
         return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS;
 
236
         }
 
237
 
 
238
      if(pss_parameter.trailer_field != 1)
 
239
         {
 
240
         return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS;
 
241
         }
 
242
 
 
243
      // salt_len is actually not used for verification. Length is inferred from the signature
 
244
      padding += "(" + hash_algo + "," + mgf_algo + "," + std::to_string(pss_parameter.salt_len) + ")";
 
245
      }
 
246
 
 
247
   try
 
248
      {
 
249
      PK_Verifier verifier(pub_key, padding, format);
 
250
      const bool valid = verifier.verify_message(tbs_data(), signature());
 
251
 
 
252
      if(valid)
 
253
         return Certificate_Status_Code::VERIFIED;
 
254
      else
 
255
         return Certificate_Status_Code::SIGNATURE_ERROR;
 
256
      }
 
257
   catch(Algorithm_Not_Found&)
 
258
      {
 
259
      return Certificate_Status_Code::SIGNATURE_ALGO_UNKNOWN;
 
260
      }
 
261
   catch(...)
 
262
      {
 
263
      // This shouldn't happen, fallback to generic signature error
 
264
      return Certificate_Status_Code::SIGNATURE_ERROR;
 
265
      }
 
266
   }
 
267
 
 
268
/*
 
269
* Apply the X.509 SIGNED macro
 
270
*/
 
271
std::vector<uint8_t> X509_Object::make_signed(PK_Signer* signer,
 
272
                                            RandomNumberGenerator& rng,
 
273
                                            const AlgorithmIdentifier& algo,
 
274
                                            const secure_vector<uint8_t>& tbs_bits)
 
275
   {
 
276
   const std::vector<uint8_t> signature = signer->sign_message(tbs_bits, rng);
 
277
 
 
278
   return DER_Encoder()
 
279
      .start_cons(SEQUENCE)
 
280
         .raw_bytes(tbs_bits)
 
281
         .encode(algo)
 
282
         .encode(signature, BIT_STRING)
 
283
      .end_cons()
 
284
   .get_contents_unlocked();
 
285
   }
 
286
 
 
287
}