Beispiel #1
0
//static
CPUID::Endian_status CPUID::runtime_check_endian()
   {
   // Check runtime endian
   const uint32_t endian32 = 0x01234567;
   const uint8_t* e8 = reinterpret_cast<const uint8_t*>(&endian32);

   Endian_status endian = ENDIAN_UNKNOWN;

   if(e8[0] == 0x01 && e8[1] == 0x23 && e8[2] == 0x45 && e8[3] == 0x67)
      {
      endian = ENDIAN_BIG;
      }
   else if(e8[0] == 0x67 && e8[1] == 0x45 && e8[2] == 0x23 && e8[3] == 0x01)
      {
      endian = ENDIAN_LITTLE;
      }
   else
      {
      throw Internal_Error("Unexpected endian at runtime, neither big nor little");
      }

   // If we were compiled with a known endian, verify it matches at runtime
#if defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN)
   BOTAN_ASSERT(endian == ENDIAN_LITTLE, "Build and runtime endian match");
#elif defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN)
   BOTAN_ASSERT(endian == ENDIAN_BIG, "Build and runtime endian match");
#endif

   return endian;
   }
Beispiel #2
0
void Threefish_512::encrypt_n(const byte in[], byte out[], size_t blocks) const
   {
   BOTAN_ASSERT(m_K.size() == 9, "Key was set");
   BOTAN_ASSERT(m_T.size() == 3, "Tweak was set");

   for(size_t i = 0; i != blocks; ++i)
      {
      u64bit X0 = load_le<u64bit>(in, 0);
      u64bit X1 = load_le<u64bit>(in, 1);
      u64bit X2 = load_le<u64bit>(in, 2);
      u64bit X3 = load_le<u64bit>(in, 3);
      u64bit X4 = load_le<u64bit>(in, 4);
      u64bit X5 = load_le<u64bit>(in, 5);
      u64bit X6 = load_le<u64bit>(in, 6);
      u64bit X7 = load_le<u64bit>(in, 7);

      THREEFISH_INJECT_KEY(0);

      THREEFISH_ENC_8_ROUNDS(1,2);
      THREEFISH_ENC_8_ROUNDS(3,4);
      THREEFISH_ENC_8_ROUNDS(5,6);
      THREEFISH_ENC_8_ROUNDS(7,8);
      THREEFISH_ENC_8_ROUNDS(9,10);
      THREEFISH_ENC_8_ROUNDS(11,12);
      THREEFISH_ENC_8_ROUNDS(13,14);
      THREEFISH_ENC_8_ROUNDS(15,16);
      THREEFISH_ENC_8_ROUNDS(17,18);

      store_le(out, X0, X1, X2, X3, X4, X5, X6, X7);

      in += 64;
      out += 64;
      }
   }
Beispiel #3
0
void EAX_Decryption::finish(secure_vector<byte>& buffer, size_t offset)
{
    BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
    const size_t sz = buffer.size() - offset;
    byte* buf = buffer.data() + offset;

    BOTAN_ASSERT(sz >= tag_size(), "Have the tag as part of final input");

    const size_t remaining = sz - tag_size();

    if(remaining)
    {
        m_cmac->update(buf, remaining);
        m_ctr->cipher(buf, buf, remaining);
    }

    const byte* included_tag = &buf[remaining];

    secure_vector<byte> mac = m_cmac->final();
    mac ^= m_nonce_mac;
    mac ^= m_ad_mac;

    if(!same_mem(mac.data(), included_tag, tag_size()))
        throw Integrity_Failure("EAX tag check failed");

    buffer.resize(offset + remaining);
}
Beispiel #4
0
void Threefish_512::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
   {
   BOTAN_ASSERT(m_K.size() == 9, "Key was set");
   BOTAN_ASSERT(m_T.size() == 3, "Tweak was set");

#if defined(BOTAN_HAS_THREEFISH_512_AVX2)
   if(CPUID::has_avx2())
      {
      return avx2_encrypt_n(in, out, blocks);
      }
#endif

   BOTAN_PARALLEL_FOR(size_t i = 0; i < blocks; ++i)
      {
      uint64_t X0, X1, X2, X3, X4, X5, X6, X7;
      load_le(in + BLOCK_SIZE*i, X0, X1, X2, X3, X4, X5, X6, X7);

      THREEFISH_INJECT_KEY(0);

      THREEFISH_ENC_8_ROUNDS(1,2);
      THREEFISH_ENC_8_ROUNDS(3,4);
      THREEFISH_ENC_8_ROUNDS(5,6);
      THREEFISH_ENC_8_ROUNDS(7,8);
      THREEFISH_ENC_8_ROUNDS(9,10);
      THREEFISH_ENC_8_ROUNDS(11,12);
      THREEFISH_ENC_8_ROUNDS(13,14);
      THREEFISH_ENC_8_ROUNDS(15,16);
      THREEFISH_ENC_8_ROUNDS(17,18);

      store_le(out + BLOCK_SIZE*i, X0, X1, X2, X3, X4, X5, X6, X7);
      }
   }
