Botan 2.13.0 Crypto and TLS for C++11

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

mode_pad.cpp
Go to the documentation of this file.
1 /*
2 * CBC Padding Methods
3 * (C) 1999-2007,2013,2018 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 */
41 void PKCS7_Padding::add_padding(secure_vector<uint8_t>& buffer,
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 input[], size_t input_length) const
55 {
56 if(!valid_blocksize(input_length))
57 return input_length;
58
59 CT::poison(input, input_length);
60
61 const uint8_t last_byte = input[input_length-1];
62
63 /*
64 The input should == the block size so if the last byte exceeds
65 that then the padding is certainly invalid
66 */
67 auto bad_input = CT::Mask<size_t>::is_gt(last_byte, input_length);
68
69 const size_t pad_pos = input_length - last_byte;
70
71 for(size_t i = 0; i != input_length - 1; ++i)
72 {
73 // Does this byte equal the expected pad byte?
74 const auto pad_eq = CT::Mask<size_t>::is_equal(input[i], last_byte);
75
76 // Ignore values that are not part of the padding
77 const auto in_range = CT::Mask<size_t>::is_gte(i, pad_pos);
78 bad_input |= in_range & (~pad_eq);
79 }
80
81 CT::unpoison(input, input_length);
82
83 return bad_input.select_and_unpoison(input_length, pad_pos);
84 }
85
86 /*
87 * Pad with ANSI X9.23 Method
88 */
89 void ANSI_X923_Padding::add_padding(secure_vector<uint8_t>& buffer,
90 size_t last_byte_pos,
91 size_t block_size) const
92 {
93 const uint8_t pad_value = static_cast<uint8_t>(block_size - last_byte_pos);
94
95 for(size_t i = last_byte_pos; i < block_size-1; ++i)
96 {
97 buffer.push_back(0);
98 }
99 buffer.push_back(pad_value);
100 }
101
102 /*
103 * Unpad with ANSI X9.23 Method
104 */
105 size_t ANSI_X923_Padding::unpad(const uint8_t input[], size_t input_length) const
106 {
107 if(!valid_blocksize(input_length))
108 return input_length;
109
110 CT::poison(input, input_length);
111
112 const size_t last_byte = input[input_length-1];
113
114 auto bad_input = CT::Mask<size_t>::is_gt(last_byte, input_length);
115
116 const size_t pad_pos = input_length - last_byte;
117
118 for(size_t i = 0; i != input_length - 1; ++i)
119 {
120 // Ignore values that are not part of the padding
121 const auto in_range = CT::Mask<size_t>::is_gte(i, pad_pos);
122 const auto pad_is_nonzero = CT::Mask<size_t>::expand(input[i]);
123 bad_input |= pad_is_nonzero & in_range;
124 }
125
126 CT::unpoison(input, input_length);
127
128 return bad_input.select_and_unpoison(input_length, pad_pos);
129 }
130
131 /*
132 * Pad with One and Zeros Method
133 */
134 void OneAndZeros_Padding::add_padding(secure_vector<uint8_t>& buffer,
135 size_t last_byte_pos,
136 size_t block_size) const
137 {
138 buffer.push_back(0x80);
139
140 for(size_t i = last_byte_pos + 1; i % block_size; ++i)
141 buffer.push_back(0x00);
142 }
143
144 /*
145 * Unpad with One and Zeros Method
146 */
147 size_t OneAndZeros_Padding::unpad(const uint8_t input[], size_t input_length) const
148 {
149 if(!valid_blocksize(input_length))
150 return input_length;
151
152 CT::poison(input, input_length);
153
154 auto bad_input = CT::Mask<uint8_t>::cleared();
155 auto seen_0x80 = CT::Mask<uint8_t>::cleared();
156
157 size_t pad_pos = input_length - 1;
158 size_t i = input_length;
159
160 while(i)
161 {
162 const auto is_0x80 = CT::Mask<uint8_t>::is_equal(input[i-1], 0x80);
163 const auto is_zero = CT::Mask<uint8_t>::is_zero(input[i-1]);
164
165 seen_0x80 |= is_0x80;
166 pad_pos -= seen_0x80.if_not_set_return(1);
167 bad_input |= ~seen_0x80 & ~is_zero;
168 i--;
169 }
170 bad_input |= ~seen_0x80;
171
172 CT::unpoison(input, input_length);
173
174 return CT::Mask<size_t>::expand(bad_input).select_and_unpoison(input_length, pad_pos);
175 }
176
177 /*
178 * Pad with ESP Padding Method
179 */
180 void ESP_Padding::add_padding(secure_vector<uint8_t>& buffer,
181 size_t last_byte_pos,
182 size_t block_size) const
183 {
184 uint8_t pad_value = 0x01;
185
186 for(size_t i = last_byte_pos; i < block_size; ++i)
187 {
188 buffer.push_back(pad_value++);
189 }
190 }
191
192 /*
193 * Unpad with ESP Padding Method
194 */
195 size_t ESP_Padding::unpad(const uint8_t input[], size_t input_length) const
196 {
197 if(!valid_blocksize(input_length))
198 return input_length;
199
200 CT::poison(input, input_length);
201
202 const uint8_t input_length_8 = static_cast<uint8_t>(input_length);
203 const uint8_t last_byte = input[input_length-1];
204
205 auto bad_input = CT::Mask<uint8_t>::is_zero(last_byte) |
206 CT::Mask<uint8_t>::is_gt(last_byte, input_length_8);
207
208 const uint8_t pad_pos = input_length_8 - last_byte;
209 size_t i = input_length_8 - 1;
210 while(i)
211 {
212 const auto in_range = CT::Mask<size_t>::is_gt(i, pad_pos);
213 const auto incrementing = CT::Mask<uint8_t>::is_equal(input[i-1], input[i]-1);
214
215 bad_input |= CT::Mask<uint8_t>(in_range) & ~incrementing;
216 --i;
217 }
218
219 CT::unpoison(input, input_length);
220 return bad_input.select_and_unpoison(input_length_8, pad_pos);
221 }
222
223
224 }
Botan::ESP_Padding::unpad
size_t unpad(const uint8_t[], size_t) const override
Definition: mode_pad.cpp:195
Botan::CT::Mask::cleared
static Mask< T > cleared()
Definition: ct_utils.h:115
Botan::ESP_Padding::valid_blocksize
bool valid_blocksize(size_t bs) const override
Definition: mode_pad.h:129
Botan::ANSI_X923_Padding::valid_blocksize
bool valid_blocksize(size_t bs) const override
Definition: mode_pad.h:95
Botan::PKCS7_Padding::unpad
size_t unpad(const uint8_t[], size_t) const override
Definition: mode_pad.cpp:54
Botan::ANSI_X923_Padding::add_padding
void add_padding(secure_vector< uint8_t > &buffer, size_t final_block_bytes, size_t block_size) const override
Definition: mode_pad.cpp:89
Botan::CT::Mask
Definition: ct_utils.h:87
Botan::CT::Mask::is_gte
static Mask< T > is_gte(T x, T y)
Definition: ct_utils.h:181
Botan::CT::poison
void poison(const T *p, size_t n)
Definition: ct_utils.h:48
Botan::ESP_Padding::add_padding
void add_padding(secure_vector< uint8_t > &buffer, size_t final_block_bytes, size_t block_size) const override
Definition: mode_pad.cpp:180
Botan::Null_Padding
Definition: mode_pad.h:137
Botan::CT::Mask::expand
static Mask< T > expand(T v)
Definition: ct_utils.h:123
Botan::secure_vector
std::vector< T, secure_allocator< T >> secure_vector
Definition: secmem.h:65
Botan::ESP_Padding
Definition: mode_pad.h:120
Botan::OneAndZeros_Padding::add_padding
void add_padding(secure_vector< uint8_t > &buffer, size_t final_block_bytes, size_t block_size) const override
Definition: mode_pad.cpp:134
Botan::ANSI_X923_Padding::unpad
size_t unpad(const uint8_t[], size_t) const override
Definition: mode_pad.cpp:105
Botan::PKCS7_Padding::valid_blocksize
bool valid_blocksize(size_t bs) const override
Definition: mode_pad.h:78
Botan::PKCS7_Padding::add_padding
void add_padding(secure_vector< uint8_t > &buffer, size_t final_block_bytes, size_t block_size) const override
Definition: mode_pad.cpp:41
Botan
Definition: alg_id.cpp:13
Botan::OneAndZeros_Padding
Definition: mode_pad.h:103
Botan::BlockCipherModePaddingMethod
Definition: mode_pad.h:28
Botan::ANSI_X923_Padding
Definition: mode_pad.h:86
Botan::OneAndZeros_Padding::valid_blocksize
bool valid_blocksize(size_t bs) const override
Definition: mode_pad.h:112
Botan::PKCS7_Padding
Definition: mode_pad.h:69
Botan::CT::unpoison
void unpoison(const T *p, size_t n)
Definition: ct_utils.h:59
Botan::OneAndZeros_Padding::unpad
size_t unpad(const uint8_t[], size_t) const override
Definition: mode_pad.cpp:147
Botan::CT::Mask::is_zero
static Mask< T > is_zero(T x)
Definition: ct_utils.h:141
Botan::CT::Mask::is_equal
static Mask< T > is_equal(T x, T y)
Definition: ct_utils.h:149
Botan::CT::Mask::is_gt
static Mask< T > is_gt(T x, T y)
Definition: ct_utils.h:165
Botan::get_bc_pad
BlockCipherModePaddingMethod * get_bc_pad(const std::string &algo_spec)
Definition: mode_pad.cpp:18