Beispiel #1
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 #2
0
bool EMSA1::verify(const secure_vector<byte>& coded,
                   const secure_vector<byte>& raw, size_t key_bits)
   {
   try {
      if(raw.size() != m_hash->output_length())
         throw Encoding_Error("EMSA1::encoding_of: Invalid size for input");

      secure_vector<byte> our_coding = emsa1_encoding(raw, key_bits);

      if(our_coding == coded) return true;
      if(our_coding.empty() || our_coding[0] != 0) return false;
      if(our_coding.size() <= coded.size()) return false;

      size_t offset = 0;
      while(offset < our_coding.size() && our_coding[offset] == 0)
         ++offset;
      if(our_coding.size() - offset != coded.size())
         return false;

      for(size_t j = 0; j != coded.size(); ++j)
         if(coded[j] != our_coding[j+offset])
            return false;

      return true;
      }
   catch(Invalid_Argument)
      {
      return false;
      }
   }
Beispiel #3
0
void Montgomery_Params::mul_by(BigInt& x,
                               const secure_vector<word>& y,
                               secure_vector<word>& ws) const
   {
   const size_t output_size = 2*m_p_words + 2;

   if(ws.size() < 2*output_size)
      ws.resize(2*output_size);

   word* z_data = &ws[0];
   word* ws_data = &ws[output_size];

   BOTAN_DEBUG_ASSERT(x.sig_words() <= m_p_words);

   bigint_mul(z_data, output_size,
              x.data(), x.size(), std::min(m_p_words, x.size()),
              y.data(), y.size(), std::min(m_p_words, y.size()),
              ws_data, output_size);

   bigint_monty_redc(z_data,
                     m_p.data(), m_p_words, m_p_dash,
                     ws_data, output_size);

   if(x.size() < output_size)
      x.grow_to(output_size);
   copy_mem(x.mutable_data(), z_data, output_size);
   }
Beispiel #4
0
/*
* PSSR Decode/Verify Operation
*/
bool PSSR::verify(const secure_vector<byte>& const_coded,
                   const secure_vector<byte>& raw, size_t key_bits)
   {
   const size_t HASH_SIZE = hash->output_length();
   const size_t KEY_BYTES = (key_bits + 7) / 8;

   if(key_bits < 8*HASH_SIZE + 9)
      return false;

   if(raw.size() != HASH_SIZE)
      return false;

   if(const_coded.size() > KEY_BYTES || const_coded.size() <= 1)
      return false;

   if(const_coded[const_coded.size()-1] != 0xBC)
      return false;

   secure_vector<byte> coded = const_coded;
   if(coded.size() < KEY_BYTES)
      {
      secure_vector<byte> temp(KEY_BYTES);
      buffer_insert(temp, KEY_BYTES - coded.size(), coded);
      coded = temp;
      }

   const size_t TOP_BITS = 8 * ((key_bits + 7) / 8) - key_bits;
   if(TOP_BITS > 8 - high_bit(coded[0]))
      return false;

   byte* DB = &coded[0];
   const size_t DB_size = coded.size() - HASH_SIZE - 1;

   const byte* H = &coded[DB_size];
   const size_t H_size = HASH_SIZE;

   mgf1_mask(*hash, &H[0], H_size, &DB[0], DB_size);
   DB[0] &= 0xFF >> TOP_BITS;

   size_t salt_offset = 0;
   for(size_t j = 0; j != DB_size; ++j)
      {
      if(DB[j] == 0x01)
         { salt_offset = j + 1; break; }
      if(DB[j])
         return false;
      }
   if(salt_offset == 0)
      return false;

   for(size_t j = 0; j != 8; ++j)
      hash->update(0);
   hash->update(raw);
   hash->update(&DB[salt_offset], DB_size - salt_offset);
   secure_vector<byte> H2 = hash->final();

   return same_mem(&H[0], &H2[0], HASH_SIZE);
   }
