8#include <botan/internal/oaep.h>
10#include <botan/exceptn.h>
12#include <botan/internal/ct_utils.h>
13#include <botan/internal/mgf1.h>
14#include <botan/internal/stl_util.h>
21size_t OAEP::pad(std::span<uint8_t> output,
22 std::span<const uint8_t> input,
24 RandomNumberGenerator& rng)
const {
28 throw Invalid_Argument(
"OAEP: Input is too large");
31 const size_t output_size = key_length;
33 output = output.first(output_size);
35 BufferStuffer stuffer(output);
38 rng.randomize(stuffer.next(m_Phash.size()));
39 stuffer.append(m_Phash);
40 stuffer.append(0x00, stuffer.remaining_capacity() - (1 + input.size()));
42 stuffer.append(input);
45 const size_t hlen = m_Phash.size();
47 mgf1_mask(*m_mgf1_hash, output.first(hlen), output.subspan(hlen));
49 mgf1_mask(*m_mgf1_hash, output.subspan(hlen), output.first(hlen));
57CT::Option<size_t> OAEP::unpad(std::span<uint8_t> output, std::span<const uint8_t> input)
const {
89 auto buf = std::span{decoded};
91 const size_t hlen = m_Phash.size();
93 mgf1_mask(*m_mgf1_hash, buf.subspan(hlen), buf.first(hlen));
95 mgf1_mask(*m_mgf1_hash, buf.first(hlen), buf.subspan(hlen));
99 return CT::copy_output(delim.has_value() && has_leading_0, output, buf, delim.value_or(0));
104 if(input.size() < 1 + 2 * phash.size()) {
108 size_t delim_idx = 2 * phash.size();
112 for(uint8_t ib : input.subspan(2 * phash.size())) {
116 const auto add_m = waiting_for_delim & zero_m;
118 bad_input_m |= waiting_for_delim & ~(zero_m | one_m);
120 delim_idx += add_m.if_set_return(1);
122 waiting_for_delim &= zero_m;
126 bad_input_m |= waiting_for_delim;
129 bad_input_m |=
CT::is_not_equal(&input[phash.size()], phash.data(), phash.size());
133 const auto accept = !(bad_input_m.
as_choice());
142 if(keybits / 8 > 2 * m_Phash.size() + 1) {
143 return ((keybits / 8) - 2 * m_Phash.size() - 1);
149OAEP::OAEP(std::unique_ptr<HashFunction> hash, std::string_view P) : m_mgf1_hash(std::move(hash)) {
150 m_Phash = m_mgf1_hash->process(P);
153OAEP::OAEP(std::unique_ptr<HashFunction> hash, std::unique_ptr<HashFunction> mgf1_hash, std::string_view P) :
154 m_mgf1_hash(std::move(mgf1_hash)) {
155 auto phash = std::move(hash);
156 m_Phash = phash->process(P);
#define BOTAN_ASSERT_NOMSG(expr)
static constexpr Mask< T > set()
constexpr CT::Choice as_choice() const
static constexpr Mask< T > is_equal(T x, T y)
static constexpr Mask< T > is_zero(T x)
static constexpr Mask< T > cleared()
OAEP(std::unique_ptr< HashFunction > hash, std::string_view P="")
size_t maximum_input_size(size_t) const override
constexpr auto scoped_poison(const Ts &... xs)
constexpr CT::Mask< T > is_not_equal(const T x[], const T y[], size_t len)
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)
void mgf1_mask(HashFunction &hash, const uint8_t in[], size_t in_len, uint8_t out[], size_t out_len)
CT::Option< size_t > oaep_find_delim(std::span< const uint8_t > input, std::span< const uint8_t > phash)
std::vector< T, secure_allocator< T > > secure_vector