Botan 3.6.0
Crypto and TLS for C&
eme_pkcs.cpp
Go to the documentation of this file.
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
17namespace Botan {
18
19/*
20* PKCS1 Pad Operation
21*/
22size_t EME_PKCS1v15::pad(std::span<uint8_t> output,
23 std::span<const uint8_t> input,
24 size_t key_length,
25 RandomNumberGenerator& rng) const {
26 key_length /= 8;
27
28 if(input.size() > maximum_input_size(key_length * 8)) {
29 throw Invalid_Argument("PKCS1: Input is too large");
30 }
31
32 BufferStuffer stuffer(output);
33
34 const size_t padding_bytes = [&]() {
35 auto d = checked_sub(key_length, input.size() + 2);
36 BOTAN_ASSERT_NOMSG(d.has_value());
37 return *d;
38 }();
39
40 stuffer.append(0x02);
41 for(size_t i = 0; i != padding_bytes; ++i) {
42 stuffer.append(rng.next_nonzero_byte());
43 }
44 stuffer.append(0x00);
45 stuffer.append(input);
46
47 return output.size() - stuffer.remaining_capacity();
48}
49
50/*
51* PKCS1 Unpad Operation
52*/
53CT::Option<size_t> EME_PKCS1v15::unpad(std::span<uint8_t> output, std::span<const uint8_t> input) const {
54 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 if(input.size() < 11) {
63 return {};
64 }
65
66 auto scope = CT::scoped_poison(input);
67
68 CT::Mask<uint8_t> bad_input_m = CT::Mask<uint8_t>::cleared();
69 CT::Mask<uint8_t> seen_zero_m = CT::Mask<uint8_t>::cleared();
70 size_t delim_idx = 2; // initial 0002
71
72 bad_input_m |= ~CT::Mask<uint8_t>::is_equal(input[0], 0);
73 bad_input_m |= ~CT::Mask<uint8_t>::is_equal(input[1], 2);
74
75 for(size_t i = 2; i < input.size(); ++i) {
76 const auto is_zero_m = CT::Mask<uint8_t>::is_zero(input[i]);
77 delim_idx += seen_zero_m.if_not_set_return(1);
78 seen_zero_m |= is_zero_m;
79 }
80
81 // no zero delim -> bad padding
82 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 bad_input_m |= CT::Mask<uint8_t>(CT::Mask<size_t>::is_lt(delim_idx, 11));
89
90 const CT::Choice accept = !(bad_input_m.as_choice());
91
92 return CT::copy_output(accept, output, input, delim_idx);
93}
94
95/*
96* Return the max input size for a given key size
97*/
98size_t EME_PKCS1v15::maximum_input_size(size_t keybits) const {
99 if(keybits / 8 > 10) {
100 return ((keybits / 8) - 10);
101 } else {
102 return 0;
103 }
104}
105
106} // namespace Botan
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:59
static constexpr Mask< T > is_lt(T x, T y)
Definition ct_utils.h:442
static constexpr Mask< T > is_zero(T x)
Definition ct_utils.h:429
static constexpr Mask< T > cleared()
Definition ct_utils.h:384
constexpr auto scoped_poison(const Ts &... xs)
Definition ct_utils.h:216
BOTAN_TEST_API CT::Option< size_t > copy_output(CT::Choice accept, std::span< uint8_t > output, std::span< const uint8_t > input, size_t offset)
Definition ct_utils.cpp:13
constexpr std::optional< T > checked_sub(T a, T b)
Definition int_utils.h:28