Exemple #1
0
/*************************************************
* CTR-BE Encryption/Decryption                   *
*************************************************/
void CTR_BE::write(const byte input[], u32bit length)
   {
   u32bit copied = std::min(BLOCK_SIZE - position, length);
   xor_buf(buffer + position, input, copied);
   send(buffer + position, copied);
   input += copied;
   length -= copied;
   position += copied;

   if(position == BLOCK_SIZE)
      increment_counter();

   while(length >= BLOCK_SIZE)
      {
      xor_buf(buffer, input, BLOCK_SIZE);
      send(buffer, BLOCK_SIZE);

      input += BLOCK_SIZE;
      length -= BLOCK_SIZE;
      increment_counter();
      }

   xor_buf(buffer + position, input, length);
   send(buffer + position, length);
   position += length;
   }
Exemple #2
0
/*
* Finish encrypting in XTS mode
*/
void XTS_Encryption::end_msg()
   {
   const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE;

   if(position < BLOCK_SIZE)
      throw Exception("XTS_Encryption: insufficient data to encrypt");
   else if(position == BLOCK_SIZE)
      {
      encrypt(buffer);
      }
   else if(position == 2*BLOCK_SIZE)
      {
      encrypt(buffer);
      encrypt(buffer + BLOCK_SIZE);
      }
   else
      { // steal ciphertext
      xor_buf(buffer, tweak, cipher->BLOCK_SIZE);
      cipher->encrypt(buffer);
      xor_buf(buffer, tweak, cipher->BLOCK_SIZE);

      poly_double(tweak, cipher->BLOCK_SIZE);

      for(u32bit i = 0; i != position - cipher->BLOCK_SIZE; ++i)
         std::swap(buffer[i], buffer[i + cipher->BLOCK_SIZE]);

      xor_buf(buffer, tweak, cipher->BLOCK_SIZE);
      cipher->encrypt(buffer);
      xor_buf(buffer, tweak, cipher->BLOCK_SIZE);

      send(buffer, position);
      }

   position = 0;
   }
Exemple #3
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;
   }
Exemple #4
0
/*************************************************
* OFB Encryption/Decryption                      *
*************************************************/
void OFB::write(const byte input[], u32bit length)
   {
   u32bit copied = std::min(BLOCK_SIZE - position, length);
   xor_buf(buffer, input, state + position, copied);
   send(buffer, copied);
   input += copied;
   length -= copied;
   position += copied;

   if(position == BLOCK_SIZE)
      {
      cipher->encrypt(state);
      position = 0;
      }

   while(length >= BLOCK_SIZE)
      {
      xor_buf(buffer, input, state, BLOCK_SIZE);
      send(buffer, BLOCK_SIZE);

      input += BLOCK_SIZE;
      length -= BLOCK_SIZE;
      cipher->encrypt(state);
      }

   xor_buf(buffer, input, state + position, length);
   send(buffer, length);
   position += length;
   }
Exemple #5
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());
   }
Exemple #6
0
void EAX_Encryption::finish(secure_vector<byte>& buffer, size_t offset)
{
    update(buffer, offset);

    secure_vector<byte> data_mac = m_cmac->final();
    xor_buf(data_mac, m_nonce_mac, data_mac.size());
    xor_buf(data_mac, m_ad_mac, data_mac.size());

    buffer += std::make_pair(data_mac.data(), tag_size());
}
Exemple #7
0
/*
* Decrypt a block
*/
void XTS_Decryption::decrypt(const byte block[])
   {
   xor_buf(buffer, block, tweak, cipher->BLOCK_SIZE);
   cipher->decrypt(buffer);
   xor_buf(buffer, tweak, cipher->BLOCK_SIZE);

   poly_double(tweak, cipher->BLOCK_SIZE);

   send(buffer, cipher->BLOCK_SIZE);
   }
Exemple #8
0
/*
* Finish decrypting in CTS mode
*/
void CTS_Decryption::end_msg()
   {
   cipher->decrypt(buffer, temp);
   xor_buf(temp, buffer + BLOCK_SIZE, position - BLOCK_SIZE);
   SecureVector<byte> xn = temp;
   copy_mem(buffer + position, xn + (position - BLOCK_SIZE),
            BUFFER_SIZE - position);
   cipher->decrypt(buffer + BLOCK_SIZE, temp);
   xor_buf(temp, state, BLOCK_SIZE);
   send(temp, BLOCK_SIZE);
   send(xn, position - BLOCK_SIZE);
   }
