Botan  1.11.15
Classes | Typedefs | Enumerations | Functions
Botan::TLS Namespace Reference

Classes

class  Alert
class  Blocking_Client
class  Certificate
class  Certificate_Req
class  Certificate_Verify
class  Change_Cipher_Spec
class  Channel
class  Ciphersuite
class  Client
class  Client_Hello
class  Client_Key_Exchange
class  Connection_Cipher_State
class  Connection_Sequence_Numbers
class  Datagram_Handshake_IO
class  Datagram_Policy
class  Datagram_Sequence_Numbers
class  Extension
class  Extensions
class  Finished
class  Handshake_Hash
class  Handshake_IO
class  Handshake_Message
class  Handshake_State
class  Heartbeat_Message
class  Heartbeat_Support_Indicator
class  Hello_Request
class  Hello_Verify_Request
class  Maximum_Fragment_Length
class  New_Session_Ticket
class  Next_Protocol
class  Next_Protocol_Notification
class  NSA_Suite_B_128
class  Policy
class  Protocol_Version
class  Renegotiation_Extension
class  Server
class  Server_Hello
class  Server_Hello_Done
class  Server_Information
class  Server_Key_Exchange
class  Server_Name_Indicator
class  Session
class  Session_Keys
class  Session_Manager
class  Session_Manager_In_Memory
class  Session_Manager_Noop
class  Session_Manager_SQL
class  Session_Manager_SQLite
class  Session_Ticket
class  Signature_Algorithms
class  SRP_Identifier
class  SRTP_Protection_Profiles
class  Stream_Handshake_IO
class  Stream_Sequence_Numbers
class  Strict_Policy
class  Supported_Elliptic_Curves
class  Text_Policy
class  TLS_Data_Reader
class  TLS_Exception
struct  Unexpected_Message

Typedefs

typedef std::function
< std::shared_ptr
< Connection_Cipher_State >
u16bit)> 
get_cipherstate_fn

Enumerations

enum  { TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0x00FF, TLS_FALLBACK_SCSV = 0x5600 }
enum  Compression_Method { NO_COMPRESSION = 0x00, DEFLATE_COMPRESSION = 0x01 }
enum  Connection_Side { CLIENT = 1, SERVER = 2 }
enum  Handshake_Extension_Type {
  TLSEXT_SERVER_NAME_INDICATION = 0, TLSEXT_MAX_FRAGMENT_LENGTH = 1, TLSEXT_CLIENT_CERT_URL = 2, TLSEXT_TRUSTED_CA_KEYS = 3,
  TLSEXT_TRUNCATED_HMAC = 4, TLSEXT_CERTIFICATE_TYPES = 9, TLSEXT_USABLE_ELLIPTIC_CURVES = 10, TLSEXT_EC_POINT_FORMATS = 11,
  TLSEXT_SRP_IDENTIFIER = 12, TLSEXT_SIGNATURE_ALGORITHMS = 13, TLSEXT_USE_SRTP = 14, TLSEXT_HEARTBEAT_SUPPORT = 15,
  TLSEXT_SESSION_TICKET = 35, TLSEXT_NEXT_PROTOCOL = 13172, TLSEXT_SAFE_RENEGOTIATION = 65281
}
enum  Handshake_Type {
  HELLO_REQUEST = 0, CLIENT_HELLO = 1, SERVER_HELLO = 2, HELLO_VERIFY_REQUEST = 3,
  NEW_SESSION_TICKET = 4, CERTIFICATE = 11, SERVER_KEX = 12, CERTIFICATE_REQUEST = 13,
  SERVER_HELLO_DONE = 14, CERTIFICATE_VERIFY = 15, CLIENT_KEX = 16, FINISHED = 20,
  CERTIFICATE_URL = 21, CERTIFICATE_STATUS = 22, NEXT_PROTOCOL = 67, HANDSHAKE_CCS = 254,
  HANDSHAKE_NONE = 255
}
enum  Record_Type {
  CHANGE_CIPHER_SPEC = 20, ALERT = 21, HANDSHAKE = 22, APPLICATION_DATA = 23,
  HEARTBEAT = 24, NO_RECORD = 256
}
enum  Size_Limits {
  TLS_HEADER_SIZE = 5, DTLS_HEADER_SIZE = TLS_HEADER_SIZE + 8, MAX_PLAINTEXT_SIZE = 16*1024, MAX_COMPRESSED_SIZE = MAX_PLAINTEXT_SIZE + 1024,
  MAX_CIPHERTEXT_SIZE = MAX_COMPRESSED_SIZE + 1024
}

Functions

template<typename T , typename Alloc >
void append_tls_length_value (std::vector< byte, Alloc > &buf, const T *vals, size_t vals_size, size_t tag_size)
template<typename T , typename Alloc , typename Alloc2 >
void append_tls_length_value (std::vector< byte, Alloc > &buf, const std::vector< T, Alloc2 > &vals, size_t tag_size)
template<typename Alloc >
void append_tls_length_value (std::vector< byte, Alloc > &buf, const std::string &str, size_t tag_size)
std::vector< bytemake_hello_random (RandomNumberGenerator &rng, const Policy &policy)
bool operator!= (const Server_Information &a, const Server_Information &b)
bool operator< (const Server_Information &a, const Server_Information &b)
bool operator== (const Server_Information &a, const Server_Information &b)
size_t read_record (secure_vector< byte > &readbuf, const byte input[], size_t input_sz, bool is_datagram, size_t &consumed, secure_vector< byte > &record, u64bit *record_sequence, Protocol_Version *record_version, Record_Type *record_type, Connection_Sequence_Numbers *sequence_numbers, get_cipherstate_fn get_cipherstate)
void write_record (secure_vector< byte > &output, byte msg_type, const byte msg[], size_t msg_length, Protocol_Version version, u64bit seq, Connection_Cipher_State *cs, RandomNumberGenerator &rng)

Typedef Documentation

typedef std::function<std::shared_ptr<Connection_Cipher_State>u16bit)> Botan::TLS::get_cipherstate_fn

Definition at line 117 of file tls_record.h.


Enumeration Type Documentation

anonymous enum
Enumerator:
TLS_EMPTY_RENEGOTIATION_INFO_SCSV 
TLS_FALLBACK_SCSV 

Definition at line 19 of file msg_client_hello.cpp.

Enumerator:
NO_COMPRESSION 
DEFLATE_COMPRESSION 

Definition at line 62 of file tls_magic.h.

                        {
   NO_COMPRESSION       = 0x00,
   DEFLATE_COMPRESSION  = 0x01
};
Enumerator:
CLIENT 
SERVER 

Definition at line 27 of file tls_magic.h.

{ CLIENT = 1, SERVER = 2 };
Enumerator:
TLSEXT_SERVER_NAME_INDICATION 
TLSEXT_MAX_FRAGMENT_LENGTH 
TLSEXT_CLIENT_CERT_URL 
TLSEXT_TRUSTED_CA_KEYS 
TLSEXT_TRUNCATED_HMAC 
TLSEXT_CERTIFICATE_TYPES 
TLSEXT_USABLE_ELLIPTIC_CURVES 
TLSEXT_EC_POINT_FORMATS 
TLSEXT_SRP_IDENTIFIER 
TLSEXT_SIGNATURE_ALGORITHMS 
TLSEXT_USE_SRTP 
TLSEXT_HEARTBEAT_SUPPORT 
TLSEXT_SESSION_TICKET 
TLSEXT_NEXT_PROTOCOL 
TLSEXT_SAFE_RENEGOTIATION 

Definition at line 24 of file tls_extensions.h.

Enumerator:
HELLO_REQUEST 
CLIENT_HELLO 
SERVER_HELLO 
HELLO_VERIFY_REQUEST 
NEW_SESSION_TICKET 
CERTIFICATE 
SERVER_KEX 
CERTIFICATE_REQUEST 
SERVER_HELLO_DONE 
CERTIFICATE_VERIFY 
CLIENT_KEX 
FINISHED 
CERTIFICATE_URL 
CERTIFICATE_STATUS 
NEXT_PROTOCOL 
HANDSHAKE_CCS 
HANDSHAKE_NONE 

Definition at line 39 of file tls_magic.h.

                    {
   HELLO_REQUEST        = 0,
   CLIENT_HELLO         = 1,
   SERVER_HELLO         = 2,
   HELLO_VERIFY_REQUEST = 3,
   NEW_SESSION_TICKET   = 4, // RFC 5077
   CERTIFICATE          = 11,
   SERVER_KEX           = 12,
   CERTIFICATE_REQUEST  = 13,
   SERVER_HELLO_DONE    = 14,
   CERTIFICATE_VERIFY   = 15,
   CLIENT_KEX           = 16,
   FINISHED             = 20,

   CERTIFICATE_URL      = 21,
   CERTIFICATE_STATUS   = 22,

   NEXT_PROTOCOL        = 67,

   HANDSHAKE_CCS        = 254, // Not a wire value
   HANDSHAKE_NONE       = 255  // Null value
};
Enumerator:
CHANGE_CIPHER_SPEC 
ALERT 
HANDSHAKE 
APPLICATION_DATA 
HEARTBEAT 
NO_RECORD 

Definition at line 29 of file tls_magic.h.

                 {
   CHANGE_CIPHER_SPEC = 20,
   ALERT              = 21,
   HANDSHAKE          = 22,
   APPLICATION_DATA   = 23,
   HEARTBEAT          = 24,

   NO_RECORD          = 256
};

Protocol Constants for SSL/TLS

Enumerator:
TLS_HEADER_SIZE 
DTLS_HEADER_SIZE 
MAX_PLAINTEXT_SIZE 
MAX_COMPRESSED_SIZE 
MAX_CIPHERTEXT_SIZE 

Definition at line 18 of file tls_magic.h.


Function Documentation

template<typename T , typename Alloc >
void Botan::TLS::append_tls_length_value ( std::vector< byte, Alloc > &  buf,
const T *  vals,
size_t  vals_size,
size_t  tag_size 
)

Helper function for encoding length-tagged vectors

Definition at line 184 of file tls_reader.h.

References Botan::get_byte().

Referenced by append_tls_length_value(), Botan::TLS::Client_Key_Exchange::Client_Key_Exchange(), Botan::TLS::SRP_Identifier::serialize(), Botan::TLS::Renegotiation_Extension::serialize(), Botan::TLS::Next_Protocol_Notification::serialize(), and Botan::TLS::Server_Key_Exchange::Server_Key_Exchange().

   {
   const size_t T_size = sizeof(T);
   const size_t val_bytes = T_size * vals_size;

   if(tag_size != 1 && tag_size != 2)
      throw std::invalid_argument("append_tls_length_value: invalid tag size");

   if((tag_size == 1 && val_bytes > 255) ||
      (tag_size == 2 && val_bytes > 65535))
      throw std::invalid_argument("append_tls_length_value: value too large");

   for(size_t i = 0; i != tag_size; ++i)
      buf.push_back(get_byte(sizeof(val_bytes)-tag_size+i, val_bytes));

   for(size_t i = 0; i != vals_size; ++i)
      for(size_t j = 0; j != T_size; ++j)
         buf.push_back(get_byte(j, vals[i]));
   }
template<typename T , typename Alloc , typename Alloc2 >
void Botan::TLS::append_tls_length_value ( std::vector< byte, Alloc > &  buf,
const std::vector< T, Alloc2 > &  vals,
size_t  tag_size 
)

Definition at line 208 of file tls_reader.h.

References append_tls_length_value().

   {
   append_tls_length_value(buf, &vals[0], vals.size(), tag_size);
   }
template<typename Alloc >
void Botan::TLS::append_tls_length_value ( std::vector< byte, Alloc > &  buf,
const std::string &  str,
size_t  tag_size 
)

Definition at line 216 of file tls_reader.h.

References append_tls_length_value().

   {
   append_tls_length_value(buf,
                           reinterpret_cast<const byte*>(&str[0]),
                           str.size(),
                           tag_size);
   }
std::vector< byte > Botan::TLS::make_hello_random ( RandomNumberGenerator &  rng,
const Policy &  policy 
)

Definition at line 24 of file msg_client_hello.cpp.

References Botan::TLS::Policy::include_time_in_hello_random(), Botan::RandomNumberGenerator::randomize(), and Botan::store_be().

   {
   std::vector<byte> buf(32);
   rng.randomize(&buf[0], buf.size());

   if(policy.include_time_in_hello_random())
      {
      const u32bit time32 = static_cast<u32bit>(
         std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()));

      store_be(time32, &buf[0]);
      }

   return buf;
   }