Beispiel #5
0
/*
* Add a new output queue
*/
void Output_Buffers::add(SecureQueue* queue)
   {
   BOTAN_ASSERT(queue, "queue was provided");

   BOTAN_ASSERT(m_buffers.size() < m_buffers.max_size(),
                "Room was available in container");

   m_buffers.push_back(queue);
   }
Beispiel #6
0
void CCM_Decryption::finish(secure_vector<byte>& buffer, size_t offset)
   {
   BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");

   buffer.insert(buffer.begin() + offset, msg_buf().begin(), msg_buf().end());

   const size_t sz = buffer.size() - offset;
   byte* buf = buffer.data() + offset;

   BOTAN_ASSERT(sz >= tag_size(), "We have the tag");

   const secure_vector<byte>& ad = ad_buf();
   BOTAN_ASSERT(ad.size() % BS == 0, "AD is block size multiple");

   const BlockCipher& E = cipher();

   secure_vector<byte> T(BS);
   E.encrypt(format_b0(sz - tag_size()), T);

   for(size_t i = 0; i != ad.size(); i += BS)
      {
      xor_buf(T.data(), &ad[i], BS);
      E.encrypt(T);
      }

   secure_vector<byte> C = format_c0();

   secure_vector<byte> S0(BS);
   E.encrypt(C, S0);
   inc(C);

   secure_vector<byte> X(BS);

   const byte* buf_end = &buf[sz - tag_size()];

   while(buf != buf_end)
      {
      const size_t to_proc = std::min<size_t>(BS, buf_end - buf);

      E.encrypt(C, X);
      xor_buf(buf, X.data(), to_proc);
      inc(C);

      xor_buf(T.data(), buf, to_proc);
      E.encrypt(T);

      buf += to_proc;
      }

   T ^= S0;

   if(!same_mem(T.data(), buf_end, tag_size()))
      throw Integrity_Failure("CCM tag check failed");

   buffer.resize(buffer.size() - tag_size());
   }
Beispiel #7
0
size_t Sqlite3_Database::Sqlite3_Statement::get_size_t(int column)
   {
   BOTAN_ASSERT(::sqlite3_column_type(m_stmt, column) == SQLITE_INTEGER,
                "Return count is an integer");

   const int sessions_int = ::sqlite3_column_int(m_stmt, column);

   BOTAN_ASSERT(sessions_int >= 0, "Expected size_t is non-negative");

   return static_cast<size_t>(sessions_int);
   }
Beispiel #8
0
std::pair<const byte*, size_t> Sqlite3_Database::Sqlite3_Statement::get_blob(int column)
   {
   BOTAN_ASSERT(::sqlite3_column_type(m_stmt, 0) == SQLITE_BLOB,
                "Return value is a blob");

   const void* session_blob = ::sqlite3_column_blob(m_stmt, column);
   const int session_blob_size = ::sqlite3_column_bytes(m_stmt, column);

   BOTAN_ASSERT(session_blob_size >= 0, "Blob size is non-negative");

   return std::make_pair(static_cast<const byte*>(session_blob),
                         static_cast<size_t>(session_blob_size));
   }
