9#include <botan/internal/iso9796.h> 
   11#include <botan/exceptn.h> 
   12#include <botan/hash.h> 
   14#include <botan/internal/ct_utils.h> 
   15#include <botan/internal/fmt.h> 
   16#include <botan/internal/hash_id.h> 
   17#include <botan/internal/mgf1.h> 
   24                                  std::span<const uint8_t> msg1,
 
   25                                  std::span<const uint8_t> hmsg2,
 
   26                                  std::span<const uint8_t> salt) {
 
   28   hash.update_be(
static_cast<uint64_t
>(msg1.size()) * 8);
 
   32   return hash.final_stdvec();
 
   35std::vector<uint8_t> iso9796_encoding(std::span<const uint8_t> msg,
 
   37                                      std::unique_ptr<HashFunction>& hash,
 
   41   const size_t output_length = (output_bits + 7) / 8;
 
   44   const size_t trailer_len = (implicit) ? 1 : 2;
 
   46   const size_t hash_len = hash->output_length();
 
   48   if(output_length <= hash_len + salt_len + trailer_len) {
 
   49      throw Encoding_Error(
"ISO9796-2::encoding_of: Output length is too small");
 
   53   const size_t capacity = output_length - hash_len - salt_len - trailer_len - 1;
 
   56   const size_t msg1_len = std::min(capacity, msg.size());
 
   57   const auto msg1 = msg.first(msg1_len);    
 
   58   const auto msg2 = msg.subspan(msg1_len);  
 
   60   const auto hmsg2 = hash->process<std::vector<uint8_t>>(msg2);
 
   61   const auto salt = rng.random_vec<std::vector<uint8_t>>(salt_len);
 
   63   const auto H = iso9796_hash(*hash, msg1, hmsg2, salt);
 
   65   std::vector<uint8_t> EM(output_length);
 
   68   stuffer.append(0x00, stuffer.remaining_capacity() - (hash_len + salt_len + trailer_len + msg1_len + 1));
 
   74   mgf1_mask(*hash, H.data(), hash_len, EM.data(), output_length - hash_len - trailer_len);
 
   88         throw Encoding_Error(
"ISO-9796: no hash identifier for " + hash->name());
 
   90      stuffer.append(hash_id);
 
   99bool iso9796_verification(std::span<const uint8_t> repr,
 
  100                          std::span<const uint8_t> raw,
 
  102                          std::unique_ptr<HashFunction>& hash,
 
  104   if(repr.size() != (key_bits + 7) / 8) {
 
  109   const uint8_t last = repr[repr.size() - 1];
 
  111   if(last != 0xBC && last != 0xCC) {
 
  115   const size_t trailer_len = last == 0xBC ? 1 : 2;
 
  117   if(trailer_len == 2) {
 
  120         throw Decoding_Error(
"ISO-9796: no hash identifier for " + hash->name());
 
  123      const uint8_t trailer_0 = repr[repr.size() - 2];
 
  124      const uint8_t trailer_1 = repr[repr.size() - 1];
 
  126      if(trailer_0 != hash_id || trailer_1 != 0xCC) {
 
  131   const size_t hash_len = hash->output_length();
 
  133   if(repr.size() < hash_len + trailer_len + salt_len) {
 
  137   std::vector<uint8_t> coded(repr.begin(), repr.end());
 
  141   uint8_t* DB = coded.data();
 
  142   const size_t DB_size = coded.size() - hash_len - trailer_len;
 
  144   const uint8_t* H = &coded[DB_size];
 
  146   mgf1_mask(*hash, H, hash_len, DB, DB_size);
 
  151   size_t msg1_offset = 1;
 
  156   for(
size_t j = 0; j < DB_size; ++j) {
 
  160      const auto add_m = waiting_for_delim & is_zero;
 
  162      bad_input |= waiting_for_delim & ~(is_zero | is_one);
 
  163      msg1_offset += add_m.if_set_return(1);
 
  165      waiting_for_delim &= is_zero;
 
  169   bad_input |= waiting_for_delim;
 
  171   const auto bad_offset = 
CT::Mask<size_t>::is_lt(coded.size(), trailer_len + hash_len + msg1_offset + salt_len);
 
  180   const size_t msg1_len = coded.size() - (trailer_len + hash_len + msg1_offset + salt_len);
 
  182   const auto msg1 = std::span(coded).subspan(msg1_offset, msg1_len);
 
  183   const auto salt = std::span(coded).subspan(msg1_offset + msg1.size(), salt_len);
 
  186   const size_t capacity = (key_bits - 2 + 7) / 8 - hash_len - salt_len - trailer_len - 1;
 
  188   std::span<const uint8_t> msg1raw = raw;
 
  189   if(msg1raw.size() > capacity) {
 
  190      hash->update(msg1raw.subspan(capacity));
 
  191      msg1raw = msg1raw.first(capacity);
 
  194   const auto hmsg2 = hash->final_stdvec();
 
  197   const auto H2 = iso9796_hash(*hash, msg1, hmsg2, salt);
 
  204   bad_input |= 
~CT::is_equal(msg1.data(), msg1raw.data(), std::min(msg1.size(), msg1raw.size()));
 
  207   return (bad_input.as_bool() == 
false);
 
  216void ISO_9796_DS2::update(
const uint8_t input[], 
size_t length) {
 
  218   m_msg_buffer.insert(m_msg_buffer.end(), input, input + length);
 
  225   std::vector<uint8_t> retbuffer = m_msg_buffer;
 
  226   m_msg_buffer.clear();
 
  233std::vector<uint8_t> ISO_9796_DS2::encoding_of(std::span<const uint8_t> msg,
 
  236   return iso9796_encoding(msg, output_bits, m_hash, m_salt_len, m_implicit, rng);
 
  242bool ISO_9796_DS2::verify(std::span<const uint8_t> repr, std::span<const uint8_t> raw, 
size_t key_bits) {
 
  243   return iso9796_verification(repr, raw, key_bits, m_hash, m_salt_len);
 
  247   return m_hash->name();
 
 
  254   return fmt(
"ISO_9796_DS2({},{},{})", m_hash->name(), (m_implicit ? 
"imp" : 
"exp"), m_salt_len);
 
 
  261void ISO_9796_DS3::update(
const uint8_t input[], 
size_t length) {
 
  263   m_msg_buffer.insert(m_msg_buffer.end(), input, input + length);
 
  270   std::vector<uint8_t> retbuffer = m_msg_buffer;
 
  271   m_msg_buffer.clear();
 
  278std::vector<uint8_t> ISO_9796_DS3::encoding_of(std::span<const uint8_t> msg,
 
  281   return iso9796_encoding(msg, output_bits, m_hash, 0, m_implicit, rng);
 
  287bool ISO_9796_DS3::verify(std::span<const uint8_t> repr, std::span<const uint8_t> raw, 
size_t key_bits) {
 
  288   return iso9796_verification(repr, raw, key_bits, m_hash, 0);
 
  292   return m_hash->name();
 
 
  299   return fmt(
"ISO_9796_DS3({},{})", m_hash->name(), (m_implicit ? 
"imp" : 
"exp"));
 
 
#define BOTAN_ASSERT_NOMSG(expr)
 
Helper class to ease in-place marshalling of concatenated fixed-length values.
 
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 hash_function() const override
 
std::string hash_function() const override
 
std::string name() const override
 
virtual std::vector< uint8_t > raw_data()=0
 
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)