Exemple #9
0
/*
* Combine cipher stream with message
*/
void ARC4::cipher(const byte in[], byte out[], size_t length)
   {
   while(length >= buffer.size() - position)
      {
      xor_buf(out, in, &buffer[position], buffer.size() - position);
      length -= (buffer.size() - position);
      in += (buffer.size() - position);
      out += (buffer.size() - position);
      generate();
      }
   xor_buf(out, in, &buffer[position], length);
   position += length;
   }
Exemple #10
0
void aont_package(RandomNumberGenerator& rng,
                  BlockCipher* cipher,
                  const byte input[], size_t input_len,
                  byte output[])
   {
   const size_t BLOCK_SIZE = cipher->block_size();

   if(!cipher->valid_keylength(BLOCK_SIZE))
      throw Invalid_Argument("AONT::package: Invalid cipher");

   // The all-zero string which is used both as the CTR IV and as K0
   const std::string all_zeros(BLOCK_SIZE*2, '0');

   SymmetricKey package_key(rng, BLOCK_SIZE);

   Pipe pipe(new StreamCipher_Filter(new CTR_BE(cipher), package_key));

   pipe.process_msg(input, input_len);
   pipe.read(output, pipe.remaining());

   // Set K0 (the all zero key)
   cipher->set_key(SymmetricKey(all_zeros));

   SecureVector<byte> buf(BLOCK_SIZE);

   const size_t blocks =
      (input_len + BLOCK_SIZE - 1) / BLOCK_SIZE;

   byte* final_block = output + input_len;
   clear_mem(final_block, BLOCK_SIZE);

   // XOR the hash blocks into the final block
   for(size_t i = 0; i != blocks; ++i)
      {
      const size_t left = std::min<size_t>(BLOCK_SIZE,
                                           input_len - BLOCK_SIZE * i);

      zeroise(buf);
      copy_mem(&buf[0], output + (BLOCK_SIZE * i), left);

      for(size_t j = 0; j != sizeof(i); ++j)
         buf[BLOCK_SIZE - 1 - j] ^= get_byte(sizeof(i)-1-j, i);

      cipher->encrypt(buf);

      xor_buf(final_block, buf, BLOCK_SIZE);
      }

   // XOR the random package key into the final block
   xor_buf(final_block, package_key.begin(), BLOCK_SIZE);
   }
Exemple #11
0
void OFB::cipher(const byte in[], byte out[], size_t length)
   {
   while(length >= m_buffer.size() - m_buf_pos)
      {
      xor_buf(out, in, &m_buffer[m_buf_pos], m_buffer.size() - m_buf_pos);
      length -= (m_buffer.size() - m_buf_pos);
      in += (m_buffer.size() - m_buf_pos);
      out += (m_buffer.size() - m_buf_pos);
      m_cipher->encrypt(m_buffer);
      m_buf_pos = 0;
      }
   xor_buf(out, in, &m_buffer[m_buf_pos], length);
   m_buf_pos += length;
   }
Exemple #12
0
/*************************************************
* HMAC Key Schedule                              *
*************************************************/
void HMAC::key(const byte key[], u32bit length)
   {
   hash->clear();
   std::fill(i_key.begin(), i_key.end(), 0x36);
   std::fill(o_key.begin(), o_key.end(), 0x5C);

   SecureVector<byte> hmac_key(key, length);
   if(hmac_key.size() > hash->HASH_BLOCK_SIZE)
      hmac_key = hash->process(hmac_key);

   xor_buf(i_key, hmac_key, hmac_key.size());
   xor_buf(o_key, hmac_key, hmac_key.size());
   hash->update(i_key);
   }
Exemple #13
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());
   }
