Пример #1
0
void CCM_Decryption::finish(secure_vector<uint8_t>& 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;
   uint8_t* buf = buffer.data() + offset;

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

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

   const BlockCipher& E = cipher();

   secure_vector<uint8_t> T(CCM_BS);
   E.encrypt(format_b0(sz - tag_size()), T);

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

   secure_vector<uint8_t> C = format_c0();

   secure_vector<uint8_t> S0(CCM_BS);
   E.encrypt(C, S0);
   inc(C);

   secure_vector<uint8_t> X(CCM_BS);

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

   while(buf != buf_end)
      {
      const size_t to_proc = std::min<size_t>(CCM_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(!constant_time_compare(T.data(), buf_end, tag_size()))
      throw Integrity_Failure("CCM tag check failed");

   buffer.resize(buffer.size() - tag_size());
   }
Пример #2
0
bool check_passhash9(const std::string& pass, const std::string& hash)
   {
   const size_t BINARY_LENGTH =
     ALGID_BYTES +
     WORKFACTOR_BYTES +
     PASSHASH9_PBKDF_OUTPUT_LEN +
     SALT_BYTES;

   const size_t BASE64_LENGTH =
      MAGIC_PREFIX.size() + (BINARY_LENGTH * 8) / 6;

   if(hash.size() != BASE64_LENGTH)
      return false;

   for(size_t i = 0; i != MAGIC_PREFIX.size(); ++i)
      if(hash[i] != MAGIC_PREFIX[i])
         return false;

   secure_vector<uint8_t> bin = base64_decode(hash.c_str() + MAGIC_PREFIX.size());

   if(bin.size() != BINARY_LENGTH)
      return false;

   uint8_t alg_id = bin[0];

   const size_t work_factor = load_be<uint16_t>(&bin[ALGID_BYTES], 0);

   // Bug in the format, bad states shouldn't be representable, but are...
   if(work_factor == 0)
      return false;

   if(work_factor > 512)
      throw Invalid_Argument("Requested passhash9 work factor " +
                             std::to_string(work_factor) + " is too large");

   const size_t kdf_iterations = WORK_FACTOR_SCALE * work_factor;

   std::unique_ptr<MessageAuthenticationCode> pbkdf_prf = get_pbkdf_prf(alg_id);

   if(!pbkdf_prf)
      return false; // unknown algorithm, reject

   PKCS5_PBKDF2 kdf(pbkdf_prf.release()); // takes ownership of pointer

   secure_vector<uint8_t> cmp = kdf.derive_key(
      PASSHASH9_PBKDF_OUTPUT_LEN,
      pass,
      &bin[ALGID_BYTES + WORKFACTOR_BYTES], SALT_BYTES,
      kdf_iterations).bits_of();

   return constant_time_compare(cmp.data(),
                   &bin[ALGID_BYTES + WORKFACTOR_BYTES + SALT_BYTES],
                   PASSHASH9_PBKDF_OUTPUT_LEN);
   }
Пример #3
0
secure_vector<uint8_t>
RTSS_Share::reconstruct(const std::vector<RTSS_Share>& shares)
   {
   if(shares.size() <= 1)
      throw Decoding_Error("Insufficient shares to do TSS reconstruction");

   for(size_t i = 0; i != shares.size(); ++i)
      {
      if(shares[i].size() < RTSS_HEADER_SIZE + 1)
         throw Decoding_Error("Missing or malformed RTSS header");

      if(shares[i].share_id() == 0)
         throw Decoding_Error("Invalid (id = 0) RTSS share detected");

      if(i > 0)
         {
         if(shares[i].size() != shares[0].size())
            throw Decoding_Error("Different sized RTSS shares detected");

         if(!same_mem(&shares[0].m_contents[0],
                      &shares[i].m_contents[0], RTSS_HEADER_SIZE))
            throw Decoding_Error("Different RTSS headers detected");
         }
      }

   const uint8_t N = shares[0].m_contents[17];

   if(shares.size() < N)
      throw Decoding_Error("Insufficient shares to do TSS reconstruction");

   const uint16_t share_len = make_uint16(shares[0].m_contents[18],
                                          shares[0].m_contents[19]);

   const uint8_t hash_id = shares[0].m_contents[16];
   std::unique_ptr<HashFunction> hash(get_rtss_hash_by_id(hash_id));
   const size_t hash_len = (hash ? hash->output_length() : 0);

   if(shares[0].size() != RTSS_HEADER_SIZE + share_len)
      {
      /*
      * This second (laxer) check accomodates a bug in TSS that was
      * fixed in 2.9.0 - previous versions used the length of the
      * *secret* here, instead of the length of the *share*, which is
      * precisely 1 + hash_len longer.
      */
      if(shares[0].size() <= RTSS_HEADER_SIZE + 1 + hash_len)
         throw Decoding_Error("Bad RTSS length field in header");
      }

   std::vector<uint8_t> V(shares.size());
   secure_vector<uint8_t> recovered;

   for(size_t i = RTSS_HEADER_SIZE + 1; i != shares[0].size(); ++i)
      {
      for(size_t j = 0; j != V.size(); ++j)
         V[j] = shares[j].m_contents[i];

      uint8_t r = 0;
      for(size_t k = 0; k != shares.size(); ++k)
         {
         // L_i function:
         uint8_t r2 = 1;
         for(size_t l = 0; l != shares.size(); ++l)
            {
            if(k == l)
               continue;

            uint8_t share_k = shares[k].share_id();
            uint8_t share_l = shares[l].share_id();

            if(share_k == share_l)
               throw Decoding_Error("Duplicate shares found in RTSS recovery");

            uint8_t div = RTSS_EXP[(255 +
                                 RTSS_LOG[share_l] -
                                 RTSS_LOG[share_k ^ share_l]) % 255];

            r2 = gfp_mul(r2, div);
            }

         r ^= gfp_mul(V[k], r2);
         }
      recovered.push_back(r);
      }

   if(hash)
      {
      if(recovered.size() < hash->output_length())
         throw Decoding_Error("RTSS recovered value too short to be valid");

      const size_t secret_len = recovered.size() - hash->output_length();

      hash->update(recovered.data(), secret_len);
      secure_vector<uint8_t> hash_check = hash->final();

      if(!constant_time_compare(hash_check.data(),
                                &recovered[secret_len],
                                hash->output_length()))
         {
         throw Decoding_Error("RTSS hash check failed");
         }

      // remove the trailing hash value
      recovered.resize(secret_len);
      }

   return recovered;
   }