Botan 2.1.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 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/internal/ct_utils.h>
11
12 namespace Botan {
13
14 /*
15 * OAEP Pad Operation
16 */
17 secure_vector<uint8_t> OAEP::pad(const uint8_t in[], size_t in_length,
18 size_t key_length,
19 RandomNumberGenerator& rng) const
20 {
21 key_length /= 8;
22
23 if(in_length > maximum_input_size(key_length * 8))
24 {
25 throw Invalid_Argument("OAEP: Input is too large");
26 }
27
28 secure_vector<uint8_t> out(key_length);
29
30 rng.randomize(out.data(), m_Phash.size());
31
32 buffer_insert(out, m_Phash.size(), m_Phash.data(), m_Phash.size());
33 out[out.size() - in_length - 1] = 0x01;
34 buffer_insert(out, out.size() - in_length, in, in_length);
35
36 mgf1_mask(*m_hash,
37 out.data(), m_Phash.size(),
38 &out[m_Phash.size()], out.size() - m_Phash.size());
39
40 mgf1_mask(*m_hash,
41 &out[m_Phash.size()], out.size() - m_Phash.size(),
42 out.data(), m_Phash.size());
43
44 return out;
45 }
46
47 /*
48 * OAEP Unpad Operation
49 */
50 secure_vector<uint8_t> OAEP::unpad(uint8_t& valid_mask,
51 const uint8_t in[], size_t in_length) const
52 {
53 /*
54 Must be careful about error messages here; if an attacker can
55 distinguish them, it is easy to use the differences as an oracle to
56 find the secret key, as described in "A Chosen Ciphertext Attack on
57 RSA Optimal Asymmetric Encryption Padding (OAEP) as Standardized in
58 PKCS #1 v2.0", James Manger, Crypto 2001
59
60 Also have to be careful about timing attacks! Pointed out by Falko
61 Strenzke.
62
63 According to the standard (Section 7.1.1), the encryptor always
64 creates a message as follows:
65 i. Concatenate a single octet with hexadecimal value 0x00,
66 maskedSeed, and maskedDB to form an encoded message EM of
67 length k octets as
68 EM = 0x00 || maskedSeed || maskedDB.
69 where k is the length of the modulus N.
70 Therefore, the first byte can always be skipped safely.
71 */
72
73 uint8_t skip_first = CT::is_zero<uint8_t>(in[0]) & 0x01;
74
75 secure_vector<uint8_t> input(in + skip_first, in + in_length);
76
77 CT::poison(input.data(), input.size());
78
79 const size_t hlen = m_Phash.size();
80
81 mgf1_mask(*m_hash,
82 &input[hlen], input.size() - hlen,
83 input.data(), hlen);
84
85 mgf1_mask(*m_hash,
86 input.data(), hlen,
87 &input[hlen], input.size() - hlen);
88
89 size_t delim_idx = 2 * hlen;
90 uint8_t waiting_for_delim = 0xFF;
91 uint8_t bad_input = 0;
92
93 for(size_t i = delim_idx; i < input.size(); ++i)
94 {
95 const uint8_t zero_m = CT::is_zero<uint8_t>(input[i]);
96 const uint8_t one_m = CT::is_equal<uint8_t>(input[i], 1);
97
98 const uint8_t add_m = waiting_for_delim & zero_m;
99
100 bad_input |= waiting_for_delim & ~(zero_m | one_m);
101
102 delim_idx += CT::select<uint8_t>(add_m, 1, 0);
103
104 waiting_for_delim &= zero_m;
105 }
106
107 // If we never saw any non-zero byte, then it's not valid input
108 bad_input |= waiting_for_delim;
109 bad_input |= CT::is_equal<uint8_t>(same_mem(&input[hlen], m_Phash.data(), hlen), false);
110
111 CT::unpoison(input.data(), input.size());
112 CT::unpoison(&bad_input, 1);
113 CT::unpoison(&delim_idx, 1);
114
115 valid_mask = ~bad_input;
116
117 secure_vector<uint8_t> output(input.begin() + delim_idx + 1, input.end());
118 CT::cond_zero_mem(bad_input, output.data(), output.size());
119
120 return output;
121 }
122
123 /*
124 * Return the max input size for a given key size
125 */
126 size_t OAEP::maximum_input_size(size_t keybits) const
127 {
128 if(keybits / 8 > 2*m_Phash.size() + 1)
129 return ((keybits / 8) - 2*m_Phash.size() - 1);
130 else
131 return 0;
132 }
133
134 /*
135 * OAEP Constructor
136 */
137 OAEP::OAEP(HashFunction* hash, const std::string& P) : m_hash(hash)
138 {
139 m_Phash = m_hash->process(P);
140 }
141
142 }
Botan::same_mem
bool same_mem(const T *p1, const T *p2, size_t n)
Definition: mem_ops.h:98
Botan::CT::poison
void poison(const T *p, size_t n)
Definition: ct_utils.h:46
Botan::CT::cond_zero_mem
void cond_zero_mem(T cond, T *array, size_t elems)
Definition: ct_utils.h:153
Botan
Definition: alg_id.cpp:13
Botan::HashFunction
Definition: hash.h:19
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::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:133
Botan::OAEP::OAEP
OAEP(HashFunction *hash, const std::string &P="")
Definition: oaep.cpp:137
Botan::CT::unpoison
void unpoison(const T *p, size_t n)
Definition: ct_utils.h:57
Botan::OAEP::maximum_input_size
size_t maximum_input_size(size_t) const override
Definition: oaep.cpp:126
m_hash
std::unique_ptr< HashFunction > m_hash
Definition: tpm.cpp:439
hash
MechanismType hash
Definition: p11_mechanism.cpp:63