Beispiel #9
0
void ECB_Encryption::update(secure_vector<byte>& buffer, size_t offset)
   {
   BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
   const size_t sz = buffer.size() - offset;
   byte* buf = buffer.data() + offset;

   const size_t BS = cipher().block_size();

   BOTAN_ASSERT(sz % BS == 0, "ECB input is full blocks");
   const size_t blocks = sz / BS;

   cipher().encrypt_n(buf, buf, blocks);
   }
Beispiel #10
0
void CCM_Encryption::finish(secure_vector<byte>& buffer, size_t offset)
   {
   BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");

   buffer.insert(buffer.begin() + offset, msg_buf().begin(), msg_buf().end());

   const size_t sz = buffer.size() - offset;
   byte* buf = buffer.data() + offset;

   const secure_vector<byte>& ad = ad_buf();
   BOTAN_ASSERT(ad.size() % BS == 0, "AD is block size multiple");

   const BlockCipher& E = cipher();

   secure_vector<byte> T(BS);
   E.encrypt(format_b0(sz), T);

   for(size_t i = 0; i != ad.size(); i += BS)
      {
      xor_buf(T.data(), &ad[i], BS);
      E.encrypt(T);
      }

   secure_vector<byte> C = format_c0();
   secure_vector<byte> S0(BS);
   E.encrypt(C, S0);
   inc(C);

   secure_vector<byte> X(BS);

   const byte* buf_end = &buf[sz];

   while(buf != buf_end)
      {
      const size_t to_proc = std::min<size_t>(BS, buf_end - buf);

      xor_buf(T.data(), buf, to_proc);
      E.encrypt(T);

      E.encrypt(C, X);
      xor_buf(buf, X.data(), to_proc);
      inc(C);

      buf += to_proc;
      }

   T ^= S0;

   buffer += std::make_pair(T.data(), tag_size());
   }
Beispiel #11
0
std::shared_ptr<const X509_Certificate>
Certificate_Store_MacOS::find_cert_by_pubkey_sha1(const std::vector<uint8_t>& key_hash) const
   {
   if(key_hash.size() != 20)
      {
      throw Invalid_Argument("Certificate_Store_MacOS::find_cert_by_pubkey_sha1 invalid hash");
      }

   scoped_CFType<CFDataRef> key_hash_cfdata(createCFDataView(key_hash));
   check_notnull(key_hash_cfdata, "create key hash search object");

   scoped_CFType<CFArrayRef> result(m_impl->search(
      {
         {kSecAttrPublicKeyHash, key_hash_cfdata.get()},
      }));

   if(!result)
      {
      return nullptr;  // no certificate found
      }

   const auto count = CFArrayGetCount(result.get());
   BOTAN_ASSERT(count > 0, "certificate result list contains an object");

   // `count` might be greater than 1, but we'll just select the first match
   auto cfCert = to_SecCertificateRef(CFArrayGetValueAtIndex(result.get(), 0));
   return readCertificate(cfCert);
   }
Beispiel #12
0
EC_PrivateKey::EC_PrivateKey(const AlgorithmIdentifier& alg_id,
                             const secure_vector<byte>& key_bits)
   {
   m_domain_params = EC_Group(alg_id.parameters);
   m_domain_encoding = EC_DOMPAR_ENC_EXPLICIT;

   OID key_parameters;
   secure_vector<byte> public_key_bits;

   BER_Decoder(key_bits)
      .start_cons(SEQUENCE)
         .decode_and_check<size_t>(1, "Unknown version code for ECC key")
         .decode_octet_string_bigint(m_private_key)
         .decode_optional(key_parameters, ASN1_Tag(0), PRIVATE)
         .decode_optional_string(public_key_bits, BIT_STRING, 1, PRIVATE)
      .end_cons();

   if(!key_parameters.empty() && key_parameters != alg_id.oid)
      throw Decoding_Error("EC_PrivateKey - inner and outer OIDs did not match");

   if(public_key_bits.empty())
      {
      m_public_key = domain().get_base_point() * m_private_key;

      BOTAN_ASSERT(m_public_key.on_the_curve(),
                   "Public point derived from loaded key was on the curve");
      }
   else
      {
      m_public_key = OS2ECP(public_key_bits, domain().get_curve());
      // OS2ECP verifies that the point is on the curve
      }
   }
