padding.hpp
Go to the documentation of this file.
1 //---------------------------------------------------------------------------//
2 // Copyright (c) 2018-2020 Mikhail Komarov <nemo@nil.foundation>
3 //
4 // MIT License
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining a copy
7 // of this software and associated documentation files (the "Software"), to deal
8 // in the Software without restriction, including without limitation the rights
9 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 // copies of the Software, and to permit persons to whom the Software is
11 // furnished to do so, subject to the following conditions:
12 //
13 // The above copyright notice and this permission notice shall be included in all
14 // copies or substantial portions of the Software.
15 //
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 // SOFTWARE.
23 //---------------------------------------------------------------------------//
24 
25 #ifndef CRYPTO3_MODE_PADDING_HPP
26 #define CRYPTO3_MODE_PADDING_HPP
27 
28 #include <nil/crypto3/utilities/secmem.hpp>
29 
30 #include <string>
31 
32 #include <boost/static_assert.hpp>
33 
34 namespace nil {
35  namespace crypto3 {
36  namespace block {
37  namespace modes {
38  namespace padding {
50  template<typename Cipher>
51  struct basic_padding {
52  typedef std::size_t size_type;
53 
54  typedef Cipher cipher_type;
55 
56  constexpr static const size_type block_bits = cipher_type::block_bits;
57  constexpr static const size_type block_words = cipher_type::block_words;
58  typedef typename cipher_type::block_type block_type;
59  };
60 
64  template<typename Cipher>
65  struct zeros : public basic_padding<Cipher> {
67 
69 
73 
74  constexpr static const bool always_pad = false;
75 
76  inline static size_type required_output_size(size_type len, size_type block_size) {
77  if (len) {
78  const size_type rem = len % block_size;
79  if (rem) {
80  if (std::numeric_limits<size_type>::max() - len < block_size) {
81  throw std::overflow_error("message length is too long");
82  } else {
83  return len - rem + block_size;
84  }
85  }
86  }
87  return len;
88  }
89 
90  inline static block_type pad(const block_type &block, size_type bytes_in_block) {
91  block_type result = block;
92  uint8_t *ptr = static_cast<uint8_t *>(&*result.data());
93  std::memset(ptr + bytes_in_block, 0, block_bits / CHAR_BIT - bytes_in_block);
94 
95  return result;
96  }
97 
98  inline static block_type unpad(const block_type &block, size_type bytes_in_block) {
99  ct::poison(block, bytes_in_block);
100  uint8_t bad_input = 0;
101  uint8_t seen_one = 0;
102  size_t pad_pos = bytes_in_block - 1;
103  size_t i = bytes_in_block;
104 
105  while (i) {
106  seen_one |= ct::is_equal<uint8_t>(block[i - 1], 0x80);
107  pad_pos -= ct::select<uint8_t>(~seen_one, 1, 0);
108  bad_input |= ~ct::is_zero<uint8_t>(block[i - 1]) & ~seen_one;
109  i--;
110  }
111  bad_input |= ~seen_one;
112 
113  ct::conditional_copy_mem(size_t(bad_input), &pad_pos, &bytes_in_block, &pad_pos, 1);
114  ct::unpoison(block, bytes_in_block);
115  ct::unpoison(pad_pos);
116  }
117  };
118 
124  template<typename Cipher>
125  struct one_and_zeros : public basic_padding<Cipher> {
127 
129 
133 
135 
136  constexpr static const bool always_pad = true;
137 
138  inline static size_type required_output_size(size_type len, size_type block_size) {
139  if (len) {
140  const size_type rem = len % block_size;
141  if (rem) {
142  if (std::numeric_limits<size_type>::max() - len < block_size) {
143  throw std::overflow_error("message length is too long");
144  } else {
145  return len - rem + block_size;
146  }
147  }
148  }
149  return len + block_size;
150  }
151 
152  inline static block_type pad(const block_type &block, size_type bytes_in_block) {
153  block_type result = block;
154  uint8_t *ptr = static_cast<uint8_t *>(result);
155  ptr += bytes_in_block;
156  *ptr++ = 0x80;
157  ++bytes_in_block;
158  std::memset(ptr, 0, block_bits / CHAR_BIT - bytes_in_block);
159  return result;
160  }
161  };
162 
167  template<typename Cipher>
168  struct trailing_bit : public basic_padding<Cipher> {
170 
172 
176  };
177 
203  template<typename Cipher>
204  struct pkcs7 : public basic_padding<Cipher> {
206 
208 
212 
214 
215  inline static void pad(const block_type &block, size_type bytes_in_block) {
216  const uint8_t pad_value = static_cast<uint8_t>(block_size - last_byte_pos);
217 
218  for (size_t i = 0; i != pad_value; ++i) {
219  buffer.push_back(pad_value);
220  }
221  }
222 
223  inline static void unpad(const block_type &block, size_type bytes_in_block) {
224  ct::poison(block, bytes_in_block);
225  size_t bad_input = 0;
226  const uint8_t last_byte = block[bytes_in_block - 1];
227 
228  bad_input |= ct::expand_mask<size_t>(last_byte > bytes_in_block);
229 
230  size_t pad_pos = bytes_in_block - last_byte;
231  size_t i = bytes_in_block - 2;
232  while (i) {
233  bad_input |=
234  (~ct::is_equal(block[i], last_byte)) & ct::expand_mask<uint8_t>(i >= pad_pos);
235  --i;
236  }
237 
238  ct::conditional_copy_mem(bad_input, &pad_pos, &bytes_in_block, &pad_pos, 1);
239  ct::unpoison(block, bytes_in_block);
240  ct::unpoison(pad_pos);
241  }
242  };
243 
248  template<typename Cipher>
249  struct esp : public basic_padding<Cipher> {
251 
253 
257 
258  inline static void pad(const block_type &block, size_type bytes_in_block) {
259  uint8_t pad_value = 0x01;
260 
261  for (size_t i = last_byte_pos; i < bytes_in_block; ++i) {
262  buffer.push_back(pad_value++);
263  }
264  }
265 
266  inline static void unpad(const block_type &block, size_type size) {
267  ct::poison(block, size);
268 
269  const size_t last_byte = block[size - 1];
270  size_t bad_input = 0;
271  bad_input |= ct::expand_mask<size_t>(last_byte > size);
272 
273  size_t pad_pos = size - last_byte;
274  size_t i = size - 1;
275  while (i) {
276  bad_input |= ~ct::is_equal<uint8_t>(size_t(block[i - 1]), size_t(block[i]) - 1) &
277  ct::expand_mask<uint8_t>(i > pad_pos);
278  --i;
279  }
280  ct::conditional_copy_mem(bad_input, &pad_pos, &size, &pad_pos, 1);
281  ct::unpoison(block, size);
282  ct::unpoison(pad_pos);
283  }
284  };
285 
290  template<typename Cipher>
291  struct ansi_x923 : public basic_padding<Cipher> {
293 
295 
299 
301 
302  inline static void pad(const block_type &block, size_type bytes_in_block) {
303  const uint8_t pad_value = static_cast<uint8_t>(bytes_in_block - last_byte_pos);
304 
305  for (size_t i = last_byte_pos; i < bytes_in_block - 1; ++i) {
306  buffer.push_back(0);
307  }
308  buffer.push_back(pad_value);
309  }
310 
311  inline static void unpad(const block_type &block, size_type size) {
312  ct::poison(block, size);
313  size_t bad_input = 0;
314  const size_t last_byte = block[size - 1];
315 
316  bad_input |= ct::expand_mask<size_t>(last_byte > size);
317 
318  size_t pad_pos = size - last_byte;
319  size_t i = size - 2;
320  while (i) {
321  bad_input |= (~ct::is_zero(block[i])) & ct::expand_mask<uint8_t>(i >= pad_pos);
322  --i;
323  }
324  ct::conditional_copy_mem(bad_input, &pad_pos, &size, &pad_pos, 1);
325  ct::unpoison(block, size);
326  ct::unpoison(pad_pos);
327  }
328  };
329  } // namespace padding
330  } // namespace modes
331  } // namespace block
332  } // namespace crypto3
333 } // namespace nil
334 
335 #endif
constexpr T max(const vector< T, N > &v)
computes the maximum valued element
Definition: algebra/include/nil/crypto3/algebra/vector/math.hpp:146
boost::mpl::apply< AccumulatorSet, tag::block< Mode > >::type::result_type block(const AccumulatorSet &acc)
Definition: accumulators/block.hpp:259
bool is_zero(const Range &a)
Definition: basic_operations.hpp:43
Definition: pair.hpp:31
ANSI X9.23 Padding.
Definition: padding.hpp:291
constexpr static const size_type block_bits
Definition: padding.hpp:296
basic_padding< Cipher >::size_type size_type
Definition: padding.hpp:292
static void pad(const block_type &block, size_type bytes_in_block)
Definition: padding.hpp:302
constexpr static const size_type block_words
Definition: padding.hpp:297
BOOST_STATIC_ASSERT(block_bits > 0 &&block_bits< 256)
basic_padding< Cipher >::cipher_type cipher_type
Definition: padding.hpp:294
basic_padding< Cipher >::block_type block_type
Definition: padding.hpp:298
static void unpad(const block_type &block, size_type size)
Definition: padding.hpp:311
Block Cipher Mode Padding Method.
Definition: padding.hpp:51
std::size_t size_type
Definition: padding.hpp:52
Cipher cipher_type
Definition: padding.hpp:54
constexpr static const size_type block_bits
Definition: padding.hpp:56
constexpr static const size_type block_words
Definition: padding.hpp:57
cipher_type::block_type block_type
Definition: padding.hpp:58
ESP Padding (RFC 4304)
Definition: padding.hpp:249
static void pad(const block_type &block, size_type bytes_in_block)
Definition: padding.hpp:258
static void unpad(const block_type &block, size_type size)
Definition: padding.hpp:266
basic_padding< Cipher >::cipher_type cipher_type
Definition: padding.hpp:252
constexpr static const size_type block_bits
Definition: padding.hpp:254
basic_padding< Cipher >::size_type size_type
Definition: padding.hpp:250
basic_padding< Cipher >::block_type block_type
Definition: padding.hpp:256
constexpr static const size_type block_words
Definition: padding.hpp:255
(ISO/IEC 9797-1, padding method 2)
Definition: padding.hpp:125
static block_type pad(const block_type &block, size_type bytes_in_block)
Definition: padding.hpp:152
constexpr static const size_type block_words
Definition: padding.hpp:131
basic_padding< Cipher >::block_type block_type
Definition: padding.hpp:132
basic_padding< Cipher >::size_type size_type
Definition: padding.hpp:126
constexpr static const size_type block_bits
Definition: padding.hpp:130
constexpr static const bool always_pad
Definition: padding.hpp:136
basic_padding< Cipher >::cipher_type cipher_type
Definition: padding.hpp:128
static size_type required_output_size(size_type len, size_type block_size)
Definition: padding.hpp:138
static void unpad(const block_type &block, size_type bytes_in_block)
Definition: padding.hpp:223
static void pad(const block_type &block, size_type bytes_in_block)
Definition: padding.hpp:215
basic_padding< Cipher >::cipher_type cipher_type
Definition: padding.hpp:207
constexpr static const size_type block_bits
Definition: padding.hpp:209
basic_padding< Cipher >::block_type block_type
Definition: padding.hpp:211
basic_padding< Cipher >::size_type size_type
Definition: padding.hpp:205
BOOST_STATIC_ASSERT(block_bits > 0 &&block_bits< 256)
constexpr static const size_type block_words
Definition: padding.hpp:210
basic_padding< Cipher >::cipher_type cipher_type
Definition: padding.hpp:171
constexpr static const size_type block_bits
Definition: padding.hpp:173
basic_padding< Cipher >::size_type size_type
Definition: padding.hpp:169
basic_padding< Cipher >::block_type block_type
Definition: padding.hpp:175
constexpr static const size_type block_words
Definition: padding.hpp:174
static block_type pad(const block_type &block, size_type bytes_in_block)
Definition: padding.hpp:90
basic_padding< Cipher >::block_type block_type
Definition: padding.hpp:72
static size_type required_output_size(size_type len, size_type block_size)
Definition: padding.hpp:76
static block_type unpad(const block_type &block, size_type bytes_in_block)
Definition: padding.hpp:98
basic_padding< Cipher >::cipher_type cipher_type
Definition: padding.hpp:68
constexpr static const size_type block_words
Definition: padding.hpp:71
constexpr static const size_type block_bits
Definition: padding.hpp:70
constexpr static const bool always_pad
Definition: padding.hpp:74
basic_padding< Cipher >::size_type size_type
Definition: padding.hpp:66