Ejemplo n.º 1
0
secure_vector<byte>
mceies_decrypt(const McEliece_PrivateKey& privkey,
               const byte ct[], size_t ct_len,
               const byte ad[], size_t ad_len,
               const std::string& algo)
   {
   try
      {
      McEliece_KEM_Decryptor kem_op(privkey);

      const size_t mce_code_bytes = (privkey.get_code_length() + 7) / 8;

      std::unique_ptr<AEAD_Mode> aead(get_aead(algo, DECRYPTION));
      if(!aead)
         throw std::runtime_error("Unable to create AEAD instance '" + algo + "'");

      const size_t nonce_len = aead->default_nonce_length();

      if(ct_len < mce_code_bytes + nonce_len + aead->tag_size())
         throw std::runtime_error("Input message too small to be valid");

      const secure_vector<byte> mce_key = kem_op.decrypt(ct, mce_code_bytes);

      aead->set_key(aead_key(mce_key, *aead));
      aead->set_associated_data(ad, ad_len);

      secure_vector<byte> pt(ct + mce_code_bytes + nonce_len, ct + ct_len);

      aead->start(&ct[mce_code_bytes], nonce_len);
      aead->finish(pt, 0);
      return pt;
      }
   catch(std::exception& e)
      {
      throw std::runtime_error("mce_decrypt failed: " + std::string(e.what()));
      }
   }
Ejemplo n.º 2
0
secure_vector<byte>
mceies_encrypt(const McEliece_PublicKey& pubkey,
               const byte pt[], size_t pt_len,
               const byte ad[], size_t ad_len,
               RandomNumberGenerator& rng,
               const std::string& algo)
   {
   McEliece_KEM_Encryptor kem_op(pubkey);

   const std::pair<secure_vector<byte>,secure_vector<byte>> mce_ciphertext__key = kem_op.encrypt(rng);
   const secure_vector<byte>& mce_ciphertext = mce_ciphertext__key.first;
   const secure_vector<byte>& mce_key = mce_ciphertext__key.second;

   const size_t mce_code_bytes = (pubkey.get_code_length() + 7) / 8;

   BOTAN_ASSERT(mce_ciphertext.size() == mce_code_bytes, "Unexpected size");

   std::unique_ptr<AEAD_Mode> aead(get_aead(algo, ENCRYPTION));
   if(!aead)
      throw std::runtime_error("mce_encrypt unable to create AEAD instance '" + algo + "'");

   const size_t nonce_len = aead->default_nonce_length();

   aead->set_key(aead_key(mce_key, *aead));
   aead->set_associated_data(ad, ad_len);

   const secure_vector<byte> nonce = rng.random_vec(nonce_len);

   secure_vector<byte> msg(mce_ciphertext.size() + nonce.size() + pt_len);
   copy_mem(msg.data(), mce_ciphertext.data(), mce_ciphertext.size());
   copy_mem(msg.data() + mce_ciphertext.size(), nonce.data(), nonce.size());
   copy_mem(msg.data() + mce_ciphertext.size() + nonce.size(), pt, pt_len);

   aead->start(nonce);
   aead->finish(msg, mce_ciphertext.size() + nonce.size());
   return msg;
   }
Ejemplo n.º 3
0
Cipher_Mode* get_cipher_mode(const std::string& algo, Cipher_Dir direction)
   {
   if(auto sc = StreamCipher::create(algo))
      {
      return new Stream_Cipher_Mode(sc.release());
      }

#if defined(BOTAN_HAS_AEAD_MODES)
   if(auto aead = get_aead(algo, direction))
      {
      return aead;
      }
#endif

   if(algo.find('/') != std::string::npos)
      {
      const std::vector<std::string> algo_parts = split_on(algo, '/');
      const std::string cipher_name = algo_parts[0];
      const std::vector<std::string> mode_info = parse_algorithm_name(algo_parts[1]);

      if(mode_info.empty())
         return nullptr;

      std::ostringstream alg_args;

      alg_args << '(' << cipher_name;
      for(size_t i = 1; i < mode_info.size(); ++i)
         alg_args << ',' << mode_info[i];
      for(size_t i = 2; i < algo_parts.size(); ++i)
         alg_args << ',' << algo_parts[i];
      alg_args << ')';

      const std::string mode_name = mode_info[0] + alg_args.str();
      return get_cipher_mode(mode_name, direction);
      }

#if defined(BOTAN_HAS_BLOCK_CIPHER)

   SCAN_Name spec(algo);

   if(spec.arg_count() == 0)
      {
      return nullptr;
      }

   std::unique_ptr<BlockCipher> bc(BlockCipher::create(spec.arg(0)));

   if(!bc)
      {
      return nullptr;
      }

#if defined(BOTAN_HAS_MODE_CBC)
   if(spec.algo_name() == "CBC")
      {
      const std::string padding = spec.arg(1, "PKCS7");

      if(padding == "CTS")
         {
         if(direction == ENCRYPTION)
            return new CTS_Encryption(bc.release());
         else
            return new CTS_Decryption(bc.release());
         }
      else
         {
         std::unique_ptr<BlockCipherModePaddingMethod> pad(get_bc_pad(padding));

         if(pad)
            {
            if(direction == ENCRYPTION)
               return new CBC_Encryption(bc.release(), pad.release());
            else
               return new CBC_Decryption(bc.release(), pad.release());
            }
         }
      }
#endif

#if defined(BOTAN_HAS_MODE_XTS)
   if(spec.algo_name() == "XTS")
      {
      if(direction == ENCRYPTION)
         return new XTS_Encryption(bc.release());
      else
         return new XTS_Decryption(bc.release());
      }
#endif

#if defined(BOTAN_HAS_MODE_CFB)
   if(spec.algo_name() == "CFB")
      {
      const size_t feedback_bits = spec.arg_as_integer(1, 8*bc->block_size());
      if(direction == ENCRYPTION)
         return new CFB_Encryption(bc.release(), feedback_bits);
      else
         return new CFB_Decryption(bc.release(), feedback_bits);
      }
#endif

#endif

   return nullptr;
   }