示例#1
0
/*
* Return the hash used in generating the signature
*/
std::string X509_Object::hash_used_for_signature() const
   {
   const OID& oid = m_sig_algo.get_oid();
   const std::vector<std::string> sig_info = split_on(OIDS::lookup(oid), '/');

   if(sig_info.size() == 1 && sig_info[0] == "Ed25519")
      return "SHA-512";
   else if(sig_info.size() != 2)
      throw Internal_Error("Invalid name format found for " + oid.as_string());

   if(sig_info[1] == "EMSA4")
      {
      return OIDS::lookup(decode_pss_params(signature_algorithm().get_parameters()).hash_algo.get_oid());
      }
   else
      {
      const std::vector<std::string> pad_and_hash =
         parse_algorithm_name(sig_info[1]);

      if(pad_and_hash.size() != 2)
         {
         throw Internal_Error("Invalid name format " + sig_info[1]);
         }

      return pad_and_hash[1];
      }
   }
示例#2
0
gf2m_decomp_rootfind_state::gf2m_decomp_rootfind_state(const polyn_gf2m & polyn, uint32_t the_code_length) :
   code_length(the_code_length), m_j(0), m_j_gray(0)
   {
   gf2m coeff_3;
   gf2m coeff_head;
   std::shared_ptr<GF2m_Field> sp_field = polyn.get_sp_field();
   int deg_sigma = polyn.get_degree();
   if(deg_sigma <= 3)
      {
      throw Internal_Error("Unexpected degree in gf2m_decomp_rootfind_state");
      }

   coeff_3 = polyn.get_coef( 3);
   coeff_head = polyn.get_coef( deg_sigma); /* dummy value for SCA CM */
   if(coeff_3 != 0)
      {
      this->m_sigma_3_l = sp_field->gf_l_from_n(coeff_3);
      this->m_sigma_3_neq_0_mask = 0xFFFF;
      }
   else
      {
      // dummy value needed for timing countermeasure
      this->m_sigma_3_l = sp_field->gf_l_from_n(coeff_head);
      this->m_sigma_3_neq_0_mask = 0 ;
      }

   this->m_outer_summands =  1 + brootf_decomp__calc_sum_limit(deg_sigma);
   this->m_Lik.resize(this->m_outer_summands * sp_field->get_extension_degree());
   this->m_Aij.resize(this->m_outer_summands);
   }
示例#3
0
/*
* Compress a message
*/
void CMS_Encoder::compress(const std::string& algo)
   {
   if(!CMS_Encoder::can_compress_with(algo))
      throw Invalid_Argument("CMS_Encoder: Cannot compress with " + algo);

   Filter* compressor = 0;

#if defined(BOTAN_HAS_COMPRESSOR_ZLIB)
   if(algo == "Zlib") compressor = new Zlib_Compression;
#endif

   if(compressor == 0)
      throw Internal_Error("CMS: Couldn't get ahold of a compressor");

   Pipe pipe(compressor);
   pipe.process_msg(data);
   SecureVector<byte> compressed = pipe.read_all();

   DER_Encoder encoder;
   encoder.start_cons(SEQUENCE).
      encode(static_cast<size_t>(0)).
      encode(AlgorithmIdentifier("Compression." + algo,
                                 MemoryVector<byte>())).
      raw_bytes(make_econtent(compressed, type)).
   end_cons();

   add_layer("CMS.CompressedData", encoder);
   }
示例#4
0
std::unique_ptr<RSA_PrivateKey>
make_openssl_rsa_private_key(RandomNumberGenerator& rng, size_t rsa_bits)
   {
   if (rsa_bits > INT_MAX)
      throw Internal_Error("rsa_bits overflow");

   secure_vector<uint8_t> seed(BOTAN_SYSTEM_RNG_POLL_REQUEST);
   rng.randomize(seed.data(), seed.size());
   RAND_seed(seed.data(), seed.size());

   std::unique_ptr<BIGNUM, std::function<void (BIGNUM*)>> bn(BN_new(), BN_free);
   if(!bn)
      throw OpenSSL_Error("BN_new");
   if(!BN_set_word(bn.get(), RSA_F4))
      throw OpenSSL_Error("BN_set_word");

   std::unique_ptr<RSA, std::function<void (RSA*)>> rsa(RSA_new(), RSA_free);
   if(!rsa)
      throw OpenSSL_Error("RSA_new");
   if(!RSA_generate_key_ex(rsa.get(), rsa_bits, bn.get(), nullptr))
      throw OpenSSL_Error("RSA_generate_key_ex");

   uint8_t* der = nullptr;
   int bytes = i2d_RSAPrivateKey(rsa.get(), &der);
   if(bytes < 0)
      throw OpenSSL_Error("i2d_RSAPrivateKey");

   const secure_vector<uint8_t> keydata(der, der + bytes);
   memset(der, 0, bytes);
   free(der);
   return std::unique_ptr<Botan::RSA_PrivateKey>
      (new RSA_PrivateKey(AlgorithmIdentifier(), keydata));
   }
示例#5
0
/*
* SSL3 PRF
*/
SecureVector<byte> SSL3_PRF::derive(u32bit key_len,
                                    const byte secret[], u32bit secret_len,
                                    const byte seed[], u32bit seed_len) const
   {
   if(key_len > 416)
      throw Internal_Error("SSL3_PRF: Requested key length is too large");

   MD5 md5;
   SHA_160 sha1;

   OctetString output;

   int counter = 0;
   while(key_len)
      {
      const u32bit produce = std::min(key_len, md5.OUTPUT_LENGTH);

      output = output + next_hash(counter++, produce, md5, sha1,
                                  secret, secret_len, seed, seed_len);

      key_len -= produce;
      }

   return output.bits_of();
   }