bool XMSS_WOTS_Verification_Operation::is_valid_signature(const byte sig[],
                                                          size_t sig_len)
   {
   const XMSS_WOTS_Parameters& w = m_pub_key.public_key().wots_parameters();

   BOTAN_ASSERT(sig_len == w.element_size() * w.len(),
                "Invalid signature size.");

   wots_keysig_t signature(0);
   signature.reserve(sig_len);

   size_t begin = 0;
   size_t end = 0;
   while(signature.size() < w.len())
      {
      begin = end;
      end = begin + w.element_size();
      signature.push_back(secure_vector<byte>(sig + begin, sig + end));
      }

   XMSS_WOTS_PublicKey pubkey_msg(w.oid(),
                                  m_msg_buf,
                                  signature,
                                  m_pub_key.address(),
                                  m_pub_key.public_key().public_seed());

   return pubkey_msg.key_data() == m_pub_key.public_key().key_data();
   }
Beispiel #14
0
GOST_3410_PublicKey::GOST_3410_PublicKey(const AlgorithmIdentifier& alg_id,
                                         const secure_vector<byte>& key_bits)
   {
   OID ecc_param_id;

   // The parameters also includes hash and cipher OIDs
   BER_Decoder(alg_id.parameters).start_cons(SEQUENCE).decode(ecc_param_id);

   domain_params = EC_Group(ecc_param_id);

   secure_vector<byte> bits;
   BER_Decoder(key_bits).decode(bits, OCTET_STRING);

   const size_t part_size = bits.size() / 2;

   // Keys are stored in little endian format (WTF)
   for(size_t i = 0; i != part_size / 2; ++i)
      {
      std::swap(bits[i], bits[part_size-1-i]);
      std::swap(bits[part_size+i], bits[2*part_size-1-i]);
      }

   BigInt x(bits.data(), part_size);
   BigInt y(&bits[part_size], part_size);

   public_key = PointGFp(domain().get_curve(), x, y);

   BOTAN_ASSERT(public_key.on_the_curve(),
                "Loaded GOST 34.10 public key is on the curve");
   }
Beispiel #15
0
size_t CBC_Decryption::process(uint8_t buf[], size_t sz)
   {
   const size_t BS = cipher().block_size();

   BOTAN_ASSERT(sz % BS == 0, "Input is full blocks");
   size_t blocks = sz / BS;

   while(blocks)
      {
      const size_t to_proc = std::min(BS * blocks, m_tempbuf.size());

      cipher().decrypt_n(buf, m_tempbuf.data(), to_proc / BS);

      xor_buf(m_tempbuf.data(), state_ptr(), BS);
      xor_buf(&m_tempbuf[BS], buf, to_proc - BS);
      copy_mem(state_ptr(), buf + (to_proc - BS), BS);

      copy_mem(buf, m_tempbuf.data(), to_proc);

      buf += to_proc;
      blocks -= to_proc / BS;
      }

   return sz;
   }
Beispiel #16
0
std::vector<X509_DN> Certificate_Store_MacOS::all_subjects() const
   {
   scoped_CFType<CFArrayRef> result(m_impl->search());

   if(!result)
      {
      return {};  // not a single certificate found in the keychain
      }

   const auto count = CFArrayGetCount(result.get());
   BOTAN_ASSERT(count > 0, "subject result list contains data");

   std::vector<X509_DN> output;
   output.reserve(count);
   for(unsigned int i = 0; i < count; ++i)
      {
      // Note: Apple's API provides SecCertificateCopyNormalizedSubjectSequence
      //       which would have saved us from reading a Botan::X509_Certificate,
      //       however, this function applies the same DN "normalization" as
      //       stated above.
      auto cfCert = to_SecCertificateRef(CFArrayGetValueAtIndex(result.get(), i));
      auto cert = readCertificate(cfCert);
      output.emplace_back(cert->subject_dn());
      }

   return output;
   }
