1 /*
2 * TLS Record Handling
3 * (C) 2004-2012 Jack Lloyd
4 *     2016 Matthias Gierlings
5 *
6 * Botan is released under the Simplified BSD License (see license.txt)
7 */
8 
9 #ifndef BOTAN_TLS_RECORDS_H_
10 #define BOTAN_TLS_RECORDS_H_
11 
12 #include <botan/tls_algos.h>
13 #include <botan/tls_magic.h>
14 #include <botan/tls_version.h>
15 #include <botan/aead.h>
16 #include <vector>
17 #include <chrono>
18 #include <functional>
19 
20 namespace Botan {
21 
22 namespace TLS {
23 
24 class Ciphersuite;
25 class Session_Keys;
26 
27 class Connection_Sequence_Numbers;
28 
29 /**
30 * TLS Cipher State
31 */
32 class Connection_Cipher_State final
33    {
34    public:
35       /**
36       * Initialize a new cipher state
37       */
38       Connection_Cipher_State(Protocol_Version version,
39                               Connection_Side which_side,
40                               bool is_our_side,
41                               const Ciphersuite& suite,
42                               const Session_Keys& keys,
43                               bool uses_encrypt_then_mac);
44 
aead()45       AEAD_Mode& aead()
46          {
47          BOTAN_ASSERT_NONNULL(m_aead.get());
48          return *m_aead.get();
49          }
50 
51       std::vector<uint8_t> aead_nonce(uint64_t seq, RandomNumberGenerator& rng);
52 
53       std::vector<uint8_t> aead_nonce(const uint8_t record[], size_t record_len, uint64_t seq);
54 
55       std::vector<uint8_t> format_ad(uint64_t seq, uint8_t type,
56                                   Protocol_Version version,
57                                   uint16_t ptext_length);
58 
nonce_bytes_from_handshake()59       size_t nonce_bytes_from_handshake() const { return m_nonce_bytes_from_handshake; }
nonce_bytes_from_record()60       size_t nonce_bytes_from_record() const { return m_nonce_bytes_from_record; }
61 
nonce_format()62       Nonce_Format nonce_format() const { return m_nonce_format; }
63 
age()64       std::chrono::seconds age() const
65          {
66          return std::chrono::duration_cast<std::chrono::seconds>(
67             std::chrono::system_clock::now() - m_start_time);
68          }
69 
70    private:
71       std::chrono::system_clock::time_point m_start_time;
72       std::unique_ptr<AEAD_Mode> m_aead;
73 
74       std::vector<uint8_t> m_nonce;
75       Nonce_Format m_nonce_format;
76       size_t m_nonce_bytes_from_handshake;
77       size_t m_nonce_bytes_from_record;
78    };
79 
80 class Record_Header final
81    {
82    public:
Record_Header(uint64_t sequence,Protocol_Version version,Record_Type type)83       Record_Header(uint64_t sequence,
84                     Protocol_Version version,
85                     Record_Type type) :
86          m_needed(0),
87          m_sequence(sequence),
88          m_version(version),
89          m_type(type)
90          {}
91 
Record_Header(size_t needed)92       Record_Header(size_t needed) :
93          m_needed(needed),
94          m_sequence(0),
95          m_version(Protocol_Version()),
96          m_type(NO_RECORD)
97          {}
98 
needed()99       size_t needed() const { return m_needed; }
100 
version()101       Protocol_Version version() const
102          {
103          BOTAN_ASSERT_NOMSG(m_needed == 0);
104          return m_version;
105          }
106 
sequence()107       uint64_t sequence() const
108          {
109          BOTAN_ASSERT_NOMSG(m_needed == 0);
110          return m_sequence;
111          }
112 
epoch()113       uint16_t epoch() const
114          {
115          return static_cast<uint16_t>(sequence() >> 48);
116          }
117 
type()118       Record_Type type() const
119          {
120          BOTAN_ASSERT_NOMSG(m_needed == 0);
121          return m_type;
122          }
123 
124    private:
125       size_t m_needed;
126       uint64_t m_sequence;
127       Protocol_Version m_version;
128       Record_Type m_type;
129    };
130 
131 /**
132 * Create an initial (unencrypted) TLS handshake record
133 * @param write_buffer the output record is placed here
134 * @param record_type the record layer type
135 * @param record_version the record layer version
136 * @param record_sequence the record layer sequence number
137 * @param message the record contents
138 * @param message_len is size of message
139 */
140 void write_unencrypted_record(secure_vector<uint8_t>& write_buffer,
141                               uint8_t record_type,
142                               Protocol_Version record_version,
143                               uint64_t record_sequence,
144                               const uint8_t* message,
145                               size_t message_len);
146 
147 /**
148 * Create a TLS record
149 * @param write_buffer the output record is placed here
150 * @param record_type the record layer type
151 * @param record_version the record layer version
152 * @param record_sequence the record layer sequence number
153 * @param message the record contents
154 * @param message_len is size of message
155 * @param cipherstate is the writing cipher state
156 * @param rng is a random number generator
157 */
158 void write_record(secure_vector<uint8_t>& write_buffer,
159                   uint8_t record_type,
160                   Protocol_Version record_version,
161                   uint64_t record_sequence,
162                   const uint8_t* message,
163                   size_t message_len,
164                   Connection_Cipher_State& cipherstate,
165                   RandomNumberGenerator& rng);
166 
167 // epoch -> cipher state
168 typedef std::function<std::shared_ptr<Connection_Cipher_State> (uint16_t)> get_cipherstate_fn;
169 
170 /**
171 * Decode a TLS record
172 * @return zero if full message, else number of bytes still needed
173 */
174 Record_Header read_record(bool is_datagram,
175                           secure_vector<uint8_t>& read_buffer,
176                           const uint8_t input[],
177                           size_t input_len,
178                           size_t& consumed,
179                           secure_vector<uint8_t>& record_buf,
180                           Connection_Sequence_Numbers* sequence_numbers,
181                           get_cipherstate_fn get_cipherstate,
182                           bool allow_epoch0_restart);
183 
184 }
185 
186 }
187 
188 #endif
189