/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 |