Пример #1
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);
   }
Пример #2
0
/*
* Modified key schedule used for bcrypt password hashing
*/
void Blowfish::salted_set_key(const uint8_t key[], size_t length,
                              const uint8_t salt[], size_t salt_length,
                              size_t workfactor)
   {
   BOTAN_ARG_CHECK(salt_length > 0 && salt_length % 4 == 0,
                   "Invalid salt length for Blowfish salted key schedule");

   if(length > 72)
      {
      // Truncate longer passwords to the 72 char bcrypt limit
      length = 72;
      }

   m_P.resize(18);
   copy_mem(m_P.data(), P_INIT, 18);

   m_S.resize(1024);
   copy_mem(m_S.data(), S_INIT, 1024);
   key_expansion(key, length, salt, salt_length);

   if(workfactor > 0)
      {
      const size_t rounds = static_cast<size_t>(1) << workfactor;

      for(size_t r = 0; r != rounds; ++r)
         {
         key_expansion(key, length, nullptr, 0);
         key_expansion(salt, salt_length, nullptr, 0);
         }
      }
   }
Пример #3
0
std::string generate_passhash9(const std::string& pass,
                               RandomNumberGenerator& rng,
                               uint16_t work_factor,
                               uint8_t alg_id)
   {
   BOTAN_ARG_CHECK(work_factor > 0 && work_factor < 512, "Invalid Passhash9 work factor");

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

   if(!prf)
      throw Invalid_Argument("Passhash9: Algorithm id " +
                             std::to_string(alg_id) +
                             " is not defined");

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

   secure_vector<uint8_t> salt(SALT_BYTES);
   rng.randomize(salt.data(), salt.size());

   const size_t kdf_iterations = WORK_FACTOR_SCALE * work_factor;

   secure_vector<uint8_t> blob;
   blob.push_back(alg_id);
   blob.push_back(get_byte(0, work_factor));
   blob.push_back(get_byte(1, work_factor));
   blob += salt;
   blob += kdf.derive_key(PASSHASH9_PBKDF_OUTPUT_LEN,
                          pass,
                          salt.data(), salt.size(),
                          kdf_iterations).bits_of();

   return MAGIC_PREFIX + base64_encode(blob);
   }
Пример #4
0
/*
* Modified key schedule used for bcrypt password hashing
*/
void Blowfish::eks_key_schedule(const uint8_t key[], size_t length,
                                const uint8_t salt[16], size_t workfactor)
   {

   /*
   * On a 2.8 GHz Core-i7, workfactor == 18 takes about 25 seconds to
   * hash a password. This seems like a reasonable upper bound for the
   * time being.
   * Bcrypt allows up to work factor 31 (2^31 iterations)
   */
   BOTAN_ARG_CHECK(workfactor >= 4 && workfactor <= 18,
                   "Invalid bcrypt work factor");

   if(length > 72)
      {
      // Truncate longer passwords to the 72 char bcrypt limit
      length = 72;
      }

   m_P.resize(18);
   copy_mem(m_P.data(), P_INIT, 18);

   m_S.resize(1024);
   copy_mem(m_S.data(), S_INIT, 1024);
   key_expansion(key, length, salt);

   const uint8_t null_salt[16] = { 0 };
   const size_t rounds = static_cast<size_t>(1) << workfactor;

   for(size_t r = 0; r != rounds; ++r)
      {
      key_expansion(key, length, null_salt);
      key_expansion(salt, 16, null_salt);
      }
   }
Пример #5
0
//static
void SHA_3::expand(size_t bitrate,
                   secure_vector<uint64_t>& S,
                   uint8_t output[], size_t output_length)
   {
   BOTAN_ARG_CHECK(bitrate % 8 == 0);

   size_t Si = 0;

   for(size_t i = 0; i != output_length; ++i)
      {
      if(i > 0)
         {
         if(i % (bitrate / 8) == 0)
            {
            SHA_3::permute(S.data());
            Si = 0;
            }
         else if(i % 8 == 0)
            {
            Si += 1;
            }
         }

      output[i] = get_byte(7 - (i % 8), S[Si]);
      }
   }