示例#6
0
//static
CPUID::Endian_status CPUID::runtime_check_endian()
   {
   // Check runtime endian
   const uint32_t endian32 = 0x01234567;
   const uint8_t* e8 = reinterpret_cast<const uint8_t*>(&endian32);

   Endian_status endian = ENDIAN_UNKNOWN;

   if(e8[0] == 0x01 && e8[1] == 0x23 && e8[2] == 0x45 && e8[3] == 0x67)
      {
      endian = ENDIAN_BIG;
      }
   else if(e8[0] == 0x67 && e8[1] == 0x45 && e8[2] == 0x23 && e8[3] == 0x01)
      {
      endian = ENDIAN_LITTLE;
      }
   else
      {
      throw Internal_Error("Unexpected endian at runtime, neither big nor little");
      }

   // If we were compiled with a known endian, verify it matches at runtime
#if defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN)
   BOTAN_ASSERT(endian == ENDIAN_LITTLE, "Build and runtime endian match");
#elif defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN)
   BOTAN_ASSERT(endian == ENDIAN_BIG, "Build and runtime endian match");
#endif

   return endian;
   }
/**
* Randpool Constructor
*/
Randpool::Randpool(BlockCipher* cipher_in,
                   MessageAuthenticationCode* mac_in,
                   u32bit pool_blocks,
                   u32bit iter_before_reseed) :
    ITERATIONS_BEFORE_RESEED(iter_before_reseed),
    POOL_BLOCKS(pool_blocks),
    cipher(cipher_in),
    mac(mac_in)
{
    const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE;
    const u32bit OUTPUT_LENGTH = mac->OUTPUT_LENGTH;

    if(OUTPUT_LENGTH < BLOCK_SIZE ||
            !cipher->valid_keylength(OUTPUT_LENGTH) ||
            !mac->valid_keylength(OUTPUT_LENGTH))
    {
        delete cipher;
        delete mac;
        throw Internal_Error("Randpool: Invalid algorithm combination " +
                             cipher->name() + "/" + mac->name());
    }

    buffer.create(BLOCK_SIZE);
    pool.create(POOL_BLOCKS * BLOCK_SIZE);
    counter.create(12);
    seeded = false;
}
示例#8
0
/*
* Write to a TLS connection
*/
void TLS_Server::write(const byte buf[], size_t length)
   {
   if(!active)
      throw Internal_Error("TLS_Server::write called while closed");

   writer.send(APPLICATION_DATA, buf, length);
   }
示例#9
0
/*************************************************
* Randpool Constructor                           *
*************************************************/
Randpool::Randpool(const std::string& cipher_name,
                   const std::string& mac_name) :
   ITERATIONS_BEFORE_RESEED(128), POOL_BLOCKS(32)
   {
   cipher = get_block_cipher(cipher_name);
   mac = get_mac(mac_name);

   const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE;
   const u32bit OUTPUT_LENGTH = mac->OUTPUT_LENGTH;

   if(OUTPUT_LENGTH < BLOCK_SIZE ||
      !cipher->valid_keylength(OUTPUT_LENGTH) ||
      !mac->valid_keylength(OUTPUT_LENGTH))
      {
      delete cipher;
      delete mac;
      throw Internal_Error("Randpool: Invalid algorithm combination " +
                           cipher_name + "/" + mac_name);
      }

   buffer.create(BLOCK_SIZE);
   pool.create(POOL_BLOCKS * BLOCK_SIZE);
   counter.create(12);
   entropy = 0;
   }
示例#10
0
std::pair<Handshake_Type, std::vector<uint8_t>>
Datagram_Handshake_IO::Handshake_Reassembly::message() const
   {
   if(!complete())
      throw Internal_Error("Datagram_Handshake_IO - message not complete");

   return std::make_pair(static_cast<Handshake_Type>(m_msg_type), m_message);
   }
示例#11
0
/*
* Return the hash used in generating the signature
*/
std::string X509_Object::hash_used_for_signature() const
   {
   std::vector<std::string> sig_info =
      split_on(OIDS::lookup(m_sig_algo.oid), '/');

   if(sig_info.size() != 2)
      throw Internal_Error("Invalid name format found for " +
                           m_sig_algo.oid.as_string());

   std::vector<std::string> pad_and_hash =
      parse_algorithm_name(sig_info[1]);

   if(pad_and_hash.size() != 2)
      throw Internal_Error("Invalid name format " + sig_info[1]);

   return pad_and_hash[1];
   }
示例#12
0
/*
* Set the exponent
*/
void Power_Mod::set_exponent(const BigInt& e) const
   {
   if(e.is_negative())
      throw Invalid_Argument("Power_Mod::set_exponent: arg must be > 0");

   if(!m_core)
      throw Internal_Error("Power_Mod::set_exponent: m_core was NULL");
   m_core->set_exponent(e);
   }
示例#13
0
/*
* Set the base
*/
void Power_Mod::set_base(const BigInt& b) const
   {
   if(b.is_zero() || b.is_negative())
      throw Invalid_Argument("Power_Mod::set_base: arg must be > 0");

   if(!m_core)
      throw Internal_Error("Power_Mod::set_base: m_core was NULL");
   m_core->set_base(b);
   }
