Botan 2.13.0 Crypto and TLS for C++11

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

oaep.cpp
Go to the documentation of this file.
1 /*
2 * OAEP
3 * (C) 1999-2010,2015,2018 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7
8 #include <botan/oaep.h>
9 #include <botan/mgf1.h>
10 #include <botan/exceptn.h>
11 #include <botan/rng.h>
12 #include <botan/internal/ct_utils.h>
13
14 namespace Botan {
15
16 /*
17 * OAEP Pad Operation
18 */
19 secure_vector<uint8_t> OAEP::pad(const uint8_t in[], size_t in_length,
20 size_t key_length,
21 RandomNumberGenerator& rng) const
22 {
23 key_length /= 8;
24
25 if(in_length > maximum_input_size(key_length * 8))
26 {
27 throw Invalid_Argument("OAEP: Input is too large");
28 }
29
30 secure_vector<uint8_t> out(key_length);
31
32 rng.randomize(out.data(), m_Phash.size());
33
34 buffer_insert(out, m_Phash.size(), m_Phash.data(), m_Phash.size());
35 out[out.size() - in_length - 1] = 0x01;
36 buffer_insert(out, out.size() - in_length, in, in_length);
37
38 mgf1_mask(*m_mgf1_hash,
39 out.data(), m_Phash.size(),
40 &out[m_Phash.size()], out.size() - m_Phash.size());
41
42 mgf1_mask(*m_mgf1_hash,
43 &out[m_Phash.size()], out.size() - m_Phash.size(),
44 out.data(), m_Phash.size());
45
46 return out;
47 }
48
49 /*
50 * OAEP Unpad Operation
51 */
52 secure_vector<uint8_t> OAEP::unpad(uint8_t& valid_mask,
53 const uint8_t in[], size_t in_length) const
54 {
55 /*
56 Must be careful about error messages here; if an attacker can
57 distinguish them, it is easy to use the differences as an oracle to
58 find the secret key, as described in "A Chosen Ciphertext Attack on
59 RSA Optimal Asymmetric Encryption Padding (OAEP) as Standardized in
60 PKCS #1 v2.0", James Manger, Crypto 2001
61
62 Also have to be careful about timing attacks! Pointed out by Falko
63 Strenzke.
64
65 According to the standard (Section 7.1.1), the encryptor always
66 creates a message as follows:
67 i. Concatenate a single octet with hexadecimal value 0x00,
68 maskedSeed, and maskedDB to form an encoded message EM of
69 length k octets as
70 EM = 0x00 || maskedSeed || maskedDB.
71 where k is the length of the modulus N.
72 Therefore, the first byte can always be skipped safely.
73 */
74
75 const uint8_t skip_first = CT::Mask<uint8_t>::is_zero(in[0]).if_set_return(1);
76
77 secure_vector<uint8_t> input(in + skip_first, in + in_length);
78
79 const size_t hlen = m_Phash.size();
80
81 mgf1_mask(*m_mgf1_hash,
82 &input[hlen], input.size() - hlen,
83 input.data(), hlen);
84
85 mgf1_mask(*m_mgf1_hash,
86 input.data(), hlen,
87 &input[hlen], input.size() - hlen);
88
89 return oaep_find_delim(valid_mask, input.data(), input.size(), m_Phash);
90 }
91
92 secure_vector<uint8_t>
93 oaep_find_delim(uint8_t& valid_mask,
94 const uint8_t input[], size_t input_len,
95 const secure_vector<uint8_t>& Phash)
96 {
97 const size_t hlen = Phash.size();
98
99 // Too short to be valid, reject immediately
100 if(input_len < 1 + 2*hlen)
101 {
102 return secure_vector<uint8_t>();
103 }
104
105 CT::poison(input, input_len);
106
107 size_t delim_idx = 2 * hlen;
108 CT::Mask<uint8_t> waiting_for_delim = CT::Mask<uint8_t>::set();
109 CT::Mask<uint8_t> bad_input_m = CT::Mask<uint8_t>::cleared();
110
111 for(size_t i = delim_idx; i < input_len; ++i)
112 {
113 const auto zero_m = CT::Mask<uint8_t>::is_zero(input[i]);
114 const auto one_m = CT::Mask<uint8_t>::is_equal(input[i], 1);
115
116 const auto add_m = waiting_for_delim & zero_m;
117
118 bad_input_m |= waiting_for_delim & ~(zero_m | one_m);
119
120 delim_idx += add_m.if_set_return(1);
121
122 waiting_for_delim &= zero_m;
123 }
124
125 // If we never saw any non-zero byte, then it's not valid input
126 bad_input_m |= waiting_for_delim;
127 bad_input_m |= CT::Mask<uint8_t>::is_zero(ct_compare_u8(&input[hlen], Phash.data(), hlen));
128
129 delim_idx += 1;
130
131 valid_mask = (~bad_input_m).unpoisoned_value();
132 const secure_vector<uint8_t> output = CT::copy_output(bad_input_m, input, input_len, delim_idx);
133
134 CT::unpoison(input, input_len);
135
136 return output;
137 }
138
139 /*
140 * Return the max input size for a given key size
141 */
142 size_t OAEP::maximum_input_size(size_t keybits) const
143 {
144 if(keybits / 8 > 2*m_Phash.size() + 1)
145 return ((keybits / 8) - 2*m_Phash.size() - 1);
146 else
147 return 0;
148 }
149
150 /*
151 * OAEP Constructor
152 */
153 OAEP::OAEP(HashFunction* hash, const std::string& P) : m_mgf1_hash(hash)
154 {
155 m_Phash = m_mgf1_hash->process(P);
156 }
157
158 OAEP::OAEP(HashFunction* hash,
159 HashFunction* mgf1_hash,
160 const std::string& P) : m_mgf1_hash(mgf1_hash)
161 {
162 std::unique_ptr<HashFunction> phash(hash); // takes ownership
163 m_Phash = phash->process(P);
164 }
165
166 }
Botan::CT::Mask::cleared
static Mask< T > cleared()
Definition: ct_utils.h:115
Botan::CT::Mask
Definition: ct_utils.h:87
Botan::CT::poison
void poison(const T *p, size_t n)
Definition: ct_utils.h:48
Botan::CT::Mask::if_set_return
T if_set_return(T x) const
Definition: ct_utils.h:248
Botan::secure_vector
std::vector< T, secure_allocator< T >> secure_vector
Definition: secmem.h:65
Botan::ct_compare_u8
uint8_t ct_compare_u8(const uint8_t x[], const uint8_t y[], size_t len)
Definition: mem_ops.cpp:56
Botan::CT::copy_output
secure_vector< uint8_t > copy_output(CT::Mask< uint8_t > bad_input, const uint8_t input[], size_t input_length, size_t offset)
Definition: ct_utils.cpp:13
Botan
Definition: alg_id.cpp:13
Botan::HashFunction
Definition: hash.h:20
Botan::buffer_insert
size_t buffer_insert(std::vector< T, Alloc > &buf, size_t buf_offset, const T input[], size_t input_length)
Definition: secmem.h:80
Botan::OAEP::OAEP
OAEP(HashFunction *hash, const std::string &P="")
Definition: oaep.cpp:153
Botan::CT::unpoison
void unpoison(const T *p, size_t n)
Definition: ct_utils.h:59
Botan::CT::Mask::set
static Mask< T > set()
Definition: ct_utils.h:107
Botan::mgf1_mask
void mgf1_mask(HashFunction &hash, const uint8_t in[], size_t in_len, uint8_t out[], size_t out_len)
Definition: mgf1.cpp:14
Botan::OAEP::maximum_input_size
size_t maximum_input_size(size_t) const override
Definition: oaep.cpp:142
Botan::oaep_find_delim
secure_vector< uint8_t > oaep_find_delim(uint8_t &valid_mask, const uint8_t input[], size_t input_len, const secure_vector< uint8_t > &Phash)
Definition: oaep.cpp:93
Botan::CT::Mask::is_zero
static Mask< T > is_zero(T x)
Definition: ct_utils.h:141
Botan::CT::Mask::is_equal
static Mask< T > is_equal(T x, T y)
Definition: ct_utils.h:149
hash
MechanismType hash
Definition: p11_mechanism.cpp:64