• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 5079590438

25 May 2023 12:28PM UTC coverage: 92.228% (+0.5%) from 91.723%
5079590438

Pull #3502

github

Pull Request #3502: Apply clang-format to the codebase

75589 of 81959 relevant lines covered (92.23%)

12139530.51 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.29
/src/lib/modes/mode_pad/mode_pad.cpp
1
/*
2
* CBC Padding Methods
3
* (C) 1999-2007,2013,2018,2020 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/internal/mode_pad.h>
10

11
#include <botan/exceptn.h>
12
#include <botan/internal/ct_utils.h>
13

14
namespace Botan {
15

16
/**
17
* Get a block cipher padding method by name
18
*/
19
std::unique_ptr<BlockCipherModePaddingMethod> BlockCipherModePaddingMethod::create(std::string_view algo_spec) {
2,149✔
20
   if(algo_spec == "NoPadding")
2,149✔
21
      return std::make_unique<Null_Padding>();
107✔
22

23
   if(algo_spec == "PKCS7")
2,058✔
24
      return std::make_unique<PKCS7_Padding>();
1,818✔
25

26
   if(algo_spec == "OneAndZeros")
224✔
27
      return std::make_unique<OneAndZeros_Padding>();
188✔
28

29
   if(algo_spec == "X9.23")
36✔
30
      return std::make_unique<ANSI_X923_Padding>();
16✔
31

32
   if(algo_spec == "ESP")
20✔
33
      return std::make_unique<ESP_Padding>();
20✔
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, size_t last_byte_pos, size_t BS) const {
1,343✔
42
   /*
43
   Padding format is
44
   01
45
   0202
46
   030303
47
   ...
48
   */
49
   BOTAN_DEBUG_ASSERT(last_byte_pos < BS);
1,343✔
50

51
   const uint8_t padding_len = static_cast<uint8_t>(BS - last_byte_pos);
1,343✔
52

53
   buffer.resize(buffer.size() + padding_len);
1,343✔
54

55
   CT::poison(&last_byte_pos, 1);
1,343✔
56
   CT::poison(buffer.data(), buffer.size());
1,343✔
57

58
   BOTAN_DEBUG_ASSERT(buffer.size() % BS == 0);
1,343✔
59
   BOTAN_DEBUG_ASSERT(buffer.size() >= BS);
1,343✔
60

61
   const size_t start_of_last_block = buffer.size() - BS;
1,343✔
62
   const size_t end_of_last_block = buffer.size();
1,343✔
63
   const size_t start_of_padding = buffer.size() - padding_len;
1,343✔
64

65
   for(size_t i = start_of_last_block; i != end_of_last_block; ++i) {
21,727✔
66
      auto needs_padding = CT::Mask<uint8_t>(CT::Mask<size_t>::is_gte(i, start_of_padding));
20,384✔
67
      buffer[i] = needs_padding.select(padding_len, buffer[i]);
20,384✔
68
   }
69

70
   CT::unpoison(buffer.data(), buffer.size());
1,343✔
71
   CT::unpoison(last_byte_pos);
1,343✔
72
}
1,343✔
73

74
/*
75
* Unpad with PKCS #7 Method
76
*/
77
size_t PKCS7_Padding::unpad(const uint8_t input[], size_t input_length) const {
1,565✔
78
   if(!valid_blocksize(input_length))
1,565✔
79
      return input_length;
80

81
   CT::poison(input, input_length);
1,565✔
82

83
   const uint8_t last_byte = input[input_length - 1];
1,565✔
84

85
   /*
86
   The input should == the block size so if the last byte exceeds
87
   that then the padding is certainly invalid
88
   */
89
   auto bad_input = CT::Mask<size_t>::is_gt(last_byte, input_length);
1,565✔
90

91
   const size_t pad_pos = input_length - last_byte;
1,565✔
92

93
   for(size_t i = 0; i != input_length - 1; ++i) {
52,467✔
94
      // Does this byte equal the expected pad byte?
95
      const auto pad_eq = CT::Mask<size_t>::is_equal(input[i], last_byte);
50,902✔
96

97
      // Ignore values that are not part of the padding
98
      const auto in_range = CT::Mask<size_t>::is_gte(i, pad_pos);
50,902✔
99
      bad_input |= in_range & (~pad_eq);
50,902✔
100
   }
101

102
   CT::unpoison(input, input_length);
1,565✔
103

104
   return bad_input.select_and_unpoison(input_length, pad_pos);
1,565✔
105
}
106