示例#14
0
/*
* Start a new ASN.1 EXPLICIT encoding
*/
DER_Encoder& DER_Encoder::start_explicit(uint16_t type_no)
   {
   ASN1_Tag type_tag = static_cast<ASN1_Tag>(type_no);

   // This would confuse DER_Sequence
   if(type_tag == SET)
      throw Internal_Error("DER_Encoder.start_explicit(SET) not supported");

   return start_cons(type_tag, CONTEXT_SPECIFIC);
   }
示例#15
0
const char* handshake_type_to_string(Handshake_Type type)
   {
   switch(type)
      {
      case HELLO_VERIFY_REQUEST:
         return "hello_verify_request";

      case HELLO_REQUEST:
         return "hello_request";

      case CLIENT_HELLO:
         return "client_hello";

      case SERVER_HELLO:
         return "server_hello";

      case CERTIFICATE:
         return "certificate";

      case CERTIFICATE_URL:
         return "certificate_url";

      case CERTIFICATE_STATUS:
         return "certificate_status";

      case SERVER_KEX:
         return "server_key_exchange";

      case CERTIFICATE_REQUEST:
         return "certificate_request";

      case SERVER_HELLO_DONE:
         return "server_hello_done";

      case CERTIFICATE_VERIFY:
         return "certificate_verify";

      case CLIENT_KEX:
         return "client_key_exchange";

      case NEW_SESSION_TICKET:
         return "new_session_ticket";

      case HANDSHAKE_CCS:
         return "change_cipher_spec";

      case FINISHED:
         return "finished";

      case HANDSHAKE_NONE:
         return "invalid";
      }

   throw Internal_Error("Unknown TLS handshake message type " + std::to_string(type));
   }
示例#16
0
byte Signature_Algorithms::sig_algo_code(const std::string& name)
   {
   if(name == "RSA")
      return 1;

   if(name == "DSA")
      return 2;

   if(name == "ECDSA")
      return 3;

   throw Internal_Error("Unknown sig ID " + name + " for signature_algorithms");
   }
示例#17
0
void Montgomery_Int::fix_size()
   {
   const size_t p_words = m_params->p_words();

   if(m_v.sig_words() > p_words)
      throw Internal_Error("Montgomery_Int::fix_size v too large");

   secure_vector<word>& w = m_v.get_word_vector();

   if(w.size() != p_words)
      {
      w.resize(p_words);
      w.shrink_to_fit();
      }
   }
示例#18
0
/*
* Create generator of the q-sized subgroup (DSA style generator)
*/
BigInt DL_Group::make_dsa_generator(const BigInt& p, const BigInt& q)
   {
   const BigInt e = (p - 1) / q;

   if(e == 0 || (p - 1) % q > 0)
      throw Invalid_Argument("make_dsa_generator q does not divide p-1");

   for(size_t i = 0; i != PRIME_TABLE_SIZE; ++i)
      {
      BigInt g = power_mod(PRIMES[i], e, p);
      if(g > 1)
         return g;
      }

   throw Internal_Error("DL_Group: Couldn't create a suitable generator");
   }
示例#19
0
/*
* Read from a TLS connection
*/
size_t TLS_Server::read(byte out[], size_t length)
   {
   if(!active)
      throw Internal_Error("TLS_Server::read called while closed");

   writer.flush();

   while(read_buf.size() == 0)
      {
      state_machine();
      if(active == false)
         break;
      }

   size_t got = std::min<size_t>(read_buf.size(), length);
   read_buf.read(out, got);
   return got;
   }
示例#20
0
std::string GOST_28147_89::name() const
   {
   /*
   'Guess' the right name for the sbox on the basis of the values.
   This would need to be updated if support for other sbox parameters
   is added. Preferably, we would just store the string value in the
   constructor, but can't break binary compat.
   */
   std::string sbox_name = "";
   if(SBOX[0] == 0x00072000)
      sbox_name = "R3411_94_TestParam";
   else if(SBOX[0] == 0x0002D000)
      sbox_name = "R3411_CryptoPro";
   else
      throw Internal_Error("GOST-28147 unrecognized sbox value");

   return "GOST-28147-89(" + sbox_name + ")";
   }
示例#21
0
std::pair<secure_vector<uint8_t>, std::vector<uint8_t>> TLS::Callbacks::tls_ecdh_agree(
   const std::string& curve_name,
   const std::vector<uint8_t>& peer_public_value,
   const Policy& policy,
   RandomNumberGenerator& rng,
   bool compressed)
   {
   secure_vector<uint8_t> ecdh_secret;
   std::vector<uint8_t> our_public_value;

   if(curve_name == "x25519")
      {
#if defined(BOTAN_HAS_CURVE_25519)
      if(peer_public_value.size() != 32)
         {
         throw TLS_Exception(Alert::HANDSHAKE_FAILURE, "Invalid X25519 key size");
         }

      Curve25519_PublicKey peer_key(peer_public_value);
      policy.check_peer_key_acceptable(peer_key);
      Curve25519_PrivateKey priv_key(rng);
      PK_Key_Agreement ka(priv_key, rng, "Raw");
      ecdh_secret = ka.derive_key(0, peer_key.public_value()).bits_of();

      // X25519 is always compressed but sent as "uncompressed" in TLS
      our_public_value = priv_key.public_value();
#else
      throw Internal_Error("Negotiated X25519 somehow, but it is disabled");
#endif
      }
   else
      {
      EC_Group group(OIDS::lookup(curve_name));
      ECDH_PublicKey peer_key(group, group.OS2ECP(peer_public_value));
      policy.check_peer_key_acceptable(peer_key);
      ECDH_PrivateKey priv_key(rng, group);
      PK_Key_Agreement ka(priv_key, rng, "Raw");
      ecdh_secret = ka.derive_key(0, peer_key.public_value()).bits_of();
      our_public_value = priv_key.public_value(compressed ? PointGFp::COMPRESSED : PointGFp::UNCOMPRESSED);
      }

   return std::make_pair(ecdh_secret, our_public_value);
   }
