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/hash_id.h>
15#include <botan/internal/mgf1.h>
16#include <botan/internal/stl_util.h>
22std::vector<uint8_t> iso9796_encoding(
const std::vector<uint8_t>& msg,
24 std::unique_ptr<HashFunction>& hash,
27 RandomNumberGenerator& rng) {
28 const size_t output_length = (output_bits + 7) / 8;
31 const size_t tLength = (implicit) ? 1 : 2;
33 const size_t HASH_SIZE = hash->output_length();
35 if(output_length <= HASH_SIZE + SALT_SIZE + tLength) {
36 throw Encoding_Error(
"ISO9796-2::encoding_of: Output length is too small");
40 const size_t capacity = output_length - HASH_SIZE - SALT_SIZE - tLength - 1;
43 std::vector<uint8_t> msg1;
44 if(msg.size() > capacity) {
45 msg1 = std::vector<uint8_t>(msg.begin(), msg.begin() + capacity);
46 hash->update(std::span(msg).subspan(capacity));
50 const std::vector<uint8_t> hmsg2 = hash->final_stdvec();
53 const size_t msgLength = msg1.size();
54 const auto salt = rng.random_vec<std::vector<uint8_t>>(SALT_SIZE);
55 hash->update_be(
static_cast<uint64_t
>(msgLength) * 8);
59 const std::vector<uint8_t> H = hash->final_stdvec();
61 std::vector<uint8_t> EM(output_length);
63 BufferStuffer stuffer(EM);
64 stuffer.append(0x00, stuffer.remaining_capacity() - (HASH_SIZE + SALT_SIZE + tLength + msgLength + 1));
70 mgf1_mask(*hash, H.data(), HASH_SIZE, EM.data(), output_length - HASH_SIZE - tLength);
84 throw Encoding_Error(
"ISO9796-2::encoding_of: no hash identifier for " + hash->name());
86 stuffer.append(hash_id);
95bool iso9796_verification(
const std::vector<uint8_t>& const_coded,
96 const std::vector<uint8_t>& raw,
98 std::unique_ptr<HashFunction>& hash,
100 const size_t HASH_SIZE = hash->output_length();
101 const size_t KEY_BYTES = (key_bits + 7) / 8;
103 if(const_coded.size() != KEY_BYTES) {
108 if(const_coded[const_coded.size() - 1] == 0xBC) {
112 if((!const_coded[const_coded.size() - 2]) || (const_coded[const_coded.size() - 2] != hash_id) ||
113 (const_coded[const_coded.size() - 1] != 0xCC)) {
119 std::vector<uint8_t> coded = const_coded;
123 uint8_t* DB = coded.data();
124 const size_t DB_size = coded.size() - HASH_SIZE - tLength;
126 const uint8_t* H = &coded[DB_size];
128 mgf1_mask(*hash, H, HASH_SIZE, DB, DB_size);
133 size_t msg1_offset = 1;
138 for(
size_t j = 0; j < DB_size; ++j) {
142 const auto add_m = waiting_for_delim & is_zero;
144 bad_input |= waiting_for_delim & ~(is_zero | is_one);
145 msg1_offset += add_m.if_set_return(1);
147 waiting_for_delim &= is_zero;
151 bad_input |= waiting_for_delim;
160 std::vector<uint8_t> msg1(coded.begin() + msg1_offset, coded.end() - tLength - HASH_SIZE - SALT_SIZE);
161 std::vector<uint8_t> salt(coded.begin() + msg1_offset + msg1.size(), coded.end() - tLength - HASH_SIZE);
164 const size_t capacity = (key_bits - 2 + 7) / 8 - HASH_SIZE - SALT_SIZE - tLength - 1;
165 std::vector<uint8_t> msg1raw;
166 if(raw.size() > capacity) {
167 msg1raw = std::vector<uint8_t>(raw.begin(), raw.begin() + capacity);
168 hash->update(std::span(raw).subspan(capacity));
172 const std::vector<uint8_t> hmsg2 = hash->final_stdvec();
174 const uint64_t msg1rawLength = msg1raw.size();
175 hash->update_be(msg1rawLength * 8);
176 hash->update(msg1raw);
179 std::vector<uint8_t> H3 = hash->final_stdvec();
182 const uint64_t msgLength = msg1.size();
183 hash->update_be(msgLength * 8);
187 std::vector<uint8_t> H2 = hash->final_stdvec();
193 return (bad_input.as_bool() ==
false);
202void ISO_9796_DS2::update(
const uint8_t input[],
size_t length) {
204 m_msg_buffer.insert(m_msg_buffer.end(), input, input + length);
210std::vector<uint8_t> ISO_9796_DS2::raw_data() {
211 std::vector<uint8_t> retbuffer = m_msg_buffer;
212 m_msg_buffer.clear();
219std::vector<uint8_t> ISO_9796_DS2::encoding_of(
const std::vector<uint8_t>& msg,
221 RandomNumberGenerator& rng) {
222 return iso9796_encoding(msg, output_bits, m_hash, m_SALT_SIZE, m_implicit, rng);
228bool ISO_9796_DS2::verify(
const std::vector<uint8_t>& const_coded,
const std::vector<uint8_t>& raw,
size_t key_bits) {
229 return iso9796_verification(const_coded, raw, key_bits, m_hash, m_SALT_SIZE);
236 return "ISO_9796_DS2(" + m_hash->name() +
"," + (m_implicit ?
"imp" :
"exp") +
"," + std::to_string(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 "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)
uint8_t ieee1363_hash_id(std::string_view name)