Пример #6
0
void X509_Time::encode_into(DER_Encoder& der) const
   {
   BOTAN_ARG_CHECK(m_tag == UTC_TIME || m_tag == GENERALIZED_TIME,
                   "X509_Time: Bad encoding tag");

   der.add_object(m_tag, UNIVERSAL, to_string());
   }
Пример #7
0
//static
void SHA_3::finish(size_t bitrate,
                   secure_vector<uint64_t>& S, size_t S_pos,
                   uint8_t init_pad, uint8_t fini_pad)
   {
   BOTAN_ARG_CHECK(bitrate % 64 == 0, "SHA-3 bitrate must be multiple of 64");

   S[S_pos / 8] ^= static_cast<uint64_t>(init_pad) << (8 * (S_pos % 8));
   S[(bitrate / 64) - 1] ^= static_cast<uint64_t>(fini_pad) << 56;
   SHA_3::permute(S.data());
   }
Пример #8
0
secure_vector<uint8_t> rfc3394_keywrap(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");

   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);

   std::vector<uint8_t> wrapped = nist_key_wrap(key.data(), key.size(), *aes);
   return secure_vector<uint8_t>(wrapped.begin(), wrapped.end());
   }
Пример #9
0
//static
void SHA_3::expand(size_t bitrate,
                   secure_vector<uint64_t>& S,
                   uint8_t output[], size_t output_length)
   {
   BOTAN_ARG_CHECK(bitrate % 64 == 0, "SHA-3 bitrate must be multiple of 64");

   const size_t byterate = bitrate / 8;

   while(output_length > 0)
      {
      const size_t copying = std::min(byterate, output_length);

      copy_out_vec_le(output, copying, S);

      output += copying;
      output_length -= copying;

      if(output_length > 0)
         {
         SHA_3::permute(S.data());
         }
      }
   }
Пример #10
0
void X509_Time::set_to(const std::string& t_spec, ASN1_Tag spec_tag)
   {
   if(spec_tag == UTC_OR_GENERALIZED_TIME)
      {
      try
         {
         set_to(t_spec, GENERALIZED_TIME);
         return;
         }
      catch(Invalid_Argument&) {} // Not a generalized time. Continue

      try
         {
         set_to(t_spec, UTC_TIME);
         return;
         }
      catch(Invalid_Argument&) {} // Not a UTC time. Continue

      throw Invalid_Argument("Time string could not be parsed as GeneralizedTime or UTCTime.");
      }

   BOTAN_ASSERT(spec_tag == UTC_TIME || spec_tag == GENERALIZED_TIME, "Invalid tag.");

   BOTAN_ARG_CHECK(t_spec.size() > 0, "Time string must not be empty.");

   BOTAN_ARG_CHECK(t_spec.back() == 'Z', "Botan does not support times with timezones other than Z");

   if(spec_tag == GENERALIZED_TIME)
      {
      BOTAN_ARG_CHECK(t_spec.size() == 15, "Invalid GeneralizedTime string");
      }
   else if(spec_tag == UTC_TIME)
      {
      BOTAN_ARG_CHECK(t_spec.size() == 13, "Invalid UTCTime string");
      }

   const size_t YEAR_SIZE = (spec_tag == UTC_TIME) ? 2 : 4;

   std::vector<std::string> params;
   std::string current;

   for(size_t j = 0; j != YEAR_SIZE; ++j)
      current += t_spec[j];
   params.push_back(current);
   current.clear();

   for(size_t j = YEAR_SIZE; j != t_spec.size() - 1; ++j)
      {
      current += t_spec[j];
      if(current.size() == 2)
         {
         params.push_back(current);
         current.clear();
         }
      }

   m_year   = to_u32bit(params[0]);
   m_month  = to_u32bit(params[1]);
   m_day    = to_u32bit(params[2]);
   m_hour   = to_u32bit(params[3]);
   m_minute = to_u32bit(params[4]);
   m_second = (params.size() == 6) ? to_u32bit(params[5]) : 0;
   m_tag    = spec_tag;

   if(spec_tag == UTC_TIME)
      {
      if(m_year >= 50) m_year += 1900;
      else             m_year += 2000;
      }

   if(!passes_sanity_check())
      throw Invalid_Argument("Time " + t_spec + " does not seem to be valid");
   }