示例#22
0
byte Signature_Algorithms::hash_algo_code(const std::string& name)
   {
   if(name == "MD5")
      return 1;

   if(name == "SHA-1")
      return 2;

   if(name == "SHA-224")
      return 3;

   if(name == "SHA-256")
      return 4;

   if(name == "SHA-384")
      return 5;

   if(name == "SHA-512")
      return 6;

   throw Internal_Error("Unknown hash ID " + name + " for signature_algorithms");
   }
示例#23
0
uint8_t ECDSA_PublicKey::recovery_param(const std::vector<uint8_t>& msg,
                                        const BigInt& r,
                                        const BigInt& s) const
   {
   for(uint8_t v = 0; v != 4; ++v)
      {
      try
         {
         PointGFp R = recover_ecdsa_public_key(this->domain(), msg, r, s, v);

         if(R == this->public_point())
            {
            return v;
            }
         }
      catch(Decoding_Error&)
         {
         // try the next v
         }
      }

   throw Internal_Error("Could not determine ECDSA recovery parameter");
   }
示例#24
0
std::vector<uint8_t>
EC_Group::DER_encode(EC_Group_Encoding form) const
   {
   if(form == EC_DOMPAR_ENC_EXPLICIT)
      {
      const size_t ecpVers1 = 1;
      OID curve_type("1.2.840.10045.1.1");

      const size_t p_bytes = m_curve.get_p().bytes();

      return DER_Encoder()
         .start_cons(SEQUENCE)
            .encode(ecpVers1)
            .start_cons(SEQUENCE)
               .encode(curve_type)
               .encode(m_curve.get_p())
            .end_cons()
            .start_cons(SEQUENCE)
               .encode(BigInt::encode_1363(m_curve.get_a(), p_bytes),
                       OCTET_STRING)
               .encode(BigInt::encode_1363(m_curve.get_b(), p_bytes),
                       OCTET_STRING)
            .end_cons()
            .encode(EC2OSP(m_base_point, PointGFp::UNCOMPRESSED), OCTET_STRING)
            .encode(m_order)
            .encode(m_cofactor)
         .end_cons()
         .get_contents_unlocked();
      }
   else if(form == EC_DOMPAR_ENC_OID)
      return DER_Encoder().encode(OID(get_oid())).get_contents_unlocked();
   else if(form == EC_DOMPAR_ENC_IMPLICITCA)
      return DER_Encoder().encode_null().get_contents_unlocked();
   else
      throw Internal_Error("EC_Group::DER_encode: Unknown encoding");
   }