bool Botan::TLS::operator!= ( const Server_Information &  a,
const Server_Information &  b 
) [inline]

Definition at line 71 of file tls_server_info.h.

   {
   return !(a == b);
   }
bool Botan::TLS::operator< ( const Server_Information &  a,
const Server_Information &  b 
) [inline]

Definition at line 76 of file tls_server_info.h.

References Botan::TLS::Server_Information::hostname(), Botan::TLS::Server_Information::port(), and Botan::TLS::Server_Information::service().

   {
   if(a.hostname() != b.hostname())
      return (a.hostname() < b.hostname());
   if(a.service() != b.service())
      return (a.service() < b.service());
   if(a.port() != b.port())
      return (a.port() < b.port());
   return false; // equal
   }
bool Botan::TLS::operator== ( const Server_Information &  a,
const Server_Information &  b 
) [inline]

Definition at line 63 of file tls_server_info.h.

References Botan::TLS::Server_Information::hostname(), Botan::TLS::Server_Information::port(), and Botan::TLS::Server_Information::service().

   {
   return (a.hostname() == b.hostname()) &&
          (a.service() == b.service()) &&
          (a.port() == b.port());

   }
size_t Botan::TLS::read_record ( secure_vector< byte > &  read_buffer,
const byte  input[],
size_t  input_length,
bool  is_datagram,
size_t &  input_consumed,
secure_vector< byte > &  record,
u64bit *  record_sequence,
Protocol_Version *  record_version,
Record_Type *  record_type,
Connection_Sequence_Numbers *  sequence_numbers,
get_cipherstate_fn  get_cipherstate 
)

Decode a TLS record

Returns:
zero if full message, else number of bytes still needed

Definition at line 631 of file tls_record.cpp.

Referenced by Botan::TLS::Channel::received_data().

   {
   if(is_datagram)
      return read_dtls_record(readbuf, input, input_sz, consumed,
                              record, record_sequence, record_version, record_type,
                              sequence_numbers, get_cipherstate);
   else
      return read_tls_record(readbuf, input, input_sz, consumed,
                             record, record_sequence, record_version, record_type,
                             sequence_numbers, get_cipherstate);
   }
void Botan::TLS::write_record ( secure_vector< byte > &  write_buffer,
byte  msg_type,
const byte  msg[],
size_t  msg_length,
Protocol_Version  version,
u64bit  msg_sequence,
Connection_Cipher_State *  cipherstate,
RandomNumberGenerator &  rng 
)

Create a TLS record

Parameters:
write_bufferthe output record is placed here
msg_typeis the type of the message (handshake, alert, ...)
msgis the plaintext message
msg_lengthis the length of msg
msg_sequenceis the sequence number
versionis the protocol version
cipherstateis the writing cipher state
rngis a random number generator
Returns:
number of bytes written to write_buffer

Definition at line 135 of file tls_record.cpp.

