Botan  2.6.0
Crypto and TLS for C++11
mode_pad.cpp
Go to the documentation of this file.
1 /*
2 * CBC Padding Methods
3 * (C) 1999-2007,2013 Jack Lloyd
4 * (C) 2016 RenĂ© Korthaus, Rohde & Schwarz Cybersecurity
5 *
6 * Botan is released under the Simplified BSD License (see license.txt)
7 */
8 
9 #include <botan/mode_pad.h>
10 #include <botan/exceptn.h>
11 #include <botan/internal/ct_utils.h>
12 
13 namespace Botan {
14 
15 /**
16 * Get a block cipher padding method by name
17 */
18 BlockCipherModePaddingMethod* get_bc_pad(const std::string& algo_spec)
19  {
20  if(algo_spec == "NoPadding")
21  return new Null_Padding;
22 
23  if(algo_spec == "PKCS7")
24  return new PKCS7_Padding;
25 
26  if(algo_spec == "OneAndZeros")
27  return new OneAndZeros_Padding;
28 
29  if(algo_spec == "X9.23")
30  return new ANSI_X923_Padding;
31 
32  if(algo_spec == "ESP")
33  return new ESP_Padding;
34 
35  return nullptr;
36  }
37 
38 /*
39 * Pad with PKCS #7 Method
40 */
42  size_t last_byte_pos,
43  size_t block_size) const
44  {
45  const uint8_t pad_value = static_cast<uint8_t>(block_size - last_byte_pos);
46 
47  for(size_t i = 0; i != pad_value; ++i)
48  buffer.push_back(pad_value);
49  }
50 
51 /*
52 * Unpad with PKCS #7 Method
53 */
54 size_t PKCS7_Padding::unpad(const uint8_t block[], size_t size) const
55  {
56  CT::poison(block,size);
57  size_t bad_input = 0;
58  const uint8_t last_byte = block[size-1];
59 
60  bad_input |= CT::expand_mask<size_t>(last_byte > size);
61 
62  size_t pad_pos = size - last_byte;
63  size_t i = size - 2;
64  while(i)
65  {
66  bad_input |= (~CT::is_equal(block[i],last_byte)) & CT::expand_mask<uint8_t>(i >= pad_pos);
67  --i;
68  }
69 
70  CT::conditional_copy_mem(bad_input,&pad_pos,&size,&pad_pos,1);
71  CT::unpoison(block,size);
72  CT::unpoison(pad_pos);
73  return pad_pos;
74  }
75 
76 /*
77 * Pad with ANSI X9.23 Method
78 */
80  size_t last_byte_pos,
81  size_t block_size) const
82  {
83  const uint8_t pad_value = static_cast<uint8_t>(block_size - last_byte_pos);
84 
85  for(size_t i = last_byte_pos; i < block_size-1; ++i)
86  {
87  buffer.push_back(0);
88  }
89  buffer.push_back(pad_value);
90  }
91 
92 /*
93 * Unpad with ANSI X9.23 Method
94 */
95 size_t ANSI_X923_Padding::unpad(const uint8_t block[], size_t size) const
96  {
97  CT::poison(block,size);
98  size_t bad_input = 0;
99  const size_t last_byte = block[size-1];
100 
101  bad_input |= CT::expand_mask<size_t>(last_byte > size);
102 
103  size_t pad_pos = size - last_byte;
104  size_t i = size - 2;
105  while(i)
106  {
107  bad_input |= (~CT::is_zero(block[i])) & CT::expand_mask<uint8_t>(i >= pad_pos);
108  --i;
109  }
110  CT::conditional_copy_mem(bad_input,&pad_pos,&size,&pad_pos,1);
111  CT::unpoison(block,size);
112  CT::unpoison(pad_pos);
113  return pad_pos;
114  }
115 
116 /*
117 * Pad with One and Zeros Method
118 */
120  size_t last_byte_pos,
121  size_t block_size) const
122  {
123  buffer.push_back(0x80);
124 
125  for(size_t i = last_byte_pos + 1; i % block_size; ++i)
126  buffer.push_back(0x00);
127  }
128 
129 /*
130 * Unpad with One and Zeros Method
131 */
132 size_t OneAndZeros_Padding::unpad(const uint8_t block[], size_t size) const
133  {
134  CT::poison(block, size);
135  uint8_t bad_input = 0;
136  uint8_t seen_one = 0;
137  size_t pad_pos = size - 1;
138  size_t i = size;
139 
140  while(i)
141  {
142  seen_one |= CT::is_equal<uint8_t>(block[i-1],0x80);
143  pad_pos -= CT::select<uint8_t>(~seen_one, 1, 0);
144  bad_input |= ~CT::is_zero<uint8_t>(block[i-1]) & ~seen_one;
145  i--;
146  }
147  bad_input |= ~seen_one;
148 
149  CT::conditional_copy_mem(size_t(bad_input),&pad_pos,&size,&pad_pos,1);
150  CT::unpoison(block, size);
151  CT::unpoison(pad_pos);
152 
153  return pad_pos;
154  }
155 
156 /*
157 * Pad with ESP Padding Method
158 */
160  size_t last_byte_pos,
161  size_t block_size) const
162  {
163  uint8_t pad_value = 0x01;
164 
165  for(size_t i = last_byte_pos; i < block_size; ++i)
166  {
167  buffer.push_back(pad_value++);
168  }
169  }
170 
171 /*
172 * Unpad with ESP Padding Method
173 */
174 size_t ESP_Padding::unpad(const uint8_t block[], size_t size) const
175  {
176  CT::poison(block,size);
177 
178  const size_t last_byte = block[size-1];
179  size_t bad_input = 0;
180  bad_input |= CT::expand_mask<size_t>(last_byte > size);
181 
182  size_t pad_pos = size - last_byte;
183  size_t i = size - 1;
184  while(i)
185  {
186  bad_input |= ~CT::is_equal<uint8_t>(size_t(block[i-1]),size_t(block[i])-1) & CT::expand_mask<uint8_t>(i > pad_pos);
187  --i;
188  }
189  CT::conditional_copy_mem(bad_input,&pad_pos,&size,&pad_pos,1);
190  CT::unpoison(block, size);
191  CT::unpoison(pad_pos);
192  return pad_pos;
193  }
194 
195 
196 }
size_t unpad(const uint8_t[], size_t) const override
Definition: mode_pad.cpp:174
size_t unpad(const uint8_t[], size_t) const override
Definition: mode_pad.cpp:54
void conditional_copy_mem(T value, T *to, const T *from0, const T *from1, size_t elems)
Definition: ct_utils.h:142
void add_padding(secure_vector< uint8_t > &buffer, size_t final_block_bytes, size_t block_size) const override
Definition: mode_pad.cpp:79
void poison(const T *p, size_t n)
Definition: ct_utils.h:46
void add_padding(secure_vector< uint8_t > &buffer, size_t final_block_bytes, size_t block_size) const override
Definition: mode_pad.cpp:159
T is_equal(T x, T y)
Definition: ct_utils.h:124
void add_padding(secure_vector< uint8_t > &buffer, size_t final_block_bytes, size_t block_size) const override
Definition: mode_pad.cpp:119
size_t unpad(const uint8_t[], size_t) const override
Definition: mode_pad.cpp:95
void add_padding(secure_vector< uint8_t > &buffer, size_t final_block_bytes, size_t block_size) const override
Definition: mode_pad.cpp:41
Definition: alg_id.cpp:13
T is_zero(T x)
Definition: ct_utils.h:118
void unpoison(const T *p, size_t n)
Definition: ct_utils.h:57
size_t unpad(const uint8_t[], size_t) const override
Definition: mode_pad.cpp:132
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:88
BlockCipherModePaddingMethod * get_bc_pad(const std::string &algo_spec)
Definition: mode_pad.cpp:18