示例#25
0
/*
* Read a Client Key Exchange message
*/
Client_Key_Exchange::Client_Key_Exchange(const std::vector<byte>& contents,
                                         const Handshake_State& state,
                                         const Private_Key* server_rsa_kex_key,
                                         Credentials_Manager& creds,
                                         const Policy& policy,
                                         RandomNumberGenerator& rng)
   {
   const std::string kex_algo = state.ciphersuite().kex_algo();

   if(kex_algo == "RSA")
      {
      BOTAN_ASSERT(state.server_certs() && !state.server_certs()->cert_chain().empty(),
                   "RSA key exchange negotiated so server sent a certificate");

      if(!server_rsa_kex_key)
         throw Internal_Error("Expected RSA kex but no server kex key set");

      if(!dynamic_cast<const RSA_PrivateKey*>(server_rsa_kex_key))
         throw Internal_Error("Expected RSA key but got " + server_rsa_kex_key->algo_name());

      PK_Decryptor_EME decryptor(*server_rsa_kex_key, "PKCS1v15");

      Protocol_Version client_version = state.client_hello()->version();

      /*
      * This is used as the pre-master if RSA decryption fails.
      * Otherwise we can be used as an oracle. See Bleichenbacher
      * "Chosen Ciphertext Attacks against Protocols Based on RSA
      * Encryption Standard PKCS #1", Crypto 98
      *
      * Create it here instead if in the catch clause as otherwise we
      * expose a timing channel WRT the generation of the fake value.
      * Some timing channel likely remains due to exception handling
      * and the like.
      */
      secure_vector<byte> fake_pre_master = rng.random_vec(48);
      fake_pre_master[0] = client_version.major_version();
      fake_pre_master[1] = client_version.minor_version();

      try
         {
         TLS_Data_Reader reader("ClientKeyExchange", contents);
         m_pre_master = decryptor.decrypt(reader.get_range<byte>(2, 0, 65535));

         if(m_pre_master.size() != 48 ||
            client_version.major_version() != m_pre_master[0] ||
            client_version.minor_version() != m_pre_master[1])
            {
            throw Decoding_Error("Client_Key_Exchange: Secret corrupted");
            }
         }
      catch(...)
         {
         m_pre_master = fake_pre_master;
         }
      }
   else
      {
      TLS_Data_Reader reader("ClientKeyExchange", contents);

      SymmetricKey psk;

      if(kex_algo == "PSK" || kex_algo == "DHE_PSK" || kex_algo == "ECDHE_PSK")
         {
         const std::string psk_identity = reader.get_string(2, 0, 65535);

         psk = creds.psk("tls-server",
                         state.client_hello()->sni_hostname(),
                         psk_identity);

         if(psk.length() == 0)
            {
            if(policy.hide_unknown_users())
               psk = SymmetricKey(rng, 16);
            else
               throw TLS_Exception(Alert::UNKNOWN_PSK_IDENTITY,
                                   "No PSK for identifier " + psk_identity);
            }
         }

      if(kex_algo == "PSK")
         {
         std::vector<byte> zeros(psk.length());
         append_tls_length_value(m_pre_master, zeros, 2);
         append_tls_length_value(m_pre_master, psk.bits_of(), 2);
         }
#if defined(BOTAN_HAS_SRP6)
      else if(kex_algo == "SRP_SHA")
         {
         SRP6_Server_Session& srp = state.server_kex()->server_srp_params();

         m_pre_master = srp.step2(BigInt::decode(reader.get_range<byte>(2, 0, 65535))).bits_of();
         }
#endif
      else if(kex_algo == "DH" || kex_algo == "DHE_PSK" ||
              kex_algo == "ECDH" || kex_algo == "ECDHE_PSK")
         {
         const Private_Key& private_key = state.server_kex()->server_kex_key();

         const PK_Key_Agreement_Key* ka_key =
            dynamic_cast<const PK_Key_Agreement_Key*>(&private_key);

         if(!ka_key)
            throw Internal_Error("Expected key agreement key type but got " +
                                 private_key.algo_name());

         try
            {
            PK_Key_Agreement ka(*ka_key, "Raw");

            std::vector<byte> client_pubkey;

            if(ka_key->algo_name() == "DH")
               client_pubkey = reader.get_range<byte>(2, 0, 65535);
            else
               client_pubkey = reader.get_range<byte>(1, 0, 255);

            secure_vector<byte> shared_secret = ka.derive_key(0, client_pubkey).bits_of();

            if(ka_key->algo_name() == "DH")
               shared_secret = CT::strip_leading_zeros(shared_secret);

            if(kex_algo == "DHE_PSK" || kex_algo == "ECDHE_PSK")
               {
               append_tls_length_value(m_pre_master, shared_secret, 2);
               append_tls_length_value(m_pre_master, psk.bits_of(), 2);
               }
            else
               m_pre_master = shared_secret;
            }
         catch(std::exception &)
            {
            /*
            * Something failed in the DH computation. To avoid possible
            * timing attacks, randomize the pre-master output and carry
            * on, allowing the protocol to fail later in the finished
            * checks.
            */
            m_pre_master = rng.random_vec(ka_key->public_value().size());
            }
         }
      else
         throw Internal_Error("Client_Key_Exchange: Unknown kex type " + kex_algo);
      }
   }
示例#26
0
/*
* Process a handshake message
*/
void TLS_Server::process_handshake_msg(Handshake_Type type,
                                       const MemoryRegion<byte>& contents)
   {
   rng.add_entropy(&contents[0], contents.size());

   if(state == 0)
      throw Unexpected_Message("Unexpected handshake message");

   if(active && (type == CLIENT_HELLO || type == CLIENT_HELLO_SSLV2))
      {
      delete state;
      state = 0;
      writer.alert(WARNING, NO_RENEGOTIATION);
      return;
      }

   if(type != HANDSHAKE_CCS && type != FINISHED)
      {
      if(type != CLIENT_HELLO_SSLV2)
         {
         state->hash.update(static_cast<byte>(type));

         const size_t record_length = contents.size();
         for(size_t i = 0; i != 3; i++)
            state->hash.update(get_byte<u32bit>(i+1, record_length));
         }

      state->hash.update(contents);
      }

   if(type == CLIENT_HELLO || type == CLIENT_HELLO_SSLV2)
      {
      server_check_state(type, state);

      state->client_hello = new Client_Hello(contents, type);

      client_requested_hostname = state->client_hello->hostname();

      state->version = choose_version(state->client_hello->version(),
                                      policy.min_version());

      writer.set_version(state->version);
      reader.set_version(state->version);

      state->server_hello = new Server_Hello(rng, writer,
                                             policy, cert_chain,
                                             *(state->client_hello),
                                             state->version, state->hash);

      state->suite = CipherSuite(state->server_hello->ciphersuite());

      if(state->suite.sig_type() != TLS_ALGO_SIGNER_ANON)
         {
         // FIXME: should choose certs based on sig type
         state->server_certs = new Certificate(writer, cert_chain,
                                               state->hash);
         }

      state->kex_priv = PKCS8::copy_key(*private_key, rng);
      if(state->suite.kex_type() != TLS_ALGO_KEYEXCH_NOKEX)
         {
         if(state->suite.kex_type() == TLS_ALGO_KEYEXCH_RSA)
            {
            state->kex_priv = new RSA_PrivateKey(rng,
                                                 policy.rsa_export_keysize());
            }
         else if(state->suite.kex_type() == TLS_ALGO_KEYEXCH_DH)
            {
            state->kex_priv = new DH_PrivateKey(rng, policy.dh_group());
            }
         else
            throw Internal_Error("TLS_Server: Unknown ciphersuite kex type");

         state->server_kex =
            new Server_Key_Exchange(rng, writer,
                                    state->kex_priv, private_key,
                                    state->client_hello->random(),
                                    state->server_hello->random(),
                                    state->hash);
         }

      if(policy.require_client_auth())
         {
         state->do_client_auth = true;
         throw Internal_Error("Client auth not implemented");
         // FIXME: send client auth request here
         }

      state->server_hello_done = new Server_Hello_Done(writer, state->hash);
      }
   else if(type == CERTIFICATE)
      {
      server_check_state(type, state);
      // FIXME: process this
      }
   else if(type == CLIENT_KEX)
      {
      server_check_state(type, state);

      state->client_kex = new Client_Key_Exchange(contents, state->suite,
                                                  state->version);

      SecureVector<byte> pre_master =
         state->client_kex->pre_master_secret(rng, state->kex_priv,
                                              state->server_hello->version());

      state->keys = SessionKeys(state->suite, state->version, pre_master,
                                state->client_hello->random(),
                                state->server_hello->random());
     }
   else if(type == CERTIFICATE_VERIFY)
      {
      server_check_state(type, state);
      // FIXME: process this
      }
   else if(type == HANDSHAKE_CCS)
      {
      server_check_state(type, state);

      reader.set_keys(state->suite, state->keys, SERVER);
      state->got_client_ccs = true;
      }
   else if(type == FINISHED)
      {
      server_check_state(type, state);

      state->client_finished = new Finished(contents);

      if(!state->client_finished->verify(state->keys.master_secret(),
                                         state->version, state->hash, CLIENT))
         throw TLS_Exception(DECRYPT_ERROR,
                             "Finished message didn't verify");

      state->hash.update(static_cast<byte>(type));

      const size_t record_length = contents.size();
      for(size_t i = 0; i != 3; i++)
         state->hash.update(get_byte<u32bit>(i+1, record_length));

      state->hash.update(contents);

      writer.send(CHANGE_CIPHER_SPEC, 1);
      writer.flush();

      writer.set_keys(state->suite, state->keys, SERVER);

      state->server_finished = new Finished(writer, state->version, SERVER,
                                            state->keys.master_secret(),
                                            state->hash);

      delete state;
      state = 0;
      active = true;
      }
   else
      throw Unexpected_Message("Unknown handshake message received");
   }