107
/*
108
* Pad with ANSI X9.23 Method
109
*/
110
void ANSI_X923_Padding::add_padding(secure_vector<uint8_t>& buffer, size_t last_byte_pos, size_t BS) const {
8✔
111
   /*
112
   Padding format is
113
   01
114
   0002
115
   000003
116
   ...
117
   */
118
   BOTAN_DEBUG_ASSERT(last_byte_pos < BS);
8✔
119

120
   const uint8_t padding_len = static_cast<uint8_t>(BS - last_byte_pos);
8✔
121

122
   buffer.resize(buffer.size() + padding_len);
8✔
123

124
   CT::poison(&last_byte_pos, 1);
8✔
125
   CT::poison(buffer.data(), buffer.size());
8✔
126

127
   BOTAN_DEBUG_ASSERT(buffer.size() % BS == 0);
8✔
128
   BOTAN_DEBUG_ASSERT(buffer.size() >= BS);
8✔
129

130
   const size_t start_of_last_block = buffer.size() - BS;
8✔
131
   const size_t end_of_zero_padding = buffer.size() - 1;
8✔
132
   const size_t start_of_padding = buffer.size() - padding_len;
8✔
133

134
   for(size_t i = start_of_last_block; i != end_of_zero_padding; ++i) {
144✔
135
      auto needs_padding = CT::Mask<uint8_t>(CT::Mask<size_t>::is_gte(i, start_of_padding));
136✔
136
      buffer[i] = needs_padding.select(0, buffer[i]);
136✔
137
   }
138

139
   buffer[buffer.size() - 1] = padding_len;
8✔
140
   CT::unpoison(buffer.data(), buffer.size());
8✔
141
   CT::unpoison(last_byte_pos);
8✔
142
}
8✔
143

144
/*
145
* Unpad with ANSI X9.23 Method
146
*/
147
size_t ANSI_X923_Padding::unpad(const uint8_t input[], size_t input_length) const {
269✔
148
   if(!valid_blocksize(input_length))
269✔
149
      return input_length;
150

151
   CT::poison(input, input_length);
269✔
152

153
   const size_t last_byte = input[input_length - 1];
269✔
154

155
   auto bad_input = CT::Mask<size_t>::is_gt(last_byte, input_length);
269✔
156

157
   const size_t pad_pos = input_length - last_byte;
269✔
158

159
   for(size_t i = 0; i != input_length - 1; ++i) {
32,841✔
160
      // Ignore values that are not part of the padding
161
      const auto in_range = CT::Mask<size_t>::is_gte(i, pad_pos);
32,572✔
162
      const auto pad_is_nonzero = CT::Mask<size_t>::expand(input[i]);
32,572✔
163
      bad_input |= pad_is_nonzero & in_range;
32,572✔
164
   }
165

166
   CT::unpoison(input, input_length);
269✔
167

168
   return bad_input.select_and_unpoison(input_length, pad_pos);
269✔
169
}
170

171
/*
172
* Pad with One and Zeros Method
173
*/
174
void OneAndZeros_Padding::add_padding(secure_vector<uint8_t>& buffer, size_t last_byte_pos, size_t BS) const {
126✔
175
   /*
176
   Padding format is
177
   80
178
   8000
179
   800000
180
   ...
181
   */
182

183
   BOTAN_DEBUG_ASSERT(last_byte_pos < BS);
126✔
184

185
   const uint8_t padding_len = static_cast<uint8_t>(BS - last_byte_pos);
126✔
186

187
   buffer.resize(buffer.size() + padding_len);
126✔
188

189
   CT::poison(&last_byte_pos, 1);
126✔
190
   CT::poison(buffer.data(), buffer.size());
126✔
191

192
   BOTAN_DEBUG_ASSERT(buffer.size() % BS == 0);
126✔
193
   BOTAN_DEBUG_ASSERT(buffer.size() >= BS);
126✔
194

195
   const size_t start_of_last_block = buffer.size() - BS;
126✔
196
   const size_t end_of_last_block = buffer.size();
126✔
197
   const size_t start_of_padding = buffer.size() - padding_len;
126✔
198

199
   for(size_t i = start_of_last_block; i != end_of_last_block; ++i) {
1,214✔
200
      auto needs_80 = CT::Mask<uint8_t>(CT::Mask<size_t>::is_equal(i, start_of_padding));
1,088✔
201
      auto needs_00 = CT::Mask<uint8_t>(CT::Mask<size_t>::is_gt(i, start_of_padding));
1,088✔
202
      buffer[i] = needs_00.select(0x00, needs_80.select(0x80, buffer[i]));
1,088✔
203
   }
204

205
   CT::unpoison(buffer.data(), buffer.size());
126✔
206
   CT::unpoison(last_byte_pos);
126✔
207
}
126✔
208

209
/*
210
* Unpad with One and Zeros Method
211
*/
212
size_t OneAndZeros_Padding::unpad(const uint8_t input[], size_t input_length) const {
1,129✔
213
   if(!valid_blocksize(input_length))
1,129✔
214
      return input_length;
215

216
   CT::poison(input, input_length);
1,129✔
217

218
   auto bad_input = CT::Mask<uint8_t>::cleared();
1,129✔
219
   auto seen_0x80 = CT::Mask<uint8_t>::cleared();
1,129✔
220

221
   size_t pad_pos = input_length - 1;
1,129✔
222
   size_t i = input_length;
1,129✔
223

224
   while(i) {
502,010✔
225
      const auto is_0x80 = CT::Mask<uint8_t>::is_equal(input[i - 1], 0x80);
500,881✔
226
      const auto is_zero = CT::Mask<uint8_t>::is_zero(input[i - 1]);
500,881✔
227

228
      seen_0x80 |= is_0x80;
500,881✔
229
      pad_pos -= seen_0x80.if_not_set_return(1);
500,881✔
230
      bad_input |= ~seen_0x80 & ~is_zero;
500,881✔
231
      i--;
500,881✔
232
   }
233
   bad_input |= ~seen_0x80;
1,129✔
234

235
   CT::unpoison(input, input_length);
1,129✔
236

237
   return CT::Mask<size_t>::expand(bad_input).select_and_unpoison(input_length, pad_pos);
1,129✔
238
}
239

240
/*
241
* Pad with ESP Padding Method
242
*/
243
void ESP_Padding::add_padding(secure_vector<uint8_t>& buffer, size_t last_byte_pos, size_t BS) const {
12✔
244
   /*
245
   Padding format is
246
   01
247
   0102
248
   010203
249
   ...
250
   */
251
   BOTAN_DEBUG_ASSERT(last_byte_pos < BS);
12✔
252

253
   const uint8_t padding_len = static_cast<uint8_t>(BS - last_byte_pos);
12✔
254

255
   buffer.resize(buffer.size() + padding_len);
12✔
256

257
   CT::poison(&last_byte_pos, 1);
12✔
258
   CT::poison(buffer.data(), buffer.size());
12✔
259

260
   BOTAN_DEBUG_ASSERT(buffer.size() % BS == 0);
12✔
261
   BOTAN_DEBUG_ASSERT(buffer.size() >= BS);
12✔
262

263
   const size_t start_of_last_block = buffer.size() - BS;
12✔
264
   const size_t end_of_last_block = buffer.size();
12✔
265
   const size_t start_of_padding = buffer.size() - padding_len;
12✔
266

267
   uint8_t pad_ctr = 0x01;
12✔
268

269
   for(size_t i = start_of_last_block; i != end_of_last_block; ++i) {
196✔
270
      auto needs_padding = CT::Mask<uint8_t>(CT::Mask<size_t>::is_gte(i, start_of_padding));
184✔
271
      buffer[i] = needs_padding.select(pad_ctr, buffer[i]);
184✔
272
      pad_ctr = needs_padding.select(pad_ctr + 1, pad_ctr);
184✔
273
   }
274

275
   CT::unpoison(buffer.data(), buffer.size());
12✔
276
   CT::unpoison(last_byte_pos);
12✔
277
}
12✔
278

279
/*
280
* Unpad with ESP Padding Method
281
*/
282
size_t ESP_Padding::unpad(const uint8_t input[], size_t input_length) const {
273✔
283
   if(!valid_blocksize(input_length))
273✔
284
      return input_length;
285

286
   CT::poison(input, input_length);
273✔
287

288
   const uint8_t input_length_8 = static_cast<uint8_t>(input_length);
273✔
289
   const uint8_t last_byte = input[input_length - 1];
273✔
290

291
   auto bad_input = CT::Mask<uint8_t>::is_zero(last_byte) | CT::Mask<uint8_t>::is_gt(last_byte, input_length_8);
273✔
292

293
   const uint8_t pad_pos = input_length_8 - last_byte;
273✔
294
   size_t i = input_length_8 - 1;
273✔
295
   while(i) {
32,893✔
296
      const auto in_range = CT::Mask<size_t>::is_gt(i, pad_pos);
32,620✔
297
      const auto incrementing = CT::Mask<uint8_t>::is_equal(input[i - 1], input[i] - 1);
32,620✔
298

299
      bad_input |= CT::Mask<uint8_t>(in_range) & ~incrementing;
32,620✔
300
      --i;
32,620✔
301
   }
302

303
   CT::unpoison(input, input_length);
273✔
304
   return bad_input.select_and_unpoison(input_length_8, pad_pos);
273✔
305
}
306

307
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc