8#include <botan/iso9796.h>
10#include <botan/exceptn.h>
11#include <botan/mgf1.h>
12#include <botan/hash_id.h>
13#include <botan/internal/bit_ops.h>
14#include <botan/internal/ct_utils.h>
20secure_vector<uint8_t> iso9796_encoding(
const secure_vector<uint8_t>& msg,
22 std::unique_ptr<HashFunction>&
hash,
25 RandomNumberGenerator& rng)
27 const size_t output_length = (output_bits + 7) / 8;
35 const size_t HASH_SIZE =
hash->output_length();
37 if(output_length <= HASH_SIZE + SALT_SIZE + tLength)
39 throw Encoding_Error(
"ISO9796-2::encoding_of: Output length is too small");
43 const size_t capacity = output_length - HASH_SIZE - SALT_SIZE - tLength - 1;
46 secure_vector<uint8_t> msg1;
47 secure_vector<uint8_t> msg2;
48 if(msg.size() > capacity)
50 msg1 = secure_vector<uint8_t>(msg.begin(), msg.begin() + capacity);
51 msg2 = secure_vector<uint8_t>(msg.begin() + capacity, msg.end());
61 const size_t msgLength = msg1.size();
62 secure_vector<uint8_t> salt = rng.random_vec(SALT_SIZE);
63 hash->update_be(
static_cast<uint64_t
>(msgLength) * 8);
67 secure_vector<uint8_t> H =
hash->final();
69 secure_vector<uint8_t> EM(output_length);
72 const size_t offset = output_length - HASH_SIZE - SALT_SIZE - tLength - msgLength - 1;
81 output_length - HASH_SIZE - tLength);
89 throw Encoding_Error(
"ISO9796-2::encoding_of: no hash identifier for " +
hash->name());
91 EM[output_length - 1] = 0xCC;
92 EM[output_length - 2] = hash_id;
97 EM[output_length - 1] = 0xBC;
105bool iso9796_verification(
const secure_vector<uint8_t>& const_coded,
106 const secure_vector<uint8_t>& raw,
size_t key_bits, std::unique_ptr<HashFunction>&
hash,
size_t SALT_SIZE)
108 const size_t HASH_SIZE =
hash->output_length();
109 const size_t KEY_BYTES = (key_bits + 7) / 8;
111 if(const_coded.size() != KEY_BYTES)
117 if(const_coded[const_coded.size() - 1] == 0xBC)
124 if((!const_coded[const_coded.size() - 2]) || (const_coded[const_coded.size() - 2] != hash_id) ||
125 (const_coded[const_coded.size() - 1] != 0xCC))
132 secure_vector<uint8_t> coded = const_coded;
136 uint8_t* DB = coded.data();
137 const size_t DB_size = coded.size() - HASH_SIZE - tLength;
139 const uint8_t* H = &coded[DB_size];
146 size_t msg1_offset = 1;
151 for(
size_t j = 0; j < DB_size; ++j)
156 const auto add_m = waiting_for_delim & is_zero;
158 bad_input |= waiting_for_delim & ~(is_zero | is_one);
159 msg1_offset += add_m.if_set_return(1);
161 waiting_for_delim &= is_zero;
165 bad_input |= waiting_for_delim;
174 secure_vector<uint8_t> msg1(coded.begin() + msg1_offset,
175 coded.end() - tLength - HASH_SIZE - SALT_SIZE);
176 secure_vector<uint8_t> salt(coded.begin() + msg1_offset + msg1.size(),
177 coded.end() - tLength - HASH_SIZE);
180 const size_t capacity = (key_bits - 2 + 7) / 8 - HASH_SIZE - SALT_SIZE - tLength - 1;
181 secure_vector<uint8_t> msg1raw;
182 secure_vector<uint8_t> msg2;
183 if(raw.size() > capacity)
185 msg1raw = secure_vector<uint8_t> (raw.begin(), raw.begin() + capacity);
186 msg2 = secure_vector<uint8_t> (raw.begin() + capacity, raw.end());
193 msg2 =
hash->final();
195 const uint64_t msg1rawLength = msg1raw.size();
196 hash->update_be(msg1rawLength * 8);
197 hash->update(msg1raw);
200 secure_vector<uint8_t> H3 =
hash->final();
203 const uint64_t msgLength = msg1.size();
204 hash->update_be(msgLength * 8);
208 secure_vector<uint8_t> H2 =
hash->final();
214 return (bad_input.is_set() ==
false);
221 return new ISO_9796_DS2(m_hash->clone(), m_implicit, m_SALT_SIZE);
228void ISO_9796_DS2::update(
const uint8_t input[],
size_t length)
231 m_msg_buffer.insert(m_msg_buffer.end(), input, input+length);
237secure_vector<uint8_t> ISO_9796_DS2::raw_data()
239 secure_vector<uint8_t> retbuffer = m_msg_buffer;
240 m_msg_buffer.clear();
247secure_vector<uint8_t> ISO_9796_DS2::encoding_of(
const secure_vector<uint8_t>& msg,
249 RandomNumberGenerator& rng)
251 return iso9796_encoding(msg, output_bits, m_hash, m_SALT_SIZE, m_implicit, rng);
257bool ISO_9796_DS2::verify(
const secure_vector<uint8_t>& const_coded,
258 const secure_vector<uint8_t>& raw,
size_t key_bits)
260 return iso9796_verification(const_coded, raw, key_bits, m_hash, m_SALT_SIZE);
268 return "ISO_9796_DS2(" + m_hash->name() +
","
269 + (m_implicit ?
"imp" :
"exp") +
"," +
std::to_string(m_SALT_SIZE) +
")";
281void ISO_9796_DS3::update(
const uint8_t input[],
size_t length)
284 m_msg_buffer.insert(m_msg_buffer.end(), input, input+length);
290secure_vector<uint8_t> ISO_9796_DS3::raw_data()
292 secure_vector<uint8_t> retbuffer = m_msg_buffer;
293 m_msg_buffer.clear();
300secure_vector<uint8_t> ISO_9796_DS3::encoding_of(
const secure_vector<uint8_t>& msg,
301 size_t output_bits, RandomNumberGenerator& rng)
303 return iso9796_encoding(msg, output_bits, m_hash, 0, m_implicit, rng);
309bool ISO_9796_DS3::verify(
const secure_vector<uint8_t>& const_coded,
310 const secure_vector<uint8_t>& raw,
size_t key_bits)
312 return iso9796_verification(const_coded, raw, key_bits, m_hash, 0);
319 return "ISO_9796_DS3(" + m_hash->name() +
"," +
320 (m_implicit ?
"imp" :
"exp") +
")";
static Mask< T > is_equal(T x, T y)
static Mask< T > is_zero(T x)
static Mask< T > expand(T v)
static Mask< T > is_lt(T x, T y)
static Mask< T > cleared()
ISO_9796_DS2(HashFunction *hash, bool implicit=false)
std::string name() const override
ISO_9796_DS3(HashFunction *hash, bool implicit=false)
std::string name() const override
std::string to_string(const BER_Object &obj)
void poison(const T *p, size_t n)
void unpoison(const T *p, size_t n)
void mgf1_mask(HashFunction &hash, const uint8_t in[], size_t in_len, uint8_t out[], size_t out_len)
size_t buffer_insert(std::vector< T, Alloc > &buf, size_t buf_offset, const T input[], size_t input_length)
uint8_t ct_compare_u8(const uint8_t x[], const uint8_t y[], size_t len)
uint8_t ieee1363_hash_id(const std::string &name)