8#include <botan/internal/iso9796.h>
10#include <botan/exceptn.h>
12#include <botan/internal/bit_ops.h>
13#include <botan/internal/ct_utils.h>
14#include <botan/internal/fmt.h>
15#include <botan/internal/hash_id.h>
16#include <botan/internal/mgf1.h>
17#include <botan/internal/stl_util.h>
23std::vector<uint8_t> iso9796_encoding(
const std::vector<uint8_t>& msg,
25 std::unique_ptr<HashFunction>& hash,
28 RandomNumberGenerator& rng) {
29 const size_t output_length = (output_bits + 7) / 8;
32 const size_t tLength = (implicit) ? 1 : 2;
34 const size_t HASH_SIZE = hash->output_length();
36 if(output_length <= HASH_SIZE + SALT_SIZE + tLength) {
37 throw Encoding_Error(
"ISO9796-2::encoding_of: Output length is too small");
41 const size_t capacity = output_length - HASH_SIZE - SALT_SIZE - tLength - 1;
44 std::vector<uint8_t> msg1;
45 if(msg.size() > capacity) {
46 msg1 = std::vector<uint8_t>(msg.begin(), msg.begin() + capacity);
47 hash->update(std::span(msg).subspan(capacity));
51 const std::vector<uint8_t> hmsg2 = hash->final_stdvec();
54 const size_t msgLength = msg1.size();
55 const auto salt = rng.random_vec<std::vector<uint8_t>>(SALT_SIZE);
56 hash->update_be(
static_cast<uint64_t
>(msgLength) * 8);
60 const std::vector<uint8_t> H = hash->final_stdvec();
62 std::vector<uint8_t> EM(output_length);
64 BufferStuffer stuffer(EM);
65 stuffer.append(0x00, stuffer.remaining_capacity() - (HASH_SIZE + SALT_SIZE + tLength + msgLength + 1));
71 mgf1_mask(*hash, H.data(), HASH_SIZE, EM.data(), output_length - HASH_SIZE - tLength);
85 throw Encoding_Error(
"ISO9796-2::encoding_of: no hash identifier for " + hash->name());
87 stuffer.append(hash_id);
96bool iso9796_verification(
const std::vector<uint8_t>& const_coded,
97 const std::vector<uint8_t>& raw,
99 std::unique_ptr<HashFunction>& hash,
101 const size_t HASH_SIZE = hash->output_length();
102 const size_t KEY_BYTES = (key_bits + 7) / 8;
104 if(const_coded.size() != KEY_BYTES) {
109 if(const_coded[const_coded.size() - 1] == 0xBC) {
113 if((!const_coded[const_coded.size() - 2]) || (const_coded[const_coded.size() - 2] != hash_id) ||
114 (const_coded[const_coded.size() - 1] != 0xCC)) {
120 std::vector<uint8_t> coded = const_coded;
124 uint8_t* DB = coded.data();
125 const size_t DB_size = coded.size() - HASH_SIZE - tLength;
127 const uint8_t* H = &coded[DB_size];
129 mgf1_mask(*hash, H, HASH_SIZE, DB, DB_size);
134 size_t msg1_offset = 1;
139 for(
size_t j = 0; j < DB_size; ++j) {
143 const auto add_m = waiting_for_delim & is_zero;
145 bad_input |= waiting_for_delim & ~(is_zero | is_one);
146 msg1_offset += add_m.if_set_return(1);
148 waiting_for_delim &= is_zero;
152 bad_input |= waiting_for_delim;
161 std::vector<uint8_t> msg1(coded.begin() + msg1_offset, coded.end() - tLength - HASH_SIZE - SALT_SIZE);
162 std::vector<uint8_t> salt(coded.begin() + msg1_offset + msg1.size(), coded.end() - tLength - HASH_SIZE);
165 const size_t capacity = (key_bits - 2 + 7) / 8 - HASH_SIZE - SALT_SIZE - tLength - 1;
166 std::vector<uint8_t> msg1raw;
167 if(raw.size() > capacity) {
168 msg1raw = std::vector<uint8_t>(raw.begin(), raw.begin() + capacity);
169 hash->update(std::span(raw).subspan(capacity));
173 const std::vector<uint8_t> hmsg2 = hash->final_stdvec();
175 const uint64_t msg1rawLength = msg1raw.size();
176 hash->update_be(msg1rawLength * 8);
177 hash->update(msg1raw);
180 std::vector<uint8_t> H3 = hash->final_stdvec();
183 const uint64_t msgLength = msg1.size();
184 hash->update_be(msgLength * 8);
188 std::vector<uint8_t> H2 = hash->final_stdvec();
194 return (bad_input.as_bool() ==
false);
203void ISO_9796_DS2::update(
const uint8_t input[],
size_t length) {
205 m_msg_buffer.insert(m_msg_buffer.end(), input, input + length);
211std::vector<uint8_t> ISO_9796_DS2::raw_data() {
212 std::vector<uint8_t> retbuffer = m_msg_buffer;
213 m_msg_buffer.clear();
220std::vector<uint8_t> ISO_9796_DS2::encoding_of(
const std::vector<uint8_t>& msg,
222 RandomNumberGenerator& rng) {
223 return iso9796_encoding(msg, output_bits, m_hash, m_SALT_SIZE, m_implicit, rng);
229bool ISO_9796_DS2::verify(
const std::vector<uint8_t>& const_coded,
const std::vector<uint8_t>& raw,
size_t key_bits) {
230 return iso9796_verification(const_coded, raw, key_bits, m_hash, m_SALT_SIZE);
237 return fmt(
"ISO_9796_DS2({},{},{})", m_hash->name(), (m_implicit ?
"imp" :
"exp"), m_SALT_SIZE);
244void ISO_9796_DS3::update(
const uint8_t input[],
size_t length) {
246 m_msg_buffer.insert(m_msg_buffer.end(), input, input + length);
252std::vector<uint8_t> ISO_9796_DS3::raw_data() {
253 std::vector<uint8_t> retbuffer = m_msg_buffer;
254 m_msg_buffer.clear();
261std::vector<uint8_t> ISO_9796_DS3::encoding_of(
const std::vector<uint8_t>& msg,
263 RandomNumberGenerator& rng) {
264 return iso9796_encoding(msg, output_bits, m_hash, 0, m_implicit, rng);
270bool ISO_9796_DS3::verify(
const std::vector<uint8_t>& const_coded,
const std::vector<uint8_t>& raw,
size_t key_bits) {
271 return iso9796_verification(const_coded, raw, key_bits, m_hash, 0);
278 return fmt(
"ISO_9796_DS3({},{})", m_hash->name(), (m_implicit ?
"imp" :
"exp"));
#define BOTAN_ASSERT_NOMSG(expr)
static constexpr Mask< T > set()
static constexpr Mask< T > expand(T v)
static constexpr Mask< T > is_equal(T x, T y)
static constexpr Mask< T > is_lt(T x, T y)
static constexpr Mask< T > is_zero(T x)
static constexpr Mask< T > cleared()
std::string name() const override
std::string name() const override
constexpr CT::Mask< T > is_not_equal(const T x[], const T y[], size_t len)
constexpr void unpoison(const T *p, size_t n)
constexpr void poison(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)
std::string fmt(std::string_view format, const T &... args)
uint8_t ieee1363_hash_id(std::string_view name)