示例#27
0
SymmetricKey Credentials_Manager::psk(const std::string&,
                                      const std::string&,
                                      const std::string& identity)
   {
   throw Internal_Error("No PSK set for identity " + identity);
   }
示例#28
0
/*
* Compute the result
*/
BigInt Power_Mod::execute() const
   {
   if(!m_core)
      throw Internal_Error("Power_Mod::execute: m_core was NULL");
   return m_core->execute();
   }
示例#29
0
/*
* Create a new Client Key Exchange message
*/
Client_Key_Exchange::Client_Key_Exchange(Handshake_IO& io,
                                         Handshake_State& state,
                                         const Policy& policy,
                                         Credentials_Manager& creds,
                                         const Public_Key* server_public_key,
                                         const std::string& hostname,
                                         RandomNumberGenerator& rng)
   {
   const std::string kex_algo = state.ciphersuite().kex_algo();

   if(kex_algo == "PSK")
      {
      std::string identity_hint = "";

      if(state.server_kex())
         {
         TLS_Data_Reader reader("ClientKeyExchange", state.server_kex()->params());
         identity_hint = reader.get_string(2, 0, 65535);
         }

      const std::string psk_identity = creds.psk_identity("tls-client",
                                                          hostname,
                                                          identity_hint);

      append_tls_length_value(m_key_material, psk_identity, 2);

      SymmetricKey psk = creds.psk("tls-client", hostname, psk_identity);

      std::vector<byte> zeros(psk.length());

      append_tls_length_value(m_pre_master, zeros, 2);
      append_tls_length_value(m_pre_master, psk.bits_of(), 2);
      }
   else if(state.server_kex())
      {
      TLS_Data_Reader reader("ClientKeyExchange", state.server_kex()->params());

      SymmetricKey psk;

      if(kex_algo == "DHE_PSK" || kex_algo == "ECDHE_PSK")
         {
         std::string identity_hint = reader.get_string(2, 0, 65535);

         const std::string psk_identity = creds.psk_identity("tls-client",
                                                             hostname,
                                                             identity_hint);

         append_tls_length_value(m_key_material, psk_identity, 2);

         psk = creds.psk("tls-client", hostname, psk_identity);
         }

      if(kex_algo == "DH" || kex_algo == "DHE_PSK")
         {
         BigInt p = BigInt::decode(reader.get_range<byte>(2, 1, 65535));
         BigInt g = BigInt::decode(reader.get_range<byte>(2, 1, 65535));
         BigInt Y = BigInt::decode(reader.get_range<byte>(2, 1, 65535));

         if(reader.remaining_bytes())
            throw Decoding_Error("Bad params size for DH key exchange");

         if(p.bits() < policy.minimum_dh_group_size())
            throw TLS_Exception(Alert::INSUFFICIENT_SECURITY,
                                "Server sent DH group of " +
                                std::to_string(p.bits()) +
                                " bits, policy requires at least " +
                                std::to_string(policy.minimum_dh_group_size()));

         /*
         * A basic check for key validity. As we do not know q here we
         * cannot check that Y is in the right subgroup. However since
         * our key is ephemeral there does not seem to be any
         * advantage to bogus keys anyway.
         */
         if(Y <= 1 || Y >= p - 1)
            throw TLS_Exception(Alert::INSUFFICIENT_SECURITY,
                                "Server sent bad DH key for DHE exchange");

         DL_Group group(p, g);

         if(!group.verify_group(rng, false))
            throw TLS_Exception(Alert::INSUFFICIENT_SECURITY,
                                "DH group validation failed");

         DH_PublicKey counterparty_key(group, Y);

         DH_PrivateKey priv_key(rng, group);

         PK_Key_Agreement ka(priv_key, "Raw");

         secure_vector<byte> dh_secret = CT::strip_leading_zeros(
            ka.derive_key(0, counterparty_key.public_value()).bits_of());

         if(kex_algo == "DH")
            m_pre_master = dh_secret;
         else
            {
            append_tls_length_value(m_pre_master, dh_secret, 2);
            append_tls_length_value(m_pre_master, psk.bits_of(), 2);
            }

         append_tls_length_value(m_key_material, priv_key.public_value(), 2);
         }
      else if(kex_algo == "ECDH" || kex_algo == "ECDHE_PSK")
         {
         const byte curve_type = reader.get_byte();

         if(curve_type != 3)
            throw Decoding_Error("Server sent non-named ECC curve");

         const u16bit curve_id = reader.get_u16bit();

         const std::string name = Supported_Elliptic_Curves::curve_id_to_name(curve_id);

         if(name == "")
            throw Decoding_Error("Server sent unknown named curve " + std::to_string(curve_id));

         EC_Group group(name);

         std::vector<byte> ecdh_key = reader.get_range<byte>(1, 1, 255);

         ECDH_PublicKey counterparty_key(group, OS2ECP(ecdh_key, group.get_curve()));

         ECDH_PrivateKey priv_key(rng, group);

         PK_Key_Agreement ka(priv_key, "Raw");

         secure_vector<byte> ecdh_secret =
            ka.derive_key(0, counterparty_key.public_value()).bits_of();

         if(kex_algo == "ECDH")
            m_pre_master = ecdh_secret;
         else
            {
            append_tls_length_value(m_pre_master, ecdh_secret, 2);
            append_tls_length_value(m_pre_master, psk.bits_of(), 2);
            }

         append_tls_length_value(m_key_material, priv_key.public_value(), 1);
         }
#if defined(BOTAN_HAS_SRP6)
      else if(kex_algo == "SRP_SHA")
         {
         const BigInt N = BigInt::decode(reader.get_range<byte>(2, 1, 65535));
         const BigInt g = BigInt::decode(reader.get_range<byte>(2, 1, 65535));
         std::vector<byte> salt = reader.get_range<byte>(1, 1, 255);
         const BigInt B = BigInt::decode(reader.get_range<byte>(2, 1, 65535));

         const std::string srp_group = srp6_group_identifier(N, g);

         const std::string srp_identifier =
            creds.srp_identifier("tls-client", hostname);

         const std::string srp_password =
            creds.srp_password("tls-client", hostname, srp_identifier);

         std::pair<BigInt, SymmetricKey> srp_vals =
            srp6_client_agree(srp_identifier,
                              srp_password,
                              srp_group,
                              "SHA-1",
                              salt,
                              B,
                              rng);

         append_tls_length_value(m_key_material, BigInt::encode(srp_vals.first), 2);
         m_pre_master = srp_vals.second.bits_of();
         }
#endif
      else
         {
         throw Internal_Error("Client_Key_Exchange: Unknown kex " +
                              kex_algo);
         }

      reader.assert_done();
      }
   else
      {
      // No server key exchange msg better mean RSA kex + RSA key in cert

      if(kex_algo != "RSA")
         throw Unexpected_Message("No server kex but negotiated kex " + kex_algo);

      if(!server_public_key)
         throw Internal_Error("No server public key for RSA exchange");

      if(auto rsa_pub = dynamic_cast<const RSA_PublicKey*>(server_public_key))
         {
         const Protocol_Version offered_version = state.client_hello()->version();

         m_pre_master = rng.random_vec(48);
         m_pre_master[0] = offered_version.major_version();
         m_pre_master[1] = offered_version.minor_version();

         PK_Encryptor_EME encryptor(*rsa_pub, "PKCS1v15");

         const std::vector<byte> encrypted_key = encryptor.encrypt(m_pre_master, rng);

         append_tls_length_value(m_key_material, encrypted_key, 2);
         }
      else
         throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
                             "Expected a RSA key in server cert but got " +
                             server_public_key->algo_name());
      }

   state.hash().update(io.send(*this));
   }
