Botan  2.15.0
Crypto and TLS for C++11
pssr.cpp
Go to the documentation of this file.
1 /*
2 * PSSR
3 * (C) 1999-2007,2017 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/pssr.h>
9 #include <botan/exceptn.h>
10 #include <botan/rng.h>
11 #include <botan/mgf1.h>
12 #include <botan/internal/bit_ops.h>
13 #include <botan/der_enc.h>
14 #include <botan/pk_keys.h>
15 #include <botan/internal/padding.h>
16 
17 namespace Botan {
18 
19 namespace {
20 
21 /*
22 * PSSR Encode Operation
23 */
24 secure_vector<uint8_t> pss_encode(HashFunction& hash,
25  const secure_vector<uint8_t>& msg,
26  const secure_vector<uint8_t>& salt,
27  size_t output_bits)
28  {
29  const size_t HASH_SIZE = hash.output_length();
30  const size_t SALT_SIZE = salt.size();
31 
32  if(msg.size() != HASH_SIZE)
33  throw Encoding_Error("Cannot encode PSS string, input length invalid for hash");
34  if(output_bits < 8*HASH_SIZE + 8*SALT_SIZE + 9)
35  throw Encoding_Error("Cannot encode PSS string, output length too small");
36 
37  const size_t output_length = (output_bits + 7) / 8;
38 
39  for(size_t i = 0; i != 8; ++i)
40  hash.update(0);
41  hash.update(msg);
42  hash.update(salt);
43  secure_vector<uint8_t> H = hash.final();
44 
45  secure_vector<uint8_t> EM(output_length);
46 
47  EM[output_length - HASH_SIZE - SALT_SIZE - 2] = 0x01;
48  buffer_insert(EM, output_length - 1 - HASH_SIZE - SALT_SIZE, salt);
49  mgf1_mask(hash, H.data(), HASH_SIZE, EM.data(), output_length - HASH_SIZE - 1);
50  EM[0] &= 0xFF >> (8 * ((output_bits + 7) / 8) - output_bits);
51  buffer_insert(EM, output_length - 1 - HASH_SIZE, H);
52  EM[output_length-1] = 0xBC;
53  return EM;
54  }
55 
56 bool pss_verify(HashFunction& hash,
57  const secure_vector<uint8_t>& pss_repr,
58  const secure_vector<uint8_t>& message_hash,
59  size_t key_bits,
60  size_t* out_salt_size)
61  {
62  const size_t HASH_SIZE = hash.output_length();
63  const size_t KEY_BYTES = (key_bits + 7) / 8;
64 
65  if(key_bits < 8*HASH_SIZE + 9)
66  return false;
67 
68  if(message_hash.size() != HASH_SIZE)
69  return false;
70 
71  if(pss_repr.size() > KEY_BYTES || pss_repr.size() <= 1)
72  return false;
73 
74  if(pss_repr[pss_repr.size()-1] != 0xBC)
75  return false;
76 
77  secure_vector<uint8_t> coded = pss_repr;
78  if(coded.size() < KEY_BYTES)
79  {
80  secure_vector<uint8_t> temp(KEY_BYTES);
81  buffer_insert(temp, KEY_BYTES - coded.size(), coded);
82  coded = temp;
83  }
84 
85  const size_t TOP_BITS = 8 * ((key_bits + 7) / 8) - key_bits;
86  if(TOP_BITS > 8 - high_bit(coded[0]))
87  return false;
88 
89  uint8_t* DB = coded.data();
90  const size_t DB_size = coded.size() - HASH_SIZE - 1;
91 
92  const uint8_t* H = &coded[DB_size];
93  const size_t H_size = HASH_SIZE;
94 
95  mgf1_mask(hash, H, H_size, DB, DB_size);
96  DB[0] &= 0xFF >> TOP_BITS;
97 
98  size_t salt_offset = 0;
99  for(size_t j = 0; j != DB_size; ++j)
100  {
101  if(DB[j] == 0x01)
102  { salt_offset = j + 1; break; }
103  if(DB[j])
104  return false;
105  }
106  if(salt_offset == 0)
107  return false;
108 
109  const size_t salt_size = DB_size - salt_offset;
110 
111  for(size_t j = 0; j != 8; ++j)
112  hash.update(0);
113  hash.update(message_hash);
114  hash.update(&DB[salt_offset], salt_size);
115 
116  const secure_vector<uint8_t> H2 = hash.final();
117 
118  const bool ok = constant_time_compare(H, H2.data(), HASH_SIZE);
119 
120  if(out_salt_size && ok)
121  *out_salt_size = salt_size;
122 
123  return ok;
124  }
125 
126 }
127 
129  m_hash(h),
130  m_salt_size(m_hash->output_length()),
131  m_required_salt_len(false)
132  {
133  }
134 
136  m_hash(h),
137  m_salt_size(salt_size),
138  m_required_salt_len(true)
139  {
140  }
141 
142 /*
143 * PSSR Update Operation
144 */
145 void PSSR::update(const uint8_t input[], size_t length)
146  {
147  m_hash->update(input, length);
148  }
149 
150 /*
151 * Return the raw (unencoded) data
152 */
153 secure_vector<uint8_t> PSSR::raw_data()
154  {
155  return m_hash->final();
156  }
157 
158 secure_vector<uint8_t> PSSR::encoding_of(const secure_vector<uint8_t>& msg,
159  size_t output_bits,
160  RandomNumberGenerator& rng)
161  {
162  const secure_vector<uint8_t> salt = rng.random_vec(m_salt_size);
163  return pss_encode(*m_hash, msg, salt, output_bits);
164  }
165 
166 /*
167 * PSSR Decode/Verify Operation
168 */
169 bool PSSR::verify(const secure_vector<uint8_t>& coded,
170  const secure_vector<uint8_t>& raw,
171  size_t key_bits)
172  {
173  size_t salt_size = 0;
174  const bool ok = pss_verify(*m_hash, coded, raw, key_bits, &salt_size);
175 
176  if(m_required_salt_len && salt_size != m_salt_size)
177  return false;
178 
179  return ok;
180  }
181 
183  {
184  return new PSSR(m_hash->clone(), m_salt_size);
185  }
186 
187 std::string PSSR::name() const
188  {
189  return "EMSA4(" + m_hash->name() + ",MGF1," + std::to_string(m_salt_size) + ")";
190  }
191 
193  const std::string& cert_hash_name) const
194  {
195  if(cert_hash_name != m_hash->name())
196  throw Invalid_Argument("Hash function from opts and hash_fn argument"
197  " need to be identical");
198  // check that the signature algorithm and the padding scheme fit
199  if(!sig_algo_and_pad_ok(key.algo_name(), "EMSA4"))
200  {
201  throw Invalid_Argument("Encoding scheme with canonical name EMSA4"
202  " not supported for signature algorithm " + key.algo_name());
203  }
204 
205  const AlgorithmIdentifier hash_id(cert_hash_name, AlgorithmIdentifier::USE_NULL_PARAM);
206  const AlgorithmIdentifier mgf_id("MGF1", hash_id.BER_encode());
207 
208  std::vector<uint8_t> parameters;
209  DER_Encoder(parameters)
213  .start_cons(ASN1_Tag(2), CONTEXT_SPECIFIC).encode(m_salt_size).end_cons()
214  .start_cons(ASN1_Tag(3), CONTEXT_SPECIFIC).encode(size_t(1)).end_cons() // trailer field
215  .end_cons();
216 
217  // hardcoded as RSA is the only valid algorithm for EMSA4 at the moment
218  return AlgorithmIdentifier("RSA/EMSA4", parameters);
219  }
220 
222  m_hash(h),
223  m_salt_size(m_hash->output_length()),
224  m_required_salt_len(false)
225  {
226  }
227 
229  m_hash(h),
230  m_salt_size(salt_size),
231  m_required_salt_len(true)
232  {
233  }
234 
235 /*
236 * PSSR_Raw Update Operation
237 */
238 void PSSR_Raw::update(const uint8_t input[], size_t length)
239  {
240  m_msg.insert(m_msg.end(), input, input + length);
241  }
242 
243 /*
244 * Return the raw (unencoded) data
245 */
246 secure_vector<uint8_t> PSSR_Raw::raw_data()
247  {
248  secure_vector<uint8_t> ret;
249  std::swap(ret, m_msg);
250 
251  if(ret.size() != m_hash->output_length())
252  throw Encoding_Error("PSSR_Raw Bad input length, did not match hash");
253 
254  return ret;
255  }
256 
257 secure_vector<uint8_t> PSSR_Raw::encoding_of(const secure_vector<uint8_t>& msg,
258  size_t output_bits,
259  RandomNumberGenerator& rng)
260  {
261  secure_vector<uint8_t> salt = rng.random_vec(m_salt_size);
262  return pss_encode(*m_hash, msg, salt, output_bits);
263  }
264 
265 /*
266 * PSSR_Raw Decode/Verify Operation
267 */
268 bool PSSR_Raw::verify(const secure_vector<uint8_t>& coded,
269  const secure_vector<uint8_t>& raw,
270  size_t key_bits)
271  {
272  size_t salt_size = 0;
273  const bool ok = pss_verify(*m_hash, coded, raw, key_bits, &salt_size);
274 
275  if(m_required_salt_len && salt_size != m_salt_size)
276  return false;
277 
278  return ok;
279  }
280 
282  {
283  return new PSSR_Raw(m_hash->clone(), m_salt_size);
284  }
285 
286 std::string PSSR_Raw::name() const
287  {
288  return "PSSR_Raw(" + m_hash->name() + ",MGF1," + std::to_string(m_salt_size) + ")";
289  }
290 
291 }
std::string name() const override
Definition: pssr.cpp:286
std::vector< uint8_t > BER_encode() const
Definition: asn1_obj.cpp:16
bool constant_time_compare(const uint8_t x[], const uint8_t y[], size_t len)
Definition: mem_ops.h:82
virtual std::string algo_name() const =0
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:213
size_t salt_size
ASN1_Tag
Definition: asn1_obj.h:23
DER_Encoder & end_cons()
Definition: der_enc.cpp:191
std::string name() const override
Definition: pssr.cpp:187
bool sig_algo_and_pad_ok(const std::string algo, const std::string padding)
Definition: padding.cpp:39
EMSA * clone() override
Definition: pssr.cpp:182
DER_Encoder & encode(bool b)
Definition: der_enc.cpp:285
PSSR_Raw(HashFunction *hash)
Definition: pssr.cpp:221
size_t high_bit(T n)
Definition: bit_ops.h:55
Definition: alg_id.cpp:13
size_t buffer_insert(std::vector< T, Alloc > &buf, size_t buf_offset, const T input[], size_t input_length)
Definition: secmem.h:80
DER_Encoder & start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Definition: der_enc.cpp:181
PSSR(HashFunction *hash)
Definition: pssr.cpp:128
EMSA * clone() override
Definition: pssr.cpp:281
void mgf1_mask(HashFunction &hash, const uint8_t in[], size_t in_len, uint8_t out[], size_t out_len)
Definition: mgf1.cpp:14
AlgorithmIdentifier config_for_x509(const Private_Key &key, const std::string &cert_hash_name) const override
Definition: pssr.cpp:192
MechanismType hash