Beispiel #5
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 #6
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 #7
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 #8
0
/*
* EMSA1 BSI Encode Operation
*/
secure_vector<byte> EMSA1_BSI::encoding_of(const secure_vector<byte>& msg,
                                          size_t output_bits,
                                          RandomNumberGenerator&)
   {
   if(msg.size() != hash_output_length())
      throw Encoding_Error("EMSA1_BSI::encoding_of: Invalid size for input");

   if(8*msg.size() <= output_bits)
      return msg;

   throw Encoding_Error("EMSA1_BSI::encoding_of: max key input size exceeded");
   }
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
secure_vector<uint8_t> rfc3394_keyunwrap(const secure_vector<uint8_t>& key,
                                         const SymmetricKey& kek)
   {
   BOTAN_ARG_CHECK(kek.size() == 16 || kek.size() == 24 || kek.size() == 32,
                   "Invalid KEK length for NIST key wrap");

   BOTAN_ARG_CHECK(key.size() >= 16 && key.size() % 8 == 0,
                   "Bad input key size for NIST key unwrap");

   const std::string cipher_name = "AES-" + std::to_string(8*kek.size());
   std::unique_ptr<BlockCipher> aes(BlockCipher::create_or_throw(cipher_name));
   aes->set_key(kek);

   return nist_key_unwrap(key.data(), key.size(), *aes);
   }
Beispiel #12
0
void ECB_Decryption::finish(secure_vector<byte>& buffer, size_t offset)
   {
   BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
   const size_t sz = buffer.size() - offset;

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

   if(sz == 0 || sz % BS)
      throw Decoding_Error(name() + ": Ciphertext not a multiple of block size");

   update(buffer, offset);

   const size_t pad_bytes = BS - padding().unpad(&buffer[buffer.size()-BS], BS);
   buffer.resize(buffer.size() - pad_bytes); // remove padding
   }
Beispiel #13
0
void CBC_Encryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
   {
   BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");

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

   const size_t bytes_in_final_block = (buffer.size()-offset) % BS;

   padding().add_padding(buffer, bytes_in_final_block, BS);

   if((buffer.size()-offset) % BS)
      throw Exception("Did not pad to full block size in " + name());

   update(buffer, offset);
   }
Beispiel #14
0
void ECB_Encryption::finish(secure_vector<byte>& buffer, size_t offset)
   {
   BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
   const size_t sz = buffer.size() - offset;

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

   const size_t bytes_in_final_block = sz % BS;

   padding().add_padding(buffer, bytes_in_final_block, BS);

   if(buffer.size() % BS)
      throw std::runtime_error("Did not pad to full block size in " + name());

   update(buffer, offset);
   }
Beispiel #15
0
Ed25519_PrivateKey::Ed25519_PrivateKey(const secure_vector<uint8_t>& secret_key)
   {
   if(secret_key.size() == 64)
      {
      m_private = secret_key;
      m_public.assign(&m_private[32], &m_private[64]);
      }
   else if(secret_key.size() == 32)
      {
      m_public.resize(32);
      m_private.resize(64);
      ed25519_gen_keypair(m_public.data(), m_private.data(), secret_key.data());
      }
   else
      throw Decoding_Error("Invalid size for Ed25519 private key");
   }
Beispiel #16
0
/*
* Generate one of the Sboxes
*/
void Blowfish::generate_sbox(secure_vector<uint32_t>& box,
                             uint32_t& L, uint32_t& R,
                             const uint8_t salt[],
                             size_t salt_length,
                             size_t salt_off) const
   {
   for(size_t i = 0; i != box.size(); i += 2)
      {
      if(salt_length > 0)
         {
         L ^= load_be<uint32_t>(salt, (i + salt_off) % (salt_length / 4));
         R ^= load_be<uint32_t>(salt, (i + salt_off + 1) % (salt_length / 4));
         }

      for(size_t r = 0; r != 16; r += 2)
         {
         L ^= m_P[r];
         R ^= BFF(L, m_S);

         R ^= m_P[r+1];
         L ^= BFF(R, m_S);
         }

      uint32_t T = R; R = L ^ m_P[16]; L = T ^ m_P[17];
      box[i] = L;
      box[i+1] = R;
      }
   }
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);
      }
   }