示例#30
0
/**
* Create a new Server Key Exchange message
*/
Server_Key_Exchange::Server_Key_Exchange(Handshake_IO& io,
                                         Handshake_State& state,
                                         const Policy& policy,
                                         Credentials_Manager& creds,
                                         RandomNumberGenerator& rng,
                                         const Private_Key* signing_key)
   {
   const std::string hostname = state.client_hello()->sni_hostname();
   const Kex_Algo kex_algo = state.ciphersuite().kex_method();

   if(kex_algo == Kex_Algo::PSK || kex_algo == Kex_Algo::DHE_PSK || kex_algo == Kex_Algo::ECDHE_PSK)
      {
      std::string identity_hint =
         creds.psk_identity_hint("tls-server", hostname);

      append_tls_length_value(m_params, identity_hint, 2);
      }

   if(kex_algo == Kex_Algo::DH || kex_algo == Kex_Algo::DHE_PSK)
      {
      const std::vector<Group_Params> dh_groups = state.client_hello()->supported_dh_groups();

      Group_Params shared_group = Group_Params::NONE;

      /*
      If the client does not send any DH groups in the supported groups
      extension, but does offer DH ciphersuites, we select a group arbitrarily
      */

      if(dh_groups.empty())
         {
         shared_group = policy.default_dh_group();
         }
      else
         {
         shared_group = policy.choose_key_exchange_group(dh_groups);
         }

      if(shared_group == Group_Params::NONE)
         throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
               "Could not agree on a DH group with the client");

      BOTAN_ASSERT(group_param_is_dh(shared_group), "DH groups for the DH ciphersuites god");

      const std::string group_name = state.callbacks().tls_decode_group_param(shared_group);
      std::unique_ptr<DH_PrivateKey> dh(new DH_PrivateKey(rng, DL_Group(group_name)));

      append_tls_length_value(m_params, BigInt::encode(dh->get_domain().get_p()), 2);
      append_tls_length_value(m_params, BigInt::encode(dh->get_domain().get_g()), 2);
      append_tls_length_value(m_params, dh->public_value(), 2);
      m_kex_key.reset(dh.release());
      }
   else if(kex_algo == Kex_Algo::ECDH || kex_algo == Kex_Algo::ECDHE_PSK)
      {
      const std::vector<Group_Params> ec_groups = state.client_hello()->supported_ecc_curves();

      if(ec_groups.empty())
         throw Internal_Error("Client sent no ECC extension but we negotiated ECDH");

      Group_Params shared_group = policy.choose_key_exchange_group(ec_groups);

      if(shared_group == Group_Params::NONE)
         throw TLS_Exception(Alert::HANDSHAKE_FAILURE, "No shared ECC group with client");

      std::vector<uint8_t> ecdh_public_val;

      if(shared_group == Group_Params::X25519)
         {
#if defined(BOTAN_HAS_CURVE_25519)
         std::unique_ptr<Curve25519_PrivateKey> x25519(new Curve25519_PrivateKey(rng));
         ecdh_public_val = x25519->public_value();
         m_kex_key.reset(x25519.release());
#else
         throw Internal_Error("Negotiated X25519 somehow, but it is disabled");
#endif
         }
      else
         {
         Group_Params curve = policy.choose_key_exchange_group(ec_groups);

         const std::string curve_name = state.callbacks().tls_decode_group_param(curve);

         EC_Group ec_group(curve_name);
         std::unique_ptr<ECDH_PrivateKey> ecdh(new ECDH_PrivateKey(rng, ec_group));

         // follow client's preference for point compression
         ecdh_public_val = ecdh->public_value(
            state.client_hello()->prefers_compressed_ec_points() ?
            PointGFp::COMPRESSED : PointGFp::UNCOMPRESSED);

         m_kex_key.reset(ecdh.release());
         }

      const uint16_t named_curve_id = static_cast<uint16_t>(shared_group);
      m_params.push_back(3); // named curve
      m_params.push_back(get_byte(0, named_curve_id));
      m_params.push_back(get_byte(1, named_curve_id));

      append_tls_length_value(m_params, ecdh_public_val, 1);
      }