References Botan::TLS::Connection_Cipher_State::aead(), Botan::TLS::Connection_Cipher_State::aead_nonce(), Botan::TLS::Connection_Cipher_State::block_cipher(), Botan::TLS::Connection_Cipher_State::block_size(), BOTAN_ASSERT, BOTAN_ASSERT_EQUAL, Botan::TLS::Connection_Cipher_State::cbc_state(), Botan::Buffered_Computation::final(), Botan::TLS::Connection_Cipher_State::format_ad(), Botan::get_byte(), Botan::TLS::Protocol_Version::is_datagram_protocol(), Botan::TLS::Connection_Cipher_State::iv_size(), Botan::TLS::Connection_Cipher_State::mac(), Botan::TLS::Connection_Cipher_State::mac_size(), Botan::TLS::Protocol_Version::major_version(), MAX_CIPHERTEXT_SIZE, Botan::TLS::Protocol_Version::minor_version(), Botan::TLS::Connection_Cipher_State::nonce_bytes_from_handshake(), Botan::TLS::Connection_Cipher_State::nonce_bytes_from_record(), Botan::RandomNumberGenerator::randomize(), Botan::round_up(), Botan::TLS::Connection_Cipher_State::stream_cipher(), Botan::Buffered_Computation::update(), and Botan::xor_buf().

   {
   output.clear();

   output.push_back(msg_type);
   output.push_back(version.major_version());
   output.push_back(version.minor_version());

   if(version.is_datagram_protocol())
      {
      for(size_t i = 0; i != 8; ++i)
         output.push_back(get_byte(i, seq));
      }

   if(!cs) // initial unencrypted handshake records
      {
      output.push_back(get_byte<u16bit>(0, msg_length));
      output.push_back(get_byte<u16bit>(1, msg_length));

      output.insert(output.end(), &msg[0], &msg[msg_length]);

      return;
      }

   if(AEAD_Mode* aead = cs->aead())
      {
      const size_t ctext_size = aead->output_length(msg_length);

      const secure_vector<byte>& nonce = cs->aead_nonce(seq);

      // wrong if start returns something
      const size_t rec_size = ctext_size + cs->nonce_bytes_from_record();

      BOTAN_ASSERT(rec_size <= 0xFFFF, "Ciphertext length fits in field");
      output.push_back(get_byte<u16bit>(0, rec_size));
      output.push_back(get_byte<u16bit>(1, rec_size));

      aead->set_ad(cs->format_ad(seq, msg_type, version, msg_length));

      output += std::make_pair(&nonce[cs->nonce_bytes_from_handshake()], cs->nonce_bytes_from_record());
      BOTAN_ASSERT(aead->start(nonce).empty(), "AEAD doesn't return anything from start");

      const size_t offset = output.size();
      output += std::make_pair(&msg[0], msg_length);
      aead->finish(output, offset);

      BOTAN_ASSERT(output.size() == offset + ctext_size, "Expected size");

      BOTAN_ASSERT(output.size() < MAX_CIPHERTEXT_SIZE,
                   "Produced ciphertext larger than protocol allows");
      return;
      }

   cs->mac()->update(cs->format_ad(seq, msg_type, version, msg_length));

   cs->mac()->update(msg, msg_length);

   const size_t block_size = cs->block_size();
   const size_t iv_size = cs->iv_size();
   const size_t mac_size = cs->mac_size();

   const size_t buf_size = round_up(
      iv_size + msg_length + mac_size + (block_size ? 1 : 0),
      block_size);

   if(buf_size > MAX_CIPHERTEXT_SIZE)
      throw Internal_Error("Output record is larger than allowed by protocol");

   output.push_back(get_byte<u16bit>(0, buf_size));
   output.push_back(get_byte<u16bit>(1, buf_size));

   const size_t header_size = output.size();

   if(iv_size)
      {
      output.resize(output.size() + iv_size);
      rng.randomize(&output[output.size() - iv_size], iv_size);
      }

   output.insert(output.end(), &msg[0], &msg[msg_length]);

   output.resize(output.size() + mac_size);
   cs->mac()->final(&output[output.size() - mac_size]);

   if(block_size)
      {
      const size_t pad_val =
         buf_size - (iv_size + msg_length + mac_size + 1);

      for(size_t i = 0; i != pad_val + 1; ++i)
         output.push_back(pad_val);
      }

   if(buf_size > MAX_CIPHERTEXT_SIZE)
      throw Internal_Error("Produced ciphertext larger than protocol allows");

   BOTAN_ASSERT_EQUAL(buf_size + header_size, output.size(),
                      "Output buffer is sized properly");

   if(StreamCipher* sc = cs->stream_cipher())
      {
      sc->cipher1(&output[header_size], buf_size);
      }
   else if(BlockCipher* bc = cs->block_cipher())
      {
      secure_vector<byte>& cbc_state = cs->cbc_state();

      BOTAN_ASSERT(buf_size % block_size == 0,
                   "Buffer is an even multiple of block size");

      byte* buf = &output[header_size];

      const size_t blocks = buf_size / block_size;

      xor_buf(&buf[0], &cbc_state[0], block_size);
      bc->encrypt(&buf[0]);

      for(size_t i = 1; i < blocks; ++i)
         {
         xor_buf(&buf[block_size*i], &buf[block_size*(i-1)], block_size);
         bc->encrypt(&buf[block_size*i]);
         }

      cbc_state.assign(&buf[block_size*(blocks-1)],
                       &buf[block_size*blocks]);
      }
   else
      throw Internal_Error("NULL cipher not supported");
   }