Beispiel #18
0
/*
* Generate one of the Sboxes
*/
void Blowfish::generate_sbox(secure_vector<uint32_t>& box,
                             uint32_t& L, uint32_t& R,
                             const uint8_t salt[16],
                             size_t salt_off) const
   {
   const uint32_t* S1 = &m_S[0];
   const uint32_t* S2 = &m_S[256];
   const uint32_t* S3 = &m_S[512];
   const uint32_t* S4 = &m_S[768];

   for(size_t i = 0; i != box.size(); i += 2)
      {
      L ^= load_be<uint32_t>(salt, (i + salt_off) % 4);
      R ^= load_be<uint32_t>(salt, (i + salt_off + 1) % 4);

      for(size_t j = 0; j != 16; j += 2)
         {
         L ^= m_P[j];
         R ^= ((S1[get_byte(0, L)]  + S2[get_byte(1, L)]) ^
                S3[get_byte(2, L)]) + S4[get_byte(3, L)];

         R ^= m_P[j+1];
         L ^= ((S1[get_byte(0, R)]  + S2[get_byte(1, R)]) ^
                S3[get_byte(2, R)]) + S4[get_byte(3, R)];
         }

      uint32_t T = R; R = L ^ m_P[16]; L = T ^ m_P[17];
      box[i] = L;
      box[i+1] = R;
      }
   }
Beispiel #19
0
void mceliece_decrypt(secure_vector<byte>& plaintext_out,
                      secure_vector<byte>& error_mask_out,
                      const secure_vector<byte>& ciphertext,
                      const McEliece_PrivateKey& key)
   {
   mceliece_decrypt(plaintext_out, error_mask_out, ciphertext.data(), ciphertext.size(), key);
   }
Beispiel #20
0
BigInt Montgomery_Params::redc(const BigInt& x, secure_vector<word>& ws) const
   {
   const size_t output_size = 2*m_p_words + 2;

   if(ws.size() < output_size)
      ws.resize(output_size);

   BigInt z = x;
   z.grow_to(output_size);

   bigint_monty_redc(z.mutable_data(),
                     m_p.data(), m_p_words, m_p_dash,
                     ws.data(), ws.size());

   return z;
   }
Beispiel #21
0
/*
* PSSR Encode Operation
*/
secure_vector<byte> PSSR::encoding_of(const secure_vector<byte>& msg,
                                      size_t output_bits,
                                      RandomNumberGenerator& rng)
{
    const size_t HASH_SIZE = m_hash->output_length();

    if(msg.size() != HASH_SIZE)
        throw Encoding_Error("PSSR::encoding_of: Bad input length");
    if(output_bits < 8*HASH_SIZE + 8*m_SALT_SIZE + 9)
        throw Encoding_Error("PSSR::encoding_of: Output length is too small");

    const size_t output_length = (output_bits + 7) / 8;

    secure_vector<byte> salt = rng.random_vec(m_SALT_SIZE);

    for(size_t j = 0; j != 8; ++j)
        m_hash->update(0);
    m_hash->update(msg);
    m_hash->update(salt);
    secure_vector<byte> H = m_hash->final();

    secure_vector<byte> EM(output_length);

    EM[output_length - HASH_SIZE - m_SALT_SIZE - 2] = 0x01;
    buffer_insert(EM, output_length - 1 - HASH_SIZE - m_SALT_SIZE, salt);
    mgf1_mask(*m_hash, H.data(), HASH_SIZE, EM.data(), output_length - HASH_SIZE - 1);
    EM[0] &= 0xFF >> (8 * ((output_bits + 7) / 8) - output_bits);
    buffer_insert(EM, output_length - 1 - HASH_SIZE, H);
    EM[output_length-1] = 0xBC;

    return EM;
}
Beispiel #22
0
secure_vector<uint8_t> rfc3394_keyunwrap(const secure_vector<uint8_t>& key,
                                      const SymmetricKey& kek)
   {
   if(key.size() < 16 || key.size() % 8 != 0)
      throw Invalid_Argument("Bad input key size for NIST key unwrap");

   if(kek.size() != 16 && kek.size() != 24 && kek.size() != 32)
      throw Invalid_Argument("Bad KEK length " + std::to_string(kek.size()) + " for NIST key unwrap");

   const std::string cipher_name = "AES-" + std::to_string(8*kek.size());
   std::unique_ptr<BlockCipher> aes(BlockCipher::create_or_throw(cipher_name));
   aes->set_key(kek);

   const size_t n = (key.size() - 8) / 8;

   secure_vector<uint8_t> R(n * 8);
   secure_vector<uint8_t> A(16);

   for(size_t i = 0; i != 8; ++i)
      A[i] = key[i];

   copy_mem(R.data(), &key[8], key.size() - 8);

   for(size_t j = 0; j <= 5; ++j)
      {
      for(size_t i = n; i != 0; --i)
         {
         const uint32_t t = static_cast<uint32_t>((5 - j) * n + i);

         uint8_t t_buf[4] = { 0 };
         store_be(t, t_buf);

         xor_buf(&A[4], t_buf, 4);

         copy_mem(&A[8], &R[8*(i-1)], 8);

         aes->decrypt(A.data());

         copy_mem(&R[8*(i-1)], &A[8], 8);
         }
      }

   if(load_be<uint64_t>(A.data(), 0) != 0xA6A6A6A6A6A6A6A6)
      throw Integrity_Failure("NIST key unwrap failed");

   return R;
   }
