aboutsummaryrefslogtreecommitdiffstats
path: root/src/tls/rec_read.cpp
blob: e640cd5eb4aca086040ed225e60ff76c533082c4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/*
* TLS Record Reading
* (C) 2004-2012 Jack Lloyd
*
* Released under the terms of the Botan license
*/

#include <botan/tls_record.h>
#include <botan/tls_exceptn.h>
#include <botan/internal/rounding.h>

namespace Botan {

namespace TLS {

Record_Reader::Record_Reader() :
   m_readbuf(TLS_HEADER_SIZE + MAX_CIPHERTEXT_SIZE)
   {
   reset();
   set_maximum_fragment_size(0);
   }

/*
* Reset the state
*/
void Record_Reader::reset()
   {
   set_maximum_fragment_size(0);

   m_macbuf.clear();

   zeroise(m_readbuf);
   m_readbuf_pos = 0;

   m_read_cipherstate.reset();

   m_version = Protocol_Version();
   m_read_seq_no = 0;
   }

void Record_Reader::set_maximum_fragment_size(size_t max_fragment)
   {
   if(max_fragment == 0)
      m_max_fragment = MAX_PLAINTEXT_SIZE;
   else
      m_max_fragment = clamp(max_fragment, 128, MAX_PLAINTEXT_SIZE);
   }

/*
* Set the version to use
*/
void Record_Reader::set_version(Protocol_Version version)
   {
   m_version = version;
   }

Protocol_Version Record_Reader::get_version() const
   {
   return m_version;
   }

/*
* Set the keys for reading
*/
void Record_Reader::change_cipher_spec(Connection_Side side,
                                       const Ciphersuite& suite,
                                       const Session_Keys& keys,
                                       byte compression_method)
   {
   if(compression_method != NO_COMPRESSION)
      throw Internal_Error("Negotiated unknown compression algorithm");

   m_read_seq_no = 0;

   // flip side as we are reading
   side = (side == CLIENT) ? SERVER : CLIENT;

   m_read_cipherstate.reset(
      new Connection_Cipher_State(m_version, side, suite, keys)
      );

   m_macbuf.resize(m_read_cipherstate->mac_size());
   }

/*
* Retrieve the next record
*/
size_t Record_Reader::add_input(const byte input_array[], size_t input_sz,
                                size_t& consumed,
                                byte& msg_type,
                                std::vector<byte>& msg,
                                u64bit& msg_sequence)
   {
   const size_t needed = read_record(m_readbuf,
                                     m_readbuf_pos,
                                     input_array,
                                     input_sz,
                                     consumed,
                                     msg_type,
                                     msg,
                                     m_read_seq_no,
                                     m_version,
                                     m_read_cipherstate.get());

   if(needed)
      return needed;

   // full message decoded
   if(msg.size() > m_max_fragment)
      throw TLS_Exception(Alert::RECORD_OVERFLOW, "Plaintext record is too large");

   msg_sequence = m_read_seq_no;
   m_read_seq_no += 1;

   return 0;
   }

}

}