/*************************************************
* Refill the internal state                      *
*************************************************/
void ANSI_X931_RNG::update_buffer()
   {
   const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE;

   SecureVector<byte> DT(BLOCK_SIZE);

   prng->randomize(DT, DT.size());
   cipher->encrypt(DT);

   xor_buf(R, V, DT, BLOCK_SIZE);
   cipher->encrypt(R);

   xor_buf(V, R, DT, BLOCK_SIZE);
   cipher->encrypt(V);
   }
Exemple #15
0
/**
* Refill the internal state
*/
void ANSI_X931_RNG::update_buffer()
   {
   SecureVector<byte> DT(cipher->BLOCK_SIZE);

   prng->randomize(DT, DT.size());
   cipher->encrypt(DT);

   xor_buf(R, V, DT, cipher->BLOCK_SIZE);
   cipher->encrypt(R);

   xor_buf(V, R, DT, cipher->BLOCK_SIZE);
   cipher->encrypt(V);

   position = 0;
   }
Exemple #16
0
/*
* Refill the internal state
*/
void ANSI_X931_RNG::update_buffer()
   {
   const size_t BLOCK_SIZE = m_cipher->block_size();

   secure_vector<byte> DT = m_prng->random_vec(BLOCK_SIZE);
   m_cipher->encrypt(DT);

   xor_buf(m_R.data(), m_V.data(), DT.data(), BLOCK_SIZE);
   m_cipher->encrypt(m_R);

   xor_buf(m_V.data(), m_R.data(), DT.data(), BLOCK_SIZE);
   m_cipher->encrypt(m_V);

   m_R_pos = 0;
   }
/*
* Combine cipher stream with message
*/
void RC4::cipher(const uint8_t in[], uint8_t out[], size_t length)
   {
   verify_key_set(m_state.empty() == false);

   while(length >= m_buffer.size() - m_position)
      {
      xor_buf(out, in, &m_buffer[m_position], m_buffer.size() - m_position);
      length -= (m_buffer.size() - m_position);
      in += (m_buffer.size() - m_position);
      out += (m_buffer.size() - m_position);
      generate();
      }
   xor_buf(out, in, &m_buffer[m_position], length);
   m_position += length;
   }
void
XMSS_WOTS_PublicKey::chain(secure_vector<uint8_t>& result,
                           size_t start_idx,
                           size_t steps,
                           XMSS_Address& adrs,
                           const secure_vector<uint8_t>& seed,
                           XMSS_Hash& hash)
   {
   for(size_t i = start_idx;
         i < (start_idx + steps) && i < m_wots_params.wots_parameter();
         i++)
      {
      adrs.set_hash_address(i);

      //Calculate tmp XOR bitmask
      adrs.set_key_mask_mode(XMSS_Address::Key_Mask::Mask_Mode);
      xor_buf(result, hash.prf(seed, adrs.bytes()), result.size());

      // Calculate key
      adrs.set_key_mask_mode(XMSS_Address::Key_Mask::Key_Mode);

      //Calculate f(key, tmp XOR bitmask)
      hash.f(result, hash.prf(seed, adrs.bytes()), result);
      }
   }
Exemple #19
0
/*
* Decrypt a block
*/
void CTS_Decryption::decrypt(const byte block[])
   {
   cipher->decrypt(block, temp);
   xor_buf(temp, state, BLOCK_SIZE);
   send(temp, BLOCK_SIZE);
   state.copy(block, BLOCK_SIZE);
   }
Exemple #20
0
void cbc_decrypt(cbc_state_t *state, aes_ctx_t *ctx) {
  uint8_t this_cipher[AES_BUF_LEN];
  memcpy(this_cipher, state->data, AES_BUF_LEN);
  aes128_dec(state->data, ctx);
  xor_buf(state->data, state->iv, AES_BUF_LEN);
  memcpy(state->iv, this_cipher, AES_BUF_LEN);
}
Exemple #21
0
/*
* Combine cipher stream with message
*/
void ChaCha::cipher(const byte in[], byte out[], size_t length)
   {
   while(length >= m_buffer.size() - m_position)
      {
      xor_buf(out, in, &m_buffer[m_position], m_buffer.size() - m_position);
      length -= (m_buffer.size() - m_position);
      in += (m_buffer.size() - m_position);
      out += (m_buffer.size() - m_position);
      chacha_x4(m_buffer.data(), m_state.data(), m_rounds);
      m_position = 0;
      }

   xor_buf(out, in, &m_buffer[m_position], length);

   m_position += length;
   }