Beispiel #23
0
void Stream_Decompression::finish(secure_vector<byte>& buf, size_t offset)
   {
   if(buf.size() != offset || m_stream.get())
      process(buf, offset, m_stream->finish_flag());

   if(m_stream.get())
      throw std::runtime_error(name() + " finished but not at stream end");
   }
Beispiel #24
0
secure_vector<uint8_t> EMSA1::encoding_of(const secure_vector<uint8_t>& msg,
                                       size_t output_bits,
                                       RandomNumberGenerator&)
   {
   if(msg.size() != hash_output_length())
      throw Encoding_Error("EMSA1::encoding_of: Invalid size for input");
   return emsa1_encoding(msg, output_bits);
   }
Beispiel #25
0
void Stream_Decompression::finish(secure_vector<uint8_t>& buf, size_t offset)
   {
   if(buf.size() != offset || m_stream.get())
      process(buf, offset, m_stream->finish_flag());

   if(m_stream.get())
      throw Exception(name() + " finished but not at stream end");
   }
Beispiel #26
0
uint32_t HOTP::generate_hotp(uint64_t counter)
   {
   m_mac->update_be(counter);
   const secure_vector<uint8_t> mac = m_mac->final();

   const size_t offset = mac[mac.size()-1] & 0x0F;
   const uint32_t code = load_be<uint32_t>(mac.data() + offset, 0) & 0x7FFFFFFF;
   return code % m_digit_mod;
   }
Beispiel #27
0
secure_vector<uint8_t> rfc3394_keywrap(const secure_vector<uint8_t>& key,
                                    const SymmetricKey& kek)
   {
   if(key.size() % 8 != 0)
      throw Invalid_Argument("Bad input key size for NIST key wrap");

   if(kek.size() != 16 && kek.size() != 24 && kek.size() != 32)
      throw Invalid_Argument("Bad KEK length " + std::to_string(kek.size()) + " for NIST key wrap");

   const std::string cipher_name = "AES-" + std::to_string(8*kek.size());
   std::unique_ptr<BlockCipher> aes(BlockCipher::create_or_throw(cipher_name));
   aes->set_key(kek);

   const size_t n = key.size() / 8;

   secure_vector<uint8_t> R((n + 1) * 8);
   secure_vector<uint8_t> A(16);

   for(size_t i = 0; i != 8; ++i)
      A[i] = 0xA6;

   copy_mem(&R[8], key.data(), key.size());

   for(size_t j = 0; j <= 5; ++j)
      {
      for(size_t i = 1; i <= n; ++i)
         {
         const uint32_t t = static_cast<uint32_t>((n * j) + i);

         copy_mem(&A[8], &R[8*i], 8);

         aes->encrypt(A.data());
         copy_mem(&R[8*i], &A[8], 8);

         uint8_t t_buf[4] = { 0 };
         store_be(t, t_buf);
         xor_buf(&A[4], t_buf, 4);
         }
      }

   copy_mem(R.data(), A.data(), 8);

   return R;
   }
Beispiel #28
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 #29
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 #30
0
BigInt Montgomery_Params::sqr(const BigInt& x, secure_vector<word>& ws) const
   {
   const size_t output_size = 2*m_p_words + 2;

   if(ws.size() < output_size)
      ws.resize(output_size);

   BigInt z(BigInt::Positive, output_size);

   BOTAN_DEBUG_ASSERT(x.sig_words() <= m_p_words);

   bigint_sqr(z.mutable_data(), z.size(),
              x.data(), x.size(), std::min(m_p_words, x.size()),
              ws.data(), ws.size());

   bigint_monty_redc(z.mutable_data(),
                     m_p.data(), m_p_words, m_p_dash,
                     ws.data(), ws.size());

   return z;
   }