#if defined(BOTAN_HAS_SRP6)
   else if(kex_algo == Kex_Algo::SRP_SHA)
      {
      const std::string srp_identifier = state.client_hello()->srp_identifier();

      std::string group_id;
      BigInt v;
      std::vector<uint8_t> salt;

      const bool found = creds.srp_verifier("tls-server", hostname,
                                            srp_identifier,
                                            group_id, v, salt,
                                            policy.hide_unknown_users());

      if(!found)
         throw TLS_Exception(Alert::UNKNOWN_PSK_IDENTITY,
                             "Unknown SRP user " + srp_identifier);

      m_srp_params.reset(new SRP6_Server_Session);

      BigInt B = m_srp_params->step1(v, group_id,
                                     "SHA-1", rng);

      DL_Group group(group_id);

      append_tls_length_value(m_params, BigInt::encode(group.get_p()), 2);
      append_tls_length_value(m_params, BigInt::encode(group.get_g()), 2);
      append_tls_length_value(m_params, salt, 1);
      append_tls_length_value(m_params, BigInt::encode(B), 2);
      }
#endif
#if defined(BOTAN_HAS_CECPQ1)
   else if(kex_algo == Kex_Algo::CECPQ1)
      {
      std::vector<uint8_t> cecpq1_offer(CECPQ1_OFFER_BYTES);
      m_cecpq1_key.reset(new CECPQ1_key);
      CECPQ1_offer(cecpq1_offer.data(), m_cecpq1_key.get(), rng);
      append_tls_length_value(m_params, cecpq1_offer, 2);
      }
#endif
   else if(kex_algo != Kex_Algo::PSK)
      {
      throw Internal_Error("Server_Key_Exchange: Unknown kex type " +
                           kex_method_to_string(kex_algo));
      }

   if(state.ciphersuite().signature_used())
      {
      BOTAN_ASSERT(signing_key, "Signing key was set");

      std::pair<std::string, Signature_Format> format =
         state.choose_sig_format(*signing_key, m_scheme, false, policy);

      std::vector<uint8_t> buf = state.client_hello()->random();

      buf += state.server_hello()->random();
      buf += params();

      m_signature =
         state.callbacks().tls_sign_message(*signing_key, rng,
                                            format.first, format.second, buf);
      }

   state.hash().update(io.send(*this));
   }