Beispiel #17
0
/**
* EC_PrivateKey constructor
*/
EC_PrivateKey::EC_PrivateKey(RandomNumberGenerator& rng,
                             const EC_Group& ec_group,
                             const BigInt& x,
                             bool with_modular_inverse)
   {
   m_domain_params = ec_group;
   if (!ec_group.get_oid().empty())
      m_domain_encoding = EC_DOMPAR_ENC_OID;
   else
      m_domain_encoding = EC_DOMPAR_ENC_EXPLICIT;

   if(x == 0)
      {
      m_private_key = BigInt::random_integer(rng, 1, domain().get_order());
      }
   else
      {
      m_private_key = x;
      }

   m_public_key = domain().get_base_point() *
                  ((with_modular_inverse) ? inverse_mod(m_private_key, m_domain_params.get_order()) : m_private_key);

   BOTAN_ASSERT(m_public_key.on_the_curve(),
                "Generated public key point was on the curve");
   }
Beispiel #18
0
void GHASH::update(const uint8_t input[], size_t length)
   {
   BOTAN_ASSERT(m_ghash.size() == GCM_BS, "Key was set");

   m_text_len += length;

   ghash_update(m_ghash, input, length);
   }
Beispiel #19
0
void Stream_Decompression::process(secure_vector<byte>& buf, size_t offset, u32bit flags)
   {
   BOTAN_ASSERT(m_stream, "Initialized");
   BOTAN_ASSERT(buf.size() >= offset, "Offset is sane");

   if(m_buffer.size() < buf.size() + offset)
      m_buffer.resize(buf.size() + offset);

   m_stream->next_in(buf.data() + offset, buf.size() - offset);
   m_stream->next_out(m_buffer.data() + offset, m_buffer.size() - offset);

   while(true)
      {
      const bool stream_end = m_stream->run(flags);

      if(stream_end)
         {
         if(m_stream->avail_in() == 0) // all data consumed?
            {
            m_buffer.resize(m_buffer.size() - m_stream->avail_out());
            clear();
            break;
            }

         // More data follows: try to process as a following stream
         const size_t read = (buf.size() - offset) - m_stream->avail_in();
         start();
         m_stream->next_in(buf.data() + offset + read, buf.size() - offset - read);
         }

      if(m_stream->avail_out() == 0)
         {
         const size_t added = 8 + m_buffer.size();
         m_buffer.resize(m_buffer.size() + added);
         m_stream->next_out(m_buffer.data() + m_buffer.size() - added, added);
         }
      else if(m_stream->avail_in() == 0)
         {
         m_buffer.resize(m_buffer.size() - m_stream->avail_out());
         break;
         }
      }

   copy_mem(m_buffer.data(), buf.data(), offset);
   buf.swap(m_buffer);
   }
Beispiel #20
0
std::vector<byte> Transform_Filter::Nonce_State::get()
   {
   BOTAN_ASSERT(m_fresh_nonce, "The nonce is fresh for this message");

   if(!m_nonce.empty())
      m_fresh_nonce = false;
   return m_nonce;
   }
Beispiel #21
0
void CCM_Mode::update(secure_vector<byte>& buffer, size_t offset)
   {
   BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
   const size_t sz = buffer.size() - offset;
   byte* buf = buffer.data() + offset;

   m_msg_buf.insert(m_msg_buf.end(), buf, buf + sz);
   buffer.resize(offset); // truncate msg
   }
Beispiel #22
0
/*
* Get a particular output queue
*/
SecureQueue* Output_Buffers::get(Pipe::message_id msg) const
   {
   if(msg < m_offset)
      return nullptr;

   BOTAN_ASSERT(msg < message_count(), "Message number is in range");

   return m_buffers[msg-m_offset];
   }
Beispiel #23
0
void EAX_Decryption::update(secure_vector<byte>& buffer, size_t offset)
{
    BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
    const size_t sz = buffer.size() - offset;
    byte* buf = buffer.data() + offset;

    m_cmac->update(buf, sz);
    m_ctr->cipher(buf, buf, sz);
}
Beispiel #24
0
Cascade_Cipher::Cascade_Cipher(BlockCipher* c1, BlockCipher* c2) :
   m_cipher1(c1), m_cipher2(c2)
   {
   m_block = block_size_for_cascade(c1->block_size(), c2->block_size());

   BOTAN_ASSERT(m_block % c1->block_size() == 0 &&
                m_block % c2->block_size() == 0,
                "Combined block size is a multiple of each ciphers block");
   }
Beispiel #25
0
void XTS_Decryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
   {
   BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
   const size_t sz = buffer.size() - offset;
   uint8_t* buf = buffer.data() + offset;

   BOTAN_ASSERT(sz >= minimum_final_size(), "Have sufficient final input in XTS decrypt");

   const size_t BS = cipher().block_size();

   if(sz % BS == 0)
      {
      update(buffer, offset);
      }
   else
      {
      // steal ciphertext
      const size_t full_blocks = ((sz / BS) - 1) * BS;
      const size_t final_bytes = sz - full_blocks;
      BOTAN_ASSERT(final_bytes > BS && final_bytes < 2*BS, "Left over size in expected range");

      secure_vector<uint8_t> last(buf + full_blocks, buf + full_blocks + final_bytes);
      buffer.resize(full_blocks + offset);
      update(buffer, offset);

      xor_buf(last, tweak() + BS, BS);
      cipher().decrypt(last);
      xor_buf(last, tweak() + BS, BS);

      for(size_t i = 0; i != final_bytes - BS; ++i)
         {
         last[i] ^= last[i + BS];
         last[i + BS] ^= last[i];
         last[i] ^= last[i + BS];
         }

      xor_buf(last, tweak(), BS);
      cipher().decrypt(last);
      xor_buf(last, tweak(), BS);

      buffer += last;
      }
   }
Beispiel #26
0
void CTS_Decryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
   {
   BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
   const size_t sz = buffer.size() - offset;
   uint8_t* buf = buffer.data() + offset;

   const size_t BS = cipher().block_size();

   if(sz < BS + 1)
      throw Encoding_Error(name() + ": insufficient data to decrypt");

   if(sz % BS == 0)
      {
      // swap last two blocks

      for(size_t i = 0; i != BS; ++i)
         std::swap(buffer[buffer.size()-BS+i], buffer[buffer.size()-2*BS+i]);

      update(buffer, offset);
      }
   else
      {
      const size_t full_blocks = ((sz / BS) - 1) * BS;
      const size_t final_bytes = sz - full_blocks;
      BOTAN_ASSERT(final_bytes > BS && final_bytes < 2*BS, "Left over size in expected range");

      secure_vector<uint8_t> last(buf + full_blocks, buf + full_blocks + final_bytes);
      buffer.resize(full_blocks + offset);
      update(buffer, offset);

      cipher().decrypt(last.data());

      xor_buf(last.data(), &last[BS], final_bytes - BS);

      for(size_t i = 0; i != final_bytes - BS; ++i)
         std::swap(last[i], last[i + BS]);

      cipher().decrypt(last.data());
      xor_buf(last.data(), state_ptr(), BS);

      buffer += last;
      }
   }
Beispiel #27
0
void Threefish_512::skein_feedfwd(const secure_vector<u64bit>& M,
                                  const secure_vector<u64bit>& T)
   {
   BOTAN_ASSERT(m_K.size() == 9, "Key was set");
   BOTAN_ASSERT(M.size() == 8, "Single block");

   m_T[0] = T[0];
   m_T[1] = T[1];
   m_T[2] = T[0] ^ T[1];

   u64bit X0 = M[0];
   u64bit X1 = M[1];
   u64bit X2 = M[2];
   u64bit X3 = M[3];
   u64bit X4 = M[4];
   u64bit X5 = M[5];
   u64bit X6 = M[6];
   u64bit X7 = M[7];

   THREEFISH_INJECT_KEY(0);

   THREEFISH_ENC_8_ROUNDS(1,2);
   THREEFISH_ENC_8_ROUNDS(3,4);
   THREEFISH_ENC_8_ROUNDS(5,6);
   THREEFISH_ENC_8_ROUNDS(7,8);
   THREEFISH_ENC_8_ROUNDS(9,10);
   THREEFISH_ENC_8_ROUNDS(11,12);
   THREEFISH_ENC_8_ROUNDS(13,14);
   THREEFISH_ENC_8_ROUNDS(15,16);
   THREEFISH_ENC_8_ROUNDS(17,18);

   m_K[0] = M[0] ^ X0;
   m_K[1] = M[1] ^ X1;
   m_K[2] = M[2] ^ X2;
   m_K[3] = M[3] ^ X3;
   m_K[4] = M[4] ^ X4;
   m_K[5] = M[5] ^ X5;
   m_K[6] = M[6] ^ X6;
   m_K[7] = M[7] ^ X7;

   m_K[8] = m_K[0] ^ m_K[1] ^ m_K[2] ^ m_K[3] ^
            m_K[4] ^ m_K[5] ^ m_K[6] ^ m_K[7] ^ 0x1BD11BDAA9FC1A22;
   }
Beispiel #28
0
void CCM_Mode::encode_length(size_t len, byte out[])
   {
   const size_t len_bytes = L();

   BOTAN_ASSERT(len_bytes < sizeof(size_t), "Length field fits");

   for(size_t i = 0; i != len_bytes; ++i)
      out[len_bytes-1-i] = get_byte(sizeof(size_t)-1-i, len);

   BOTAN_ASSERT((len >> (len_bytes*8)) == 0, "Message length fits in field");
   }
Beispiel #29
0
secure_vector<byte>
PK_Decryptor::decrypt_or_random(const byte in[],
                                size_t length,
                                size_t expected_pt_len,
                                RandomNumberGenerator& rng,
                                const byte required_content_bytes[],
                                const byte required_content_offsets[],
                                size_t required_contents_length) const
   {
   const secure_vector<byte> fake_pms = rng.random_vec(expected_pt_len);

   //CT::poison(in, length);

   byte valid_mask = 0;
   secure_vector<byte> decoded = do_decrypt(valid_mask, in, length);

   valid_mask &= CT::is_equal(decoded.size(), expected_pt_len);

   decoded.resize(expected_pt_len);

   for(size_t i = 0; i != required_contents_length; ++i)
      {
      /*
      These values are chosen by the application and for TLS are constants,
      so this early failure via assert is fine since we know 0,1 < 48

      If there is a protocol that has content checks on the key where
      the expected offsets are controllable by the attacker this could
      still leak.

      Alternately could always reduce the offset modulo the length?
      */

      const byte exp = required_content_bytes[i];
      const byte off = required_content_offsets[i];

      BOTAN_ASSERT(off < expected_pt_len, "Offset in range of plaintext");

      valid_mask &= CT::is_equal(decoded[off], exp);
      }

   CT::conditional_copy_mem(valid_mask,
                            /*output*/decoded.data(),
                            /*from0*/decoded.data(),
                            /*from1*/fake_pms.data(),
                            expected_pt_len);

   //CT::unpoison(in, length);
   //CT::unpoison(decoded.data(), decoded.size());

   return decoded;
   }
void
XMSS_WOTS_Verification_Operation::update(const byte msg[], size_t msg_len)
   {
   BOTAN_ASSERT(msg_len == m_pub_key.public_key().wots_parameters().
                           element_size() &&
                m_msg_buf.size() == 0,
                "XMSS WOTS only supports one message part of size n.");

   for(size_t i = 0; i < msg_len; i++)
      {
      m_msg_buf.push_back(msg[i]);
      }
   }