/*
* Finish decrypting in EAX mode
*/
void EAX_Decryption::end_msg()
   {
   if((queue_end - queue_start) != TAG_SIZE)
      throw Decoding_Error(name() + ": Message authentication failure");

   const byte* included_mac = &queue[queue_start];

   SecureVector<byte> computed_mac = cmac->final();

   xor_buf(&computed_mac[0], &nonce_mac[0], TAG_SIZE);
   xor_buf(&computed_mac[0], &header_mac[0], TAG_SIZE);

   if(!same_mem(included_mac, &computed_mac[0], TAG_SIZE))
      throw Decoding_Error(name() + ": Message authentication failure");

   queue_start = queue_end = 0;
   }
Exemple #23
0
/*
* XOR Operation for OctetStrings
*/
OctetString operator^(const OctetString& k1, const OctetString& k2)
   {
   secure_vector<uint8_t> out(std::max(k1.length(), k2.length()));

   copy_mem(out.data(), k1.begin(), k1.length());
   xor_buf(out.data(), k2.begin(), k2.length());
   return OctetString(out);
   }
Exemple #24
0
/*************************************************
* Add user-supplied entropy                      *
*************************************************/
void Randpool::add_entropy(const byte input[], u32bit length)
   {
   SecureVector<byte> mac_val = mac->process(input, length);
   xor_buf(pool, mac_val, mac_val.size());
   mix_pool();

   entropy += entropy_estimate(input, length);
   }
Exemple #25
0
void XTS_Encryption::encrypt(const byte block[])
   {
   /*
   * We can always use the first 16 bytes of buffer as temp space,
   * since either the input block is buffer (in which case this is
   * just buffer ^= tweak) or it not, in which case we already read
   * and used the data there and are processing new input. Kind of
   * subtle/nasty, but saves allocating a distinct temp buf.
   */

   xor_buf(buffer, block, tweak, cipher->BLOCK_SIZE);
   cipher->encrypt(buffer);
   xor_buf(buffer, tweak, cipher->BLOCK_SIZE);

   poly_double(tweak, cipher->BLOCK_SIZE);

   send(buffer, cipher->BLOCK_SIZE);
   }
/**
* Add user-supplied entropy
*/
void Randpool::add_entropy(const byte input[], u32bit length)
{
    SecureVector<byte> mac_val = mac->process(input, length);
    xor_buf(pool, mac_val, mac_val.size());
    mix_pool();

    if(length)
        seeded = true;
}
Exemple #27
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;
      }
   }
Exemple #28
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;
      }
   }
Exemple #29
0
void SHAKE_128_Cipher::cipher(const uint8_t in[], uint8_t out[], size_t length)
   {
   verify_key_set(m_state.empty() == false);

   while(length >= m_buffer.size() - m_buf_pos)
      {
      xor_buf(out, in, &m_buffer[m_buf_pos], m_buffer.size() - m_buf_pos);
      length -= (m_buffer.size() - m_buf_pos);
      in += (m_buffer.size() - m_buf_pos);
      out += (m_buffer.size() - m_buf_pos);

      SHA_3::permute(m_state.data());
      copy_out_le(m_buffer.data(), m_buffer.size(), m_state.data());

      m_buf_pos = 0;
      }
   xor_buf(out, in, &m_buffer[m_buf_pos], length);
   m_buf_pos += length;
   }
Exemple #30
0
/*
* Combine cipher stream with message
*/
void Salsa20::cipher(const uint8_t in[], uint8_t out[], size_t length)
   {
   while(length >= m_buffer.size() - m_position)
      {
      xor_buf(out, in, &m_buffer[m_position], m_buffer.size() - m_position);
      length -= (m_buffer.size() - m_position);
      in += (m_buffer.size() - m_position);
      out += (m_buffer.size() - m_position);
      salsa20(m_buffer.data(), m_state.data());

      ++m_state[8];
      m_state[9] += (m_state[8] == 0);

      m_position = 0;
      }

   xor_buf(out, in, &m_buffer[m_position], length);

   m_position += length;
   }