Coverage Report

Created: 2024-11-29 06:10

/src/botan/src/lib/pk_pad/eme_pkcs1/eme_pkcs.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
* PKCS #1 v1.5 Type 2 (encryption) padding
3
* (C) 1999-2007,2015,2016,2024 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7
8
#include <botan/internal/eme_pkcs.h>
9
10
#include <botan/exceptn.h>
11
#include <botan/mem_ops.h>
12
#include <botan/rng.h>
13
#include <botan/internal/ct_utils.h>
14
#include <botan/internal/int_utils.h>
15
#include <botan/internal/stl_util.h>
16
17
namespace Botan {
18
19
/*
20
* PKCS1 Pad Operation
21
*/
22
size_t EME_PKCS1v15::pad(std::span<uint8_t> output,
23
                         std::span<const uint8_t> input,
24
                         size_t key_length,
25
0
                         RandomNumberGenerator& rng) const {
26
0
   key_length /= 8;
27
28
0
   if(input.size() > maximum_input_size(key_length * 8)) {
29
0
      throw Invalid_Argument("PKCS1: Input is too large");
30
0
   }
31
32
0
   BufferStuffer stuffer(output);
33
34
0
   const size_t padding_bytes = [&]() {
35
0
      auto d = checked_sub(key_length, input.size() + 2);
36
0
      BOTAN_ASSERT_NOMSG(d.has_value());
37
0
      return *d;
38
0
   }();
39
40
0
   stuffer.append(0x02);
41
0
   for(size_t i = 0; i != padding_bytes; ++i) {
42
0
      stuffer.append(rng.next_nonzero_byte());
43
0
   }
44
0
   stuffer.append(0x00);
45
0
   stuffer.append(input);
46
47
0
   return output.size() - stuffer.remaining_capacity();
48
0
}
49
50
/*
51
* PKCS1 Unpad Operation
52
*/
53
154
CT::Option<size_t> EME_PKCS1v15::unpad(std::span<uint8_t> output, std::span<const uint8_t> input) const {
54
154
   BOTAN_ASSERT_NOMSG(output.size() >= input.size());
55
56
   /*
57
   * RSA decryption pads the ciphertext up to the modulus size, so this only
58
   * occurs with very (!) small keys, or when fuzzing.
59
   *
60
   * 11 bytes == 00,02 + 8 bytes mandatory padding + 00
61
   */
62
154
   if(input.size() < 11) {
63
38
      return {};
64
38
   }
65
66
116
   auto scope = CT::scoped_poison(input);
67
68
116
   CT::Mask<uint8_t> bad_input_m = CT::Mask<uint8_t>::cleared();
69
116
   CT::Mask<uint8_t> seen_zero_m = CT::Mask<uint8_t>::cleared();
70
116
   size_t delim_idx = 2;  // initial 0002
71
72
116
   bad_input_m |= ~CT::Mask<uint8_t>::is_equal(input[0], 0);
73
116
   bad_input_m |= ~CT::Mask<uint8_t>::is_equal(input[1], 2);
74
75
195k
   for(size_t i = 2; i < input.size(); ++i) {
76
194k
      const auto is_zero_m = CT::Mask<uint8_t>::is_zero(input[i]);
77
194k
      delim_idx += seen_zero_m.if_not_set_return(1);
78
194k
      seen_zero_m |= is_zero_m;
79
194k
   }
80
81
   // no zero delim -> bad padding
82
116
   bad_input_m |= ~seen_zero_m;
83
   /*
84
   delim indicates < 8 bytes padding -> bad padding
85
86
   We require 11 here because we are counting also the 00 delim byte
87
   */
88
116
   bad_input_m |= CT::Mask<uint8_t>(CT::Mask<size_t>::is_lt(delim_idx, 11));
89
90
116
   const CT::Choice accept = !(bad_input_m.as_choice());
91
92
116
   return CT::copy_output(accept, output, input, delim_idx);
93
154
}
94
95
/*
96
* Return the max input size for a given key size
97
*/
98
0
size_t EME_PKCS1v15::maximum_input_size(size_t keybits) const {
99
0
   if(keybits / 8 > 10) {
100
0
      return ((keybits / 8) - 10);
101
0
   } else {
102
0
      return 0;
103
0
   }
104
0
}
105
106
}  // namespace Botan