xref: /freebsd-src/contrib/bearssl/src/ssl/ssl_engine.c (revision 0957b409a90fd597c1e9124cbaf3edd2b488f4ac)
1*0957b409SSimon J. Gerraty /*
2*0957b409SSimon J. Gerraty  * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
3*0957b409SSimon J. Gerraty  *
4*0957b409SSimon J. Gerraty  * Permission is hereby granted, free of charge, to any person obtaining
5*0957b409SSimon J. Gerraty  * a copy of this software and associated documentation files (the
6*0957b409SSimon J. Gerraty  * "Software"), to deal in the Software without restriction, including
7*0957b409SSimon J. Gerraty  * without limitation the rights to use, copy, modify, merge, publish,
8*0957b409SSimon J. Gerraty  * distribute, sublicense, and/or sell copies of the Software, and to
9*0957b409SSimon J. Gerraty  * permit persons to whom the Software is furnished to do so, subject to
10*0957b409SSimon J. Gerraty  * the following conditions:
11*0957b409SSimon J. Gerraty  *
12*0957b409SSimon J. Gerraty  * The above copyright notice and this permission notice shall be
13*0957b409SSimon J. Gerraty  * included in all copies or substantial portions of the Software.
14*0957b409SSimon J. Gerraty  *
15*0957b409SSimon J. Gerraty  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16*0957b409SSimon J. Gerraty  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17*0957b409SSimon J. Gerraty  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18*0957b409SSimon J. Gerraty  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19*0957b409SSimon J. Gerraty  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20*0957b409SSimon J. Gerraty  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21*0957b409SSimon J. Gerraty  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22*0957b409SSimon J. Gerraty  * SOFTWARE.
23*0957b409SSimon J. Gerraty  */
24*0957b409SSimon J. Gerraty 
25*0957b409SSimon J. Gerraty #include "inner.h"
26*0957b409SSimon J. Gerraty 
27*0957b409SSimon J. Gerraty #if 0
28*0957b409SSimon J. Gerraty /* obsolete */
29*0957b409SSimon J. Gerraty 
30*0957b409SSimon J. Gerraty /*
31*0957b409SSimon J. Gerraty  * If BR_USE_URANDOM is not defined, then try to autodetect its presence
32*0957b409SSimon J. Gerraty  * through compiler macros.
33*0957b409SSimon J. Gerraty  */
34*0957b409SSimon J. Gerraty #ifndef BR_USE_URANDOM
35*0957b409SSimon J. Gerraty 
36*0957b409SSimon J. Gerraty /*
37*0957b409SSimon J. Gerraty  * Macro values documented on:
38*0957b409SSimon J. Gerraty  *    https://sourceforge.net/p/predef/wiki/OperatingSystems/
39*0957b409SSimon J. Gerraty  *
40*0957b409SSimon J. Gerraty  * Only the most common systems have been included here for now. This
41*0957b409SSimon J. Gerraty  * should be enriched later on.
42*0957b409SSimon J. Gerraty  */
43*0957b409SSimon J. Gerraty #if defined _AIX \
44*0957b409SSimon J. Gerraty 	|| defined __ANDROID__ \
45*0957b409SSimon J. Gerraty 	|| defined __FreeBSD__ \
46*0957b409SSimon J. Gerraty 	|| defined __NetBSD__ \
47*0957b409SSimon J. Gerraty 	|| defined __OpenBSD__ \
48*0957b409SSimon J. Gerraty 	|| defined __DragonFly__ \
49*0957b409SSimon J. Gerraty 	|| defined __linux__ \
50*0957b409SSimon J. Gerraty 	|| (defined __sun && (defined __SVR4 || defined __svr4__)) \
51*0957b409SSimon J. Gerraty 	|| (defined __APPLE__ && defined __MACH__)
52*0957b409SSimon J. Gerraty #define BR_USE_URANDOM   1
53*0957b409SSimon J. Gerraty #endif
54*0957b409SSimon J. Gerraty 
55*0957b409SSimon J. Gerraty #endif
56*0957b409SSimon J. Gerraty 
57*0957b409SSimon J. Gerraty /*
58*0957b409SSimon J. Gerraty  * If BR_USE_WIN32_RAND is not defined, perform autodetection here.
59*0957b409SSimon J. Gerraty  */
60*0957b409SSimon J. Gerraty #ifndef BR_USE_WIN32_RAND
61*0957b409SSimon J. Gerraty 
62*0957b409SSimon J. Gerraty #if defined _WIN32 || defined _WIN64
63*0957b409SSimon J. Gerraty #define BR_USE_WIN32_RAND   1
64*0957b409SSimon J. Gerraty #endif
65*0957b409SSimon J. Gerraty 
66*0957b409SSimon J. Gerraty #endif
67*0957b409SSimon J. Gerraty 
68*0957b409SSimon J. Gerraty #if BR_USE_URANDOM
69*0957b409SSimon J. Gerraty #include <sys/types.h>
70*0957b409SSimon J. Gerraty #include <unistd.h>
71*0957b409SSimon J. Gerraty #include <fcntl.h>
72*0957b409SSimon J. Gerraty #include <errno.h>
73*0957b409SSimon J. Gerraty #endif
74*0957b409SSimon J. Gerraty 
75*0957b409SSimon J. Gerraty #if BR_USE_WIN32_RAND
76*0957b409SSimon J. Gerraty #include <windows.h>
77*0957b409SSimon J. Gerraty #include <wincrypt.h>
78*0957b409SSimon J. Gerraty #pragma comment(lib, "advapi32")
79*0957b409SSimon J. Gerraty #endif
80*0957b409SSimon J. Gerraty 
81*0957b409SSimon J. Gerraty #endif
82*0957b409SSimon J. Gerraty 
83*0957b409SSimon J. Gerraty /* ==================================================================== */
84*0957b409SSimon J. Gerraty /*
85*0957b409SSimon J. Gerraty  * This part of the file does the low-level record management.
86*0957b409SSimon J. Gerraty  */
87*0957b409SSimon J. Gerraty 
88*0957b409SSimon J. Gerraty /*
89*0957b409SSimon J. Gerraty  * IMPLEMENTATION NOTES
90*0957b409SSimon J. Gerraty  * ====================
91*0957b409SSimon J. Gerraty  *
92*0957b409SSimon J. Gerraty  * In this file, we designate by "input" (and the "i" letter) the "recv"
93*0957b409SSimon J. Gerraty  * operations: incoming records from the peer, from which payload data
94*0957b409SSimon J. Gerraty  * is obtained, and must be extracted by the application (or the SSL
95*0957b409SSimon J. Gerraty  * handshake engine). Similarly, "output" (and the "o" letter) is for
96*0957b409SSimon J. Gerraty  * "send": payload data injected by the application (and SSL handshake
97*0957b409SSimon J. Gerraty  * engine), to be wrapped into records, that are then conveyed to the
98*0957b409SSimon J. Gerraty  * peer over the transport medium.
99*0957b409SSimon J. Gerraty  *
100*0957b409SSimon J. Gerraty  * The input and output buffers may be distinct or shared. When
101*0957b409SSimon J. Gerraty  * shared, input and output cannot occur concurrently; the caller
102*0957b409SSimon J. Gerraty  * must make sure that it never needs to output data while input
103*0957b409SSimon J. Gerraty  * data has been received. In practice, a shared buffer prevents
104*0957b409SSimon J. Gerraty  * pipelining of HTTP requests, or similar protocols; however, a
105*0957b409SSimon J. Gerraty  * shared buffer saves RAM.
106*0957b409SSimon J. Gerraty  *
107*0957b409SSimon J. Gerraty  * The input buffer is pointed to by 'ibuf' and has size 'ibuf_len';
108*0957b409SSimon J. Gerraty  * the output buffer is pointed to by 'obuf' and has size 'obuf_len'.
109*0957b409SSimon J. Gerraty  * From the size of these buffers is derived the maximum fragment
110*0957b409SSimon J. Gerraty  * length, which will be honoured upon sending records; regardless of
111*0957b409SSimon J. Gerraty  * that length, incoming records will be processed as long as they
112*0957b409SSimon J. Gerraty  * fit in the input buffer, and their length still complies with the
113*0957b409SSimon J. Gerraty  * protocol specification (maximum plaintext payload length is 16384
114*0957b409SSimon J. Gerraty  * bytes).
115*0957b409SSimon J. Gerraty  *
116*0957b409SSimon J. Gerraty  * Three registers are used to manage buffering in ibuf, called ixa,
117*0957b409SSimon J. Gerraty  * ixb and ixc. Similarly, three registers are used to manage buffering
118*0957b409SSimon J. Gerraty  * in obuf, called oxa, oxb and oxc.
119*0957b409SSimon J. Gerraty  *
120*0957b409SSimon J. Gerraty  *
121*0957b409SSimon J. Gerraty  * At any time, the engine is in one of the following modes:
122*0957b409SSimon J. Gerraty  * -- Failed mode: an error occurs, no I/O can happen.
123*0957b409SSimon J. Gerraty  * -- Input mode: the engine can either receive record bytes from the
124*0957b409SSimon J. Gerraty  * transport layer, or it has some buffered payload bytes to yield.
125*0957b409SSimon J. Gerraty  * -- Output mode: the engine can either receive payload bytes, or it
126*0957b409SSimon J. Gerraty  * has some record bytes to send to the transport layer.
127*0957b409SSimon J. Gerraty  * -- Input/Output mode: both input and output modes are active. When
128*0957b409SSimon J. Gerraty  * the buffer is shared, this can happen only when the buffer is empty
129*0957b409SSimon J. Gerraty  * (no buffered payload bytes or record bytes in either direction).
130*0957b409SSimon J. Gerraty  *
131*0957b409SSimon J. Gerraty  *
132*0957b409SSimon J. Gerraty  * Failed mode:
133*0957b409SSimon J. Gerraty  * ------------
134*0957b409SSimon J. Gerraty  *
135*0957b409SSimon J. Gerraty  * I/O failed for some reason (invalid received data, not enough room
136*0957b409SSimon J. Gerraty  * for the next record...). No I/O may ever occur again for this context,
137*0957b409SSimon J. Gerraty  * until an explicit reset is performed. This mode, and the error code,
138*0957b409SSimon J. Gerraty  * are also used for protocol errors, especially handshake errors.
139*0957b409SSimon J. Gerraty  *
140*0957b409SSimon J. Gerraty  *
141*0957b409SSimon J. Gerraty  * Input mode:
142*0957b409SSimon J. Gerraty  * -----------
143*0957b409SSimon J. Gerraty  *
144*0957b409SSimon J. Gerraty  *  ixa   index within ibuf[] for the currently read data
145*0957b409SSimon J. Gerraty  *  ixb   maximum index within ibuf[] for the currently read data
146*0957b409SSimon J. Gerraty  *  ixc   number of bytes not yet received for the current record
147*0957b409SSimon J. Gerraty  *
148*0957b409SSimon J. Gerraty  * -- When ixa == ixb, there is no available data for readers. When
149*0957b409SSimon J. Gerraty  * ixa != ixb, there is available data and it starts at offset ixa.
150*0957b409SSimon J. Gerraty  *
151*0957b409SSimon J. Gerraty  * -- When waiting for the next record header, ixa and ixb are equal
152*0957b409SSimon J. Gerraty  * and contain a value ranging from 0 to 4; ixc is equal to 5-ixa.
153*0957b409SSimon J. Gerraty  *
154*0957b409SSimon J. Gerraty  * -- When the header has been received, record data is obtained. The
155*0957b409SSimon J. Gerraty  * ixc field records how many bytes are still needed to reach the
156*0957b409SSimon J. Gerraty  * end of the current record.
157*0957b409SSimon J. Gerraty  *
158*0957b409SSimon J. Gerraty  *    ** If encryption is active, then ixa and ixb are kept equal, and
159*0957b409SSimon J. Gerraty  *    point to the end of the currently received record bytes. When
160*0957b409SSimon J. Gerraty  *    ixc reaches 0, decryption/MAC is applied, and ixa and ixb are
161*0957b409SSimon J. Gerraty  *    adjusted.
162*0957b409SSimon J. Gerraty  *
163*0957b409SSimon J. Gerraty  *    ** If encryption is not active, then ixa and ixb are distinct
164*0957b409SSimon J. Gerraty  *    and data can be read right away. Additional record data is
165*0957b409SSimon J. Gerraty  *    obtained only when ixa == ixb.
166*0957b409SSimon J. Gerraty  *
167*0957b409SSimon J. Gerraty  * Note: in input mode and no encryption, records larger than the buffer
168*0957b409SSimon J. Gerraty  * size are allowed. When encryption is active, the complete record must
169*0957b409SSimon J. Gerraty  * fit within the buffer, since it cannot be decrypted/MACed until it
170*0957b409SSimon J. Gerraty  * has been completely received.
171*0957b409SSimon J. Gerraty  *
172*0957b409SSimon J. Gerraty  * -- When receiving the next record header, 'version_in' contains the
173*0957b409SSimon J. Gerraty  * expected input version (0 if not expecting a specific version); on
174*0957b409SSimon J. Gerraty  * mismatch, the mode switches to 'failed'.
175*0957b409SSimon J. Gerraty  *
176*0957b409SSimon J. Gerraty  * -- When the header has been received, 'version_in' contains the received
177*0957b409SSimon J. Gerraty  * version. It is up to the caller to check and adjust the 'version_in' field
178*0957b409SSimon J. Gerraty  * to implement the required semantics.
179*0957b409SSimon J. Gerraty  *
180*0957b409SSimon J. Gerraty  * -- The 'record_type_in' field is updated with the incoming record type
181*0957b409SSimon J. Gerraty  * when the next record header has been received.
182*0957b409SSimon J. Gerraty  *
183*0957b409SSimon J. Gerraty  *
184*0957b409SSimon J. Gerraty  * Output mode:
185*0957b409SSimon J. Gerraty  * ------------
186*0957b409SSimon J. Gerraty  *
187*0957b409SSimon J. Gerraty  *  oxa   index within obuf[] for the currently accumulated data
188*0957b409SSimon J. Gerraty  *  oxb   maximum index within obuf[] for record data
189*0957b409SSimon J. Gerraty  *  oxc   pointer for start of record data, and for record sending
190*0957b409SSimon J. Gerraty  *
191*0957b409SSimon J. Gerraty  * -- When oxa != oxb, more data can be accumulated into the current
192*0957b409SSimon J. Gerraty  * record; when oxa == oxb, a closed record is being sent.
193*0957b409SSimon J. Gerraty  *
194*0957b409SSimon J. Gerraty  * -- When accumulating data, oxc points to the start of the data.
195*0957b409SSimon J. Gerraty  *
196*0957b409SSimon J. Gerraty  * -- During record sending, oxa (and oxb) point to the next record byte
197*0957b409SSimon J. Gerraty  * to send, and oxc indicates the end of the current record.
198*0957b409SSimon J. Gerraty  *
199*0957b409SSimon J. Gerraty  * Note: sent records must fit within the buffer, since the header is
200*0957b409SSimon J. Gerraty  * adjusted only when the complete record has been assembled.
201*0957b409SSimon J. Gerraty  *
202*0957b409SSimon J. Gerraty  * -- The 'version_out' and 'record_type_out' fields are used to build the
203*0957b409SSimon J. Gerraty  * record header when the mode is switched to 'sending'.
204*0957b409SSimon J. Gerraty  *
205*0957b409SSimon J. Gerraty  *
206*0957b409SSimon J. Gerraty  * Modes:
207*0957b409SSimon J. Gerraty  * ------
208*0957b409SSimon J. Gerraty  *
209*0957b409SSimon J. Gerraty  * The state register iomode contains one of the following values:
210*0957b409SSimon J. Gerraty  *
211*0957b409SSimon J. Gerraty  *  BR_IO_FAILED   I/O failed
212*0957b409SSimon J. Gerraty  *  BR_IO_IN       input mode
213*0957b409SSimon J. Gerraty  *  BR_IO_OUT      output mode
214*0957b409SSimon J. Gerraty  *  BR_IO_INOUT    input/output mode
215*0957b409SSimon J. Gerraty  *
216*0957b409SSimon J. Gerraty  * Whether encryption is active on incoming records is indicated by the
217*0957b409SSimon J. Gerraty  * incrypt flag. For outgoing records, there is no such flag; "encryption"
218*0957b409SSimon J. Gerraty  * is always considered active, but initially uses functions that do not
219*0957b409SSimon J. Gerraty  * encrypt anything. The 'incrypt' flag is needed because when there is
220*0957b409SSimon J. Gerraty  * no active encryption, records larger than the I/O buffer are accepted.
221*0957b409SSimon J. Gerraty  *
222*0957b409SSimon J. Gerraty  * Note: we do not support no-encryption modes (MAC only).
223*0957b409SSimon J. Gerraty  *
224*0957b409SSimon J. Gerraty  * TODO: implement GCM support
225*0957b409SSimon J. Gerraty  *
226*0957b409SSimon J. Gerraty  *
227*0957b409SSimon J. Gerraty  * Misc:
228*0957b409SSimon J. Gerraty  * -----
229*0957b409SSimon J. Gerraty  *
230*0957b409SSimon J. Gerraty  * 'max_frag_len' is the maximum plaintext size for an outgoing record.
231*0957b409SSimon J. Gerraty  * By default, it is set to the maximum value that fits in the provided
232*0957b409SSimon J. Gerraty  * buffers, in the following list: 512, 1024, 2048, 4096, 16384. The
233*0957b409SSimon J. Gerraty  * caller may change it if needed, but the new value MUST still fit in
234*0957b409SSimon J. Gerraty  * the buffers, and it MUST be one of the list above for compatibility
235*0957b409SSimon J. Gerraty  * with the Maximum Fragment Length extension.
236*0957b409SSimon J. Gerraty  *
237*0957b409SSimon J. Gerraty  * For incoming records, only the total buffer length and current
238*0957b409SSimon J. Gerraty  * encryption mode impact the maximum length for incoming records. The
239*0957b409SSimon J. Gerraty  * 'max_frag_len' value is still adjusted so that records up to that
240*0957b409SSimon J. Gerraty  * length can be both received and sent.
241*0957b409SSimon J. Gerraty  *
242*0957b409SSimon J. Gerraty  *
243*0957b409SSimon J. Gerraty  * Offsets and lengths:
244*0957b409SSimon J. Gerraty  * --------------------
245*0957b409SSimon J. Gerraty  *
246*0957b409SSimon J. Gerraty  * When sending fragments with TLS-1.1+, the maximum overhead is:
247*0957b409SSimon J. Gerraty  *   5 bytes for the record header
248*0957b409SSimon J. Gerraty  *   16 bytes for the explicit IV
249*0957b409SSimon J. Gerraty  *   48 bytes for the MAC (HMAC/SHA-384)
250*0957b409SSimon J. Gerraty  *   16 bytes for the padding (AES)
251*0957b409SSimon J. Gerraty  * so a total of 85 extra bytes. Note that we support block cipher sizes
252*0957b409SSimon J. Gerraty  * up to 16 bytes (AES) and HMAC output sizes up to 48 bytes (SHA-384).
253*0957b409SSimon J. Gerraty  *
254*0957b409SSimon J. Gerraty  * With TLS-1.0 and CBC mode, we apply a 1/n-1 split, for a maximum
255*0957b409SSimon J. Gerraty  * overhead of:
256*0957b409SSimon J. Gerraty  *   5 bytes for the first record header
257*0957b409SSimon J. Gerraty  *   32 bytes for the first record payload (AES-CBC + HMAC/SHA-1)
258*0957b409SSimon J. Gerraty  *   5 bytes for the second record header
259*0957b409SSimon J. Gerraty  *   20 bytes for the MAC (HMAC/SHA-1)
260*0957b409SSimon J. Gerraty  *   16 bytes for the padding (AES)
261*0957b409SSimon J. Gerraty  *   -1 byte to account for the payload byte in the first record
262*0957b409SSimon J. Gerraty  * so a total of 77 extra bytes at most, less than the 85 bytes above.
263*0957b409SSimon J. Gerraty  * Note that with TLS-1.0, the MAC is HMAC with either MD5 or SHA-1, but
264*0957b409SSimon J. Gerraty  * no other hash function.
265*0957b409SSimon J. Gerraty  *
266*0957b409SSimon J. Gerraty  * The implementation does not try to send larger records when the current
267*0957b409SSimon J. Gerraty  * encryption mode has less overhead.
268*0957b409SSimon J. Gerraty  *
269*0957b409SSimon J. Gerraty  * Maximum input record overhead is:
270*0957b409SSimon J. Gerraty  *   5 bytes for the record header
271*0957b409SSimon J. Gerraty  *   16 bytes for the explicit IV (TLS-1.1+)
272*0957b409SSimon J. Gerraty  *   48 bytes for the MAC (HMAC/SHA-384)
273*0957b409SSimon J. Gerraty  *   256 bytes for the padding
274*0957b409SSimon J. Gerraty  * so a total of 325 extra bytes.
275*0957b409SSimon J. Gerraty  *
276*0957b409SSimon J. Gerraty  * When receiving the next record header, it is written into the buffer
277*0957b409SSimon J. Gerraty  * bytes 0 to 4 (inclusive). Record data is always written into buf[]
278*0957b409SSimon J. Gerraty  * starting at offset 5. When encryption is active, the plaintext data
279*0957b409SSimon J. Gerraty  * may start at a larger offset (e.g. because of an explicit IV).
280*0957b409SSimon J. Gerraty  */
281*0957b409SSimon J. Gerraty 
282*0957b409SSimon J. Gerraty #define MAX_OUT_OVERHEAD    85
283*0957b409SSimon J. Gerraty #define MAX_IN_OVERHEAD    325
284*0957b409SSimon J. Gerraty 
285*0957b409SSimon J. Gerraty /* see inner.h */
286*0957b409SSimon J. Gerraty void
287*0957b409SSimon J. Gerraty br_ssl_engine_fail(br_ssl_engine_context *rc, int err)
288*0957b409SSimon J. Gerraty {
289*0957b409SSimon J. Gerraty 	if (rc->iomode != BR_IO_FAILED) {
290*0957b409SSimon J. Gerraty 		rc->iomode = BR_IO_FAILED;
291*0957b409SSimon J. Gerraty 		rc->err = err;
292*0957b409SSimon J. Gerraty 	}
293*0957b409SSimon J. Gerraty }
294*0957b409SSimon J. Gerraty 
295*0957b409SSimon J. Gerraty /*
296*0957b409SSimon J. Gerraty  * Adjust registers for a new incoming record.
297*0957b409SSimon J. Gerraty  */
298*0957b409SSimon J. Gerraty static void
299*0957b409SSimon J. Gerraty make_ready_in(br_ssl_engine_context *rc)
300*0957b409SSimon J. Gerraty {
301*0957b409SSimon J. Gerraty 	rc->ixa = rc->ixb = 0;
302*0957b409SSimon J. Gerraty 	rc->ixc = 5;
303*0957b409SSimon J. Gerraty 	if (rc->iomode == BR_IO_IN) {
304*0957b409SSimon J. Gerraty 		rc->iomode = BR_IO_INOUT;
305*0957b409SSimon J. Gerraty 	}
306*0957b409SSimon J. Gerraty }
307*0957b409SSimon J. Gerraty 
308*0957b409SSimon J. Gerraty /*
309*0957b409SSimon J. Gerraty  * Adjust registers for a new outgoing record.
310*0957b409SSimon J. Gerraty  */
311*0957b409SSimon J. Gerraty static void
312*0957b409SSimon J. Gerraty make_ready_out(br_ssl_engine_context *rc)
313*0957b409SSimon J. Gerraty {
314*0957b409SSimon J. Gerraty 	size_t a, b;
315*0957b409SSimon J. Gerraty 
316*0957b409SSimon J. Gerraty 	a = 5;
317*0957b409SSimon J. Gerraty 	b = rc->obuf_len - a;
318*0957b409SSimon J. Gerraty 	rc->out.vtable->max_plaintext(&rc->out.vtable, &a, &b);
319*0957b409SSimon J. Gerraty 	if ((b - a) > rc->max_frag_len) {
320*0957b409SSimon J. Gerraty 		b = a + rc->max_frag_len;
321*0957b409SSimon J. Gerraty 	}
322*0957b409SSimon J. Gerraty 	rc->oxa = a;
323*0957b409SSimon J. Gerraty 	rc->oxb = b;
324*0957b409SSimon J. Gerraty 	rc->oxc = a;
325*0957b409SSimon J. Gerraty 	if (rc->iomode == BR_IO_OUT) {
326*0957b409SSimon J. Gerraty 		rc->iomode = BR_IO_INOUT;
327*0957b409SSimon J. Gerraty 	}
328*0957b409SSimon J. Gerraty }
329*0957b409SSimon J. Gerraty 
330*0957b409SSimon J. Gerraty /* see inner.h */
331*0957b409SSimon J. Gerraty void
332*0957b409SSimon J. Gerraty br_ssl_engine_new_max_frag_len(br_ssl_engine_context *rc, unsigned max_frag_len)
333*0957b409SSimon J. Gerraty {
334*0957b409SSimon J. Gerraty 	size_t nxb;
335*0957b409SSimon J. Gerraty 
336*0957b409SSimon J. Gerraty 	rc->max_frag_len = max_frag_len;
337*0957b409SSimon J. Gerraty 	nxb = rc->oxc + max_frag_len;
338*0957b409SSimon J. Gerraty 	if (rc->oxa < rc->oxb && rc->oxb > nxb && rc->oxa < nxb) {
339*0957b409SSimon J. Gerraty 		rc->oxb = nxb;
340*0957b409SSimon J. Gerraty 	}
341*0957b409SSimon J. Gerraty }
342*0957b409SSimon J. Gerraty 
343*0957b409SSimon J. Gerraty /* see bearssl_ssl.h */
344*0957b409SSimon J. Gerraty void
345*0957b409SSimon J. Gerraty br_ssl_engine_set_buffer(br_ssl_engine_context *rc,
346*0957b409SSimon J. Gerraty 	void *buf, size_t buf_len, int bidi)
347*0957b409SSimon J. Gerraty {
348*0957b409SSimon J. Gerraty 	if (buf == NULL) {
349*0957b409SSimon J. Gerraty 		br_ssl_engine_set_buffers_bidi(rc, NULL, 0, NULL, 0);
350*0957b409SSimon J. Gerraty 	} else {
351*0957b409SSimon J. Gerraty 		/*
352*0957b409SSimon J. Gerraty 		 * In bidirectional mode, we want to maximise input
353*0957b409SSimon J. Gerraty 		 * buffer size, since we support arbitrary fragmentation
354*0957b409SSimon J. Gerraty 		 * when sending, but the peer will not necessarily
355*0957b409SSimon J. Gerraty 		 * comply to any low fragment length (in particular if
356*0957b409SSimon J. Gerraty 		 * we are the server, because the maximum fragment
357*0957b409SSimon J. Gerraty 		 * length extension is under client control).
358*0957b409SSimon J. Gerraty 		 *
359*0957b409SSimon J. Gerraty 		 * We keep a minimum size of 512 bytes for the plaintext
360*0957b409SSimon J. Gerraty 		 * of our outgoing records.
361*0957b409SSimon J. Gerraty 		 *
362*0957b409SSimon J. Gerraty 		 * br_ssl_engine_set_buffers_bidi() will compute the maximum
363*0957b409SSimon J. Gerraty 		 * fragment length for outgoing records by using the minimum
364*0957b409SSimon J. Gerraty 		 * of allocated spaces for both input and output records,
365*0957b409SSimon J. Gerraty 		 * rounded down to a standard length.
366*0957b409SSimon J. Gerraty 		 */
367*0957b409SSimon J. Gerraty 		if (bidi) {
368*0957b409SSimon J. Gerraty 			size_t w;
369*0957b409SSimon J. Gerraty 
370*0957b409SSimon J. Gerraty 			if (buf_len < (512 + MAX_IN_OVERHEAD
371*0957b409SSimon J. Gerraty 				+ 512 + MAX_OUT_OVERHEAD))
372*0957b409SSimon J. Gerraty 			{
373*0957b409SSimon J. Gerraty 				rc->iomode = BR_IO_FAILED;
374*0957b409SSimon J. Gerraty 				rc->err = BR_ERR_BAD_PARAM;
375*0957b409SSimon J. Gerraty 				return;
376*0957b409SSimon J. Gerraty 			} else if (buf_len < (16384 + MAX_IN_OVERHEAD
377*0957b409SSimon J. Gerraty 				+ 512 + MAX_OUT_OVERHEAD))
378*0957b409SSimon J. Gerraty 			{
379*0957b409SSimon J. Gerraty 				w = 512 + MAX_OUT_OVERHEAD;
380*0957b409SSimon J. Gerraty 			} else {
381*0957b409SSimon J. Gerraty 				w = buf_len - (16384 + MAX_IN_OVERHEAD);
382*0957b409SSimon J. Gerraty 			}
383*0957b409SSimon J. Gerraty 			br_ssl_engine_set_buffers_bidi(rc,
384*0957b409SSimon J. Gerraty 				buf, buf_len - w,
385*0957b409SSimon J. Gerraty 				(unsigned char *)buf + w, w);
386*0957b409SSimon J. Gerraty 		} else {
387*0957b409SSimon J. Gerraty 			br_ssl_engine_set_buffers_bidi(rc,
388*0957b409SSimon J. Gerraty 				buf, buf_len, NULL, 0);
389*0957b409SSimon J. Gerraty 		}
390*0957b409SSimon J. Gerraty 	}
391*0957b409SSimon J. Gerraty }
392*0957b409SSimon J. Gerraty 
393*0957b409SSimon J. Gerraty /* see bearssl_ssl.h */
394*0957b409SSimon J. Gerraty void
395*0957b409SSimon J. Gerraty br_ssl_engine_set_buffers_bidi(br_ssl_engine_context *rc,
396*0957b409SSimon J. Gerraty 	void *ibuf, size_t ibuf_len, void *obuf, size_t obuf_len)
397*0957b409SSimon J. Gerraty {
398*0957b409SSimon J. Gerraty 	rc->iomode = BR_IO_INOUT;
399*0957b409SSimon J. Gerraty 	rc->incrypt = 0;
400*0957b409SSimon J. Gerraty 	rc->err = BR_ERR_OK;
401*0957b409SSimon J. Gerraty 	rc->version_in = 0;
402*0957b409SSimon J. Gerraty 	rc->record_type_in = 0;
403*0957b409SSimon J. Gerraty 	rc->version_out = 0;
404*0957b409SSimon J. Gerraty 	rc->record_type_out = 0;
405*0957b409SSimon J. Gerraty 	if (ibuf == NULL) {
406*0957b409SSimon J. Gerraty 		if (rc->ibuf == NULL) {
407*0957b409SSimon J. Gerraty 			br_ssl_engine_fail(rc, BR_ERR_BAD_PARAM);
408*0957b409SSimon J. Gerraty 		}
409*0957b409SSimon J. Gerraty 	} else {
410*0957b409SSimon J. Gerraty 		unsigned u;
411*0957b409SSimon J. Gerraty 
412*0957b409SSimon J. Gerraty 		rc->ibuf = ibuf;
413*0957b409SSimon J. Gerraty 		rc->ibuf_len = ibuf_len;
414*0957b409SSimon J. Gerraty 		if (obuf == NULL) {
415*0957b409SSimon J. Gerraty 			obuf = ibuf;
416*0957b409SSimon J. Gerraty 			obuf_len = ibuf_len;
417*0957b409SSimon J. Gerraty 		}
418*0957b409SSimon J. Gerraty 		rc->obuf = obuf;
419*0957b409SSimon J. Gerraty 		rc->obuf_len = obuf_len;
420*0957b409SSimon J. Gerraty 
421*0957b409SSimon J. Gerraty 		/*
422*0957b409SSimon J. Gerraty 		 * Compute the maximum fragment length, that fits for
423*0957b409SSimon J. Gerraty 		 * both incoming and outgoing records. This length will
424*0957b409SSimon J. Gerraty 		 * be used in fragment length negotiation, so we must
425*0957b409SSimon J. Gerraty 		 * honour it both ways. Regardless, larger incoming
426*0957b409SSimon J. Gerraty 		 * records will be accepted, as long as they fit in the
427*0957b409SSimon J. Gerraty 		 * actual buffer size.
428*0957b409SSimon J. Gerraty 		 */
429*0957b409SSimon J. Gerraty 		for (u = 14; u >= 9; u --) {
430*0957b409SSimon J. Gerraty 			size_t flen;
431*0957b409SSimon J. Gerraty 
432*0957b409SSimon J. Gerraty 			flen = (size_t)1 << u;
433*0957b409SSimon J. Gerraty 			if (obuf_len >= flen + MAX_OUT_OVERHEAD
434*0957b409SSimon J. Gerraty 				&& ibuf_len >= flen + MAX_IN_OVERHEAD)
435*0957b409SSimon J. Gerraty 			{
436*0957b409SSimon J. Gerraty 				break;
437*0957b409SSimon J. Gerraty 			}
438*0957b409SSimon J. Gerraty 		}
439*0957b409SSimon J. Gerraty 		if (u == 8) {
440*0957b409SSimon J. Gerraty 			br_ssl_engine_fail(rc, BR_ERR_BAD_PARAM);
441*0957b409SSimon J. Gerraty 			return;
442*0957b409SSimon J. Gerraty 		} else if (u == 13) {
443*0957b409SSimon J. Gerraty 			u = 12;
444*0957b409SSimon J. Gerraty 		}
445*0957b409SSimon J. Gerraty 		rc->max_frag_len = (size_t)1 << u;
446*0957b409SSimon J. Gerraty 		rc->log_max_frag_len = u;
447*0957b409SSimon J. Gerraty 		rc->peer_log_max_frag_len = 0;
448*0957b409SSimon J. Gerraty 	}
449*0957b409SSimon J. Gerraty 	rc->out.vtable = &br_sslrec_out_clear_vtable;
450*0957b409SSimon J. Gerraty 	make_ready_in(rc);
451*0957b409SSimon J. Gerraty 	make_ready_out(rc);
452*0957b409SSimon J. Gerraty }
453*0957b409SSimon J. Gerraty 
454*0957b409SSimon J. Gerraty /*
455*0957b409SSimon J. Gerraty  * Clear buffers in both directions.
456*0957b409SSimon J. Gerraty  */
457*0957b409SSimon J. Gerraty static void
458*0957b409SSimon J. Gerraty engine_clearbuf(br_ssl_engine_context *rc)
459*0957b409SSimon J. Gerraty {
460*0957b409SSimon J. Gerraty 	make_ready_in(rc);
461*0957b409SSimon J. Gerraty 	make_ready_out(rc);
462*0957b409SSimon J. Gerraty }
463*0957b409SSimon J. Gerraty 
464*0957b409SSimon J. Gerraty /*
465*0957b409SSimon J. Gerraty  * Make sure the internal PRNG is initialised (but not necessarily
466*0957b409SSimon J. Gerraty  * seeded properly yet).
467*0957b409SSimon J. Gerraty  */
468*0957b409SSimon J. Gerraty static int
469*0957b409SSimon J. Gerraty rng_init(br_ssl_engine_context *cc)
470*0957b409SSimon J. Gerraty {
471*0957b409SSimon J. Gerraty 	const br_hash_class *h;
472*0957b409SSimon J. Gerraty 
473*0957b409SSimon J. Gerraty 	if (cc->rng_init_done != 0) {
474*0957b409SSimon J. Gerraty 		return 1;
475*0957b409SSimon J. Gerraty 	}
476*0957b409SSimon J. Gerraty 
477*0957b409SSimon J. Gerraty 	/*
478*0957b409SSimon J. Gerraty 	 * If using TLS-1.2, then SHA-256 or SHA-384 must be present (or
479*0957b409SSimon J. Gerraty 	 * both); we prefer SHA-256 which is faster for 32-bit systems.
480*0957b409SSimon J. Gerraty 	 *
481*0957b409SSimon J. Gerraty 	 * If using TLS-1.0 or 1.1 then SHA-1 must be present.
482*0957b409SSimon J. Gerraty 	 *
483*0957b409SSimon J. Gerraty 	 * Though HMAC_DRBG/SHA-1 is, as far as we know, as safe as
484*0957b409SSimon J. Gerraty 	 * these things can be, we still prefer the SHA-2 functions over
485*0957b409SSimon J. Gerraty 	 * SHA-1, if only for public relations (known theoretical
486*0957b409SSimon J. Gerraty 	 * weaknesses of SHA-1 with regards to collisions are mostly
487*0957b409SSimon J. Gerraty 	 * irrelevant here, but they still make people nervous).
488*0957b409SSimon J. Gerraty 	 */
489*0957b409SSimon J. Gerraty 	h = br_multihash_getimpl(&cc->mhash, br_sha256_ID);
490*0957b409SSimon J. Gerraty 	if (!h) {
491*0957b409SSimon J. Gerraty 		h = br_multihash_getimpl(&cc->mhash, br_sha384_ID);
492*0957b409SSimon J. Gerraty 		if (!h) {
493*0957b409SSimon J. Gerraty 			h = br_multihash_getimpl(&cc->mhash,
494*0957b409SSimon J. Gerraty 				br_sha1_ID);
495*0957b409SSimon J. Gerraty 			if (!h) {
496*0957b409SSimon J. Gerraty 				br_ssl_engine_fail(cc, BR_ERR_BAD_STATE);
497*0957b409SSimon J. Gerraty 				return 0;
498*0957b409SSimon J. Gerraty 			}
499*0957b409SSimon J. Gerraty 		}
500*0957b409SSimon J. Gerraty 	}
501*0957b409SSimon J. Gerraty 	br_hmac_drbg_init(&cc->rng, h, NULL, 0);
502*0957b409SSimon J. Gerraty 	cc->rng_init_done = 1;
503*0957b409SSimon J. Gerraty 	return 1;
504*0957b409SSimon J. Gerraty }
505*0957b409SSimon J. Gerraty 
506*0957b409SSimon J. Gerraty /* see inner.h */
507*0957b409SSimon J. Gerraty int
508*0957b409SSimon J. Gerraty br_ssl_engine_init_rand(br_ssl_engine_context *cc)
509*0957b409SSimon J. Gerraty {
510*0957b409SSimon J. Gerraty 	if (!rng_init(cc)) {
511*0957b409SSimon J. Gerraty 		return 0;
512*0957b409SSimon J. Gerraty 	}
513*0957b409SSimon J. Gerraty 
514*0957b409SSimon J. Gerraty 	/*
515*0957b409SSimon J. Gerraty 	 * We always try OS/hardware seeding once. If it works, then
516*0957b409SSimon J. Gerraty 	 * we assume proper seeding. If not, then external entropy must
517*0957b409SSimon J. Gerraty 	 * have been injected; otherwise, we report an error.
518*0957b409SSimon J. Gerraty 	 */
519*0957b409SSimon J. Gerraty 	if (!cc->rng_os_rand_done) {
520*0957b409SSimon J. Gerraty 		br_prng_seeder sd;
521*0957b409SSimon J. Gerraty 
522*0957b409SSimon J. Gerraty 		sd = br_prng_seeder_system(NULL);
523*0957b409SSimon J. Gerraty 		if (sd != 0 && sd(&cc->rng.vtable)) {
524*0957b409SSimon J. Gerraty 			cc->rng_init_done = 2;
525*0957b409SSimon J. Gerraty 		}
526*0957b409SSimon J. Gerraty 		cc->rng_os_rand_done = 1;
527*0957b409SSimon J. Gerraty 	}
528*0957b409SSimon J. Gerraty 	if (cc->rng_init_done < 2) {
529*0957b409SSimon J. Gerraty 		br_ssl_engine_fail(cc, BR_ERR_NO_RANDOM);
530*0957b409SSimon J. Gerraty 		return 0;
531*0957b409SSimon J. Gerraty 	}
532*0957b409SSimon J. Gerraty 	return 1;
533*0957b409SSimon J. Gerraty }
534*0957b409SSimon J. Gerraty 
535*0957b409SSimon J. Gerraty /* see bearssl_ssl.h */
536*0957b409SSimon J. Gerraty void
537*0957b409SSimon J. Gerraty br_ssl_engine_inject_entropy(br_ssl_engine_context *cc,
538*0957b409SSimon J. Gerraty 	const void *data, size_t len)
539*0957b409SSimon J. Gerraty {
540*0957b409SSimon J. Gerraty 	/*
541*0957b409SSimon J. Gerraty 	 * Externally provided entropy is assumed to be "good enough"
542*0957b409SSimon J. Gerraty 	 * (we cannot really test its quality) so if the RNG structure
543*0957b409SSimon J. Gerraty 	 * could be initialised at all, then we marked the RNG as
544*0957b409SSimon J. Gerraty 	 * "properly seeded".
545*0957b409SSimon J. Gerraty 	 */
546*0957b409SSimon J. Gerraty 	if (!rng_init(cc)) {
547*0957b409SSimon J. Gerraty 		return;
548*0957b409SSimon J. Gerraty 	}
549*0957b409SSimon J. Gerraty 	br_hmac_drbg_update(&cc->rng, data, len);
550*0957b409SSimon J. Gerraty 	cc->rng_init_done = 2;
551*0957b409SSimon J. Gerraty }
552*0957b409SSimon J. Gerraty 
553*0957b409SSimon J. Gerraty /*
554*0957b409SSimon J. Gerraty  * We define a few internal functions that implement the low-level engine
555*0957b409SSimon J. Gerraty  * API for I/O; the external API (br_ssl_engine_sendapp_buf() and similar
556*0957b409SSimon J. Gerraty  * functions) is built upon these function, with special processing for
557*0957b409SSimon J. Gerraty  * records which are not of type "application data".
558*0957b409SSimon J. Gerraty  *
559*0957b409SSimon J. Gerraty  *   recvrec_buf, recvrec_ack     receives bytes from transport medium
560*0957b409SSimon J. Gerraty  *   sendrec_buf, sendrec_ack     send bytes to transport medium
561*0957b409SSimon J. Gerraty  *   recvpld_buf, recvpld_ack     receives payload data from engine
562*0957b409SSimon J. Gerraty  *   sendpld_buf, sendpld_ack     send payload data to engine
563*0957b409SSimon J. Gerraty  */
564*0957b409SSimon J. Gerraty 
565*0957b409SSimon J. Gerraty static unsigned char *
566*0957b409SSimon J. Gerraty recvrec_buf(const br_ssl_engine_context *rc, size_t *len)
567*0957b409SSimon J. Gerraty {
568*0957b409SSimon J. Gerraty 	if (rc->shutdown_recv) {
569*0957b409SSimon J. Gerraty 		*len = 0;
570*0957b409SSimon J. Gerraty 		return NULL;
571*0957b409SSimon J. Gerraty 	}
572*0957b409SSimon J. Gerraty 
573*0957b409SSimon J. Gerraty 	/*
574*0957b409SSimon J. Gerraty 	 * Bytes from the transport can be injected only if the mode is
575*0957b409SSimon J. Gerraty 	 * compatible (in or in/out), and ixa == ixb; ixc then contains
576*0957b409SSimon J. Gerraty 	 * the number of bytes that are still expected (but it may
577*0957b409SSimon J. Gerraty 	 * exceed our buffer size).
578*0957b409SSimon J. Gerraty 	 *
579*0957b409SSimon J. Gerraty 	 * We cannot get "stuck" here (buffer is full, but still more
580*0957b409SSimon J. Gerraty 	 * data is expected) because oversized records are detected when
581*0957b409SSimon J. Gerraty 	 * their header is processed.
582*0957b409SSimon J. Gerraty 	 */
583*0957b409SSimon J. Gerraty 	switch (rc->iomode) {
584*0957b409SSimon J. Gerraty 	case BR_IO_IN:
585*0957b409SSimon J. Gerraty 	case BR_IO_INOUT:
586*0957b409SSimon J. Gerraty 		if (rc->ixa == rc->ixb) {
587*0957b409SSimon J. Gerraty 			size_t z;
588*0957b409SSimon J. Gerraty 
589*0957b409SSimon J. Gerraty 			z = rc->ixc;
590*0957b409SSimon J. Gerraty 			if (z > rc->ibuf_len - rc->ixa) {
591*0957b409SSimon J. Gerraty 				z = rc->ibuf_len - rc->ixa;
592*0957b409SSimon J. Gerraty 			}
593*0957b409SSimon J. Gerraty 			*len = z;
594*0957b409SSimon J. Gerraty 			return rc->ibuf + rc->ixa;
595*0957b409SSimon J. Gerraty 		}
596*0957b409SSimon J. Gerraty 		break;
597*0957b409SSimon J. Gerraty 	}
598*0957b409SSimon J. Gerraty 	*len = 0;
599*0957b409SSimon J. Gerraty 	return NULL;
600*0957b409SSimon J. Gerraty }
601*0957b409SSimon J. Gerraty 
602*0957b409SSimon J. Gerraty static void
603*0957b409SSimon J. Gerraty recvrec_ack(br_ssl_engine_context *rc, size_t len)
604*0957b409SSimon J. Gerraty {
605*0957b409SSimon J. Gerraty 	unsigned char *pbuf;
606*0957b409SSimon J. Gerraty 	size_t pbuf_len;
607*0957b409SSimon J. Gerraty 
608*0957b409SSimon J. Gerraty 	/*
609*0957b409SSimon J. Gerraty 	 * Adjust state if necessary (for a shared input/output buffer):
610*0957b409SSimon J. Gerraty 	 * we got some incoming bytes, so we cannot (temporarily) handle
611*0957b409SSimon J. Gerraty 	 * outgoing data.
612*0957b409SSimon J. Gerraty 	 */
613*0957b409SSimon J. Gerraty 	if (rc->iomode == BR_IO_INOUT && rc->ibuf == rc->obuf) {
614*0957b409SSimon J. Gerraty 		rc->iomode = BR_IO_IN;
615*0957b409SSimon J. Gerraty 	}
616*0957b409SSimon J. Gerraty 
617*0957b409SSimon J. Gerraty 	/*
618*0957b409SSimon J. Gerraty 	 * Adjust data pointers.
619*0957b409SSimon J. Gerraty 	 */
620*0957b409SSimon J. Gerraty 	rc->ixb = (rc->ixa += len);
621*0957b409SSimon J. Gerraty 	rc->ixc -= len;
622*0957b409SSimon J. Gerraty 
623*0957b409SSimon J. Gerraty 	/*
624*0957b409SSimon J. Gerraty 	 * If we are receiving a header and did not fully obtained it
625*0957b409SSimon J. Gerraty 	 * yet, then just wait for the next bytes.
626*0957b409SSimon J. Gerraty 	 */
627*0957b409SSimon J. Gerraty 	if (rc->ixa < 5) {
628*0957b409SSimon J. Gerraty 		return;
629*0957b409SSimon J. Gerraty 	}
630*0957b409SSimon J. Gerraty 
631*0957b409SSimon J. Gerraty 	/*
632*0957b409SSimon J. Gerraty 	 * If we just obtained a full header, process it.
633*0957b409SSimon J. Gerraty 	 */
634*0957b409SSimon J. Gerraty 	if (rc->ixa == 5) {
635*0957b409SSimon J. Gerraty 		unsigned version;
636*0957b409SSimon J. Gerraty 		unsigned rlen;
637*0957b409SSimon J. Gerraty 
638*0957b409SSimon J. Gerraty 		/*
639*0957b409SSimon J. Gerraty 		 * Get record type and version. We support only versions
640*0957b409SSimon J. Gerraty 		 * 3.x (if the version major number does not match, then
641*0957b409SSimon J. Gerraty 		 * we suppose that the record format is too alien for us
642*0957b409SSimon J. Gerraty 		 * to process it).
643*0957b409SSimon J. Gerraty 		 *
644*0957b409SSimon J. Gerraty 		 * Note: right now, we reject clients that try to send
645*0957b409SSimon J. Gerraty 		 * a ClientHello in a format compatible with SSL-2.0. It
646*0957b409SSimon J. Gerraty 		 * is unclear whether this will ever be supported; and
647*0957b409SSimon J. Gerraty 		 * if we want to support it, then this might be done in
648*0957b409SSimon J. Gerraty 		 * in the server-specific code, not here.
649*0957b409SSimon J. Gerraty 		 */
650*0957b409SSimon J. Gerraty 		rc->record_type_in = rc->ibuf[0];
651*0957b409SSimon J. Gerraty 		version = br_dec16be(rc->ibuf + 1);
652*0957b409SSimon J. Gerraty 		if ((version >> 8) != 3) {
653*0957b409SSimon J. Gerraty 			br_ssl_engine_fail(rc, BR_ERR_UNSUPPORTED_VERSION);
654*0957b409SSimon J. Gerraty 			return;
655*0957b409SSimon J. Gerraty 		}
656*0957b409SSimon J. Gerraty 
657*0957b409SSimon J. Gerraty 		/*
658*0957b409SSimon J. Gerraty 		 * We ensure that successive records have the same
659*0957b409SSimon J. Gerraty 		 * version. The handshake code must check and adjust the
660*0957b409SSimon J. Gerraty 		 * variables when necessary to accommodate the protocol
661*0957b409SSimon J. Gerraty 		 * negotiation details.
662*0957b409SSimon J. Gerraty 		 */
663*0957b409SSimon J. Gerraty 		if (rc->version_in != 0 && rc->version_in != version) {
664*0957b409SSimon J. Gerraty 			br_ssl_engine_fail(rc, BR_ERR_BAD_VERSION);
665*0957b409SSimon J. Gerraty 			return;
666*0957b409SSimon J. Gerraty 		}
667*0957b409SSimon J. Gerraty 		rc->version_in = version;
668*0957b409SSimon J. Gerraty 
669*0957b409SSimon J. Gerraty 		/*
670*0957b409SSimon J. Gerraty 		 * Decode record length. We must check that the length
671*0957b409SSimon J. Gerraty 		 * is valid (relatively to the current encryption mode)
672*0957b409SSimon J. Gerraty 		 * and also (if encryption is active) that the record
673*0957b409SSimon J. Gerraty 		 * will fit in our buffer.
674*0957b409SSimon J. Gerraty 		 *
675*0957b409SSimon J. Gerraty 		 * When no encryption is active, we can process records
676*0957b409SSimon J. Gerraty 		 * by chunks, and thus accept any record up to the
677*0957b409SSimon J. Gerraty 		 * maximum allowed plaintext length (16384 bytes).
678*0957b409SSimon J. Gerraty 		 */
679*0957b409SSimon J. Gerraty 		rlen = br_dec16be(rc->ibuf + 3);
680*0957b409SSimon J. Gerraty 		if (rc->incrypt) {
681*0957b409SSimon J. Gerraty 			if (!rc->in.vtable->check_length(
682*0957b409SSimon J. Gerraty 				&rc->in.vtable, rlen))
683*0957b409SSimon J. Gerraty 			{
684*0957b409SSimon J. Gerraty 				br_ssl_engine_fail(rc, BR_ERR_BAD_LENGTH);
685*0957b409SSimon J. Gerraty 				return;
686*0957b409SSimon J. Gerraty 			}
687*0957b409SSimon J. Gerraty 			if (rlen > (rc->ibuf_len - 5)) {
688*0957b409SSimon J. Gerraty 				br_ssl_engine_fail(rc, BR_ERR_TOO_LARGE);
689*0957b409SSimon J. Gerraty 				return;
690*0957b409SSimon J. Gerraty 			}
691*0957b409SSimon J. Gerraty 		} else {
692*0957b409SSimon J. Gerraty 			if (rlen > 16384) {
693*0957b409SSimon J. Gerraty 				br_ssl_engine_fail(rc, BR_ERR_BAD_LENGTH);
694*0957b409SSimon J. Gerraty 				return;
695*0957b409SSimon J. Gerraty 			}
696*0957b409SSimon J. Gerraty 		}
697*0957b409SSimon J. Gerraty 
698*0957b409SSimon J. Gerraty 		/*
699*0957b409SSimon J. Gerraty 		 * If the record is completely empty then we must switch
700*0957b409SSimon J. Gerraty 		 * to a new record. Note that, in that case, we
701*0957b409SSimon J. Gerraty 		 * completely ignore the record type, which is fitting
702*0957b409SSimon J. Gerraty 		 * since we received no actual data of that type.
703*0957b409SSimon J. Gerraty 		 *
704*0957b409SSimon J. Gerraty 		 * A completely empty record is technically allowed as
705*0957b409SSimon J. Gerraty 		 * long as encryption/MAC is not active, i.e. before
706*0957b409SSimon J. Gerraty 		 * completion of the first handshake. It it still weird;
707*0957b409SSimon J. Gerraty 		 * it might conceptually be useful as a heartbeat or
708*0957b409SSimon J. Gerraty 		 * keep-alive mechanism while some lengthy operation is
709*0957b409SSimon J. Gerraty 		 * going on, e.g. interaction with a human user.
710*0957b409SSimon J. Gerraty 		 */
711*0957b409SSimon J. Gerraty 		if (rlen == 0) {
712*0957b409SSimon J. Gerraty 			make_ready_in(rc);
713*0957b409SSimon J. Gerraty 		} else {
714*0957b409SSimon J. Gerraty 			rc->ixa = rc->ixb = 5;
715*0957b409SSimon J. Gerraty 			rc->ixc = rlen;
716*0957b409SSimon J. Gerraty 		}
717*0957b409SSimon J. Gerraty 		return;
718*0957b409SSimon J. Gerraty 	}
719*0957b409SSimon J. Gerraty 
720*0957b409SSimon J. Gerraty 	/*
721*0957b409SSimon J. Gerraty 	 * If there is no active encryption, then the data can be read
722*0957b409SSimon J. Gerraty 	 * right away. Note that we do not receive bytes from the
723*0957b409SSimon J. Gerraty 	 * transport medium when we still have payload bytes to be
724*0957b409SSimon J. Gerraty 	 * acknowledged.
725*0957b409SSimon J. Gerraty 	 */
726*0957b409SSimon J. Gerraty 	if (!rc->incrypt) {
727*0957b409SSimon J. Gerraty 		rc->ixa = 5;
728*0957b409SSimon J. Gerraty 		return;
729*0957b409SSimon J. Gerraty 	}
730*0957b409SSimon J. Gerraty 
731*0957b409SSimon J. Gerraty 	/*
732*0957b409SSimon J. Gerraty 	 * Since encryption is active, we must wait for a full record
733*0957b409SSimon J. Gerraty 	 * before processing it.
734*0957b409SSimon J. Gerraty 	 */
735*0957b409SSimon J. Gerraty 	if (rc->ixc != 0) {
736*0957b409SSimon J. Gerraty 		return;
737*0957b409SSimon J. Gerraty 	}
738*0957b409SSimon J. Gerraty 
739*0957b409SSimon J. Gerraty 	/*
740*0957b409SSimon J. Gerraty 	 * We got the full record. Decrypt it.
741*0957b409SSimon J. Gerraty 	 */
742*0957b409SSimon J. Gerraty 	pbuf_len = rc->ixa - 5;
743*0957b409SSimon J. Gerraty 	pbuf = rc->in.vtable->decrypt(&rc->in.vtable,
744*0957b409SSimon J. Gerraty 		rc->record_type_in, rc->version_in, rc->ibuf + 5, &pbuf_len);
745*0957b409SSimon J. Gerraty 	if (pbuf == 0) {
746*0957b409SSimon J. Gerraty 		br_ssl_engine_fail(rc, BR_ERR_BAD_MAC);
747*0957b409SSimon J. Gerraty 		return;
748*0957b409SSimon J. Gerraty 	}
749*0957b409SSimon J. Gerraty 	rc->ixa = (size_t)(pbuf - rc->ibuf);
750*0957b409SSimon J. Gerraty 	rc->ixb = rc->ixa + pbuf_len;
751*0957b409SSimon J. Gerraty 
752*0957b409SSimon J. Gerraty 	/*
753*0957b409SSimon J. Gerraty 	 * Decryption may have yielded an empty record, in which case
754*0957b409SSimon J. Gerraty 	 * we get back to "ready" state immediately.
755*0957b409SSimon J. Gerraty 	 */
756*0957b409SSimon J. Gerraty 	if (rc->ixa == rc->ixb) {
757*0957b409SSimon J. Gerraty 		make_ready_in(rc);
758*0957b409SSimon J. Gerraty 	}
759*0957b409SSimon J. Gerraty }
760*0957b409SSimon J. Gerraty 
761*0957b409SSimon J. Gerraty /* see inner.h */
762*0957b409SSimon J. Gerraty int
763*0957b409SSimon J. Gerraty br_ssl_engine_recvrec_finished(const br_ssl_engine_context *rc)
764*0957b409SSimon J. Gerraty {
765*0957b409SSimon J. Gerraty 	switch (rc->iomode) {
766*0957b409SSimon J. Gerraty 	case BR_IO_IN:
767*0957b409SSimon J. Gerraty 	case BR_IO_INOUT:
768*0957b409SSimon J. Gerraty 		return rc->ixc == 0 || rc->ixa < 5;
769*0957b409SSimon J. Gerraty 	default:
770*0957b409SSimon J. Gerraty 		return 1;
771*0957b409SSimon J. Gerraty 	}
772*0957b409SSimon J. Gerraty }
773*0957b409SSimon J. Gerraty 
774*0957b409SSimon J. Gerraty static unsigned char *
775*0957b409SSimon J. Gerraty recvpld_buf(const br_ssl_engine_context *rc, size_t *len)
776*0957b409SSimon J. Gerraty {
777*0957b409SSimon J. Gerraty 	/*
778*0957b409SSimon J. Gerraty 	 * There is payload data to be read only if the mode is
779*0957b409SSimon J. Gerraty 	 * compatible, and ixa != ixb.
780*0957b409SSimon J. Gerraty 	 */
781*0957b409SSimon J. Gerraty 	switch (rc->iomode) {
782*0957b409SSimon J. Gerraty 	case BR_IO_IN:
783*0957b409SSimon J. Gerraty 	case BR_IO_INOUT:
784*0957b409SSimon J. Gerraty 		*len = rc->ixb - rc->ixa;
785*0957b409SSimon J. Gerraty 		return (*len == 0) ? NULL : (rc->ibuf + rc->ixa);
786*0957b409SSimon J. Gerraty 	default:
787*0957b409SSimon J. Gerraty 		*len = 0;
788*0957b409SSimon J. Gerraty 		return NULL;
789*0957b409SSimon J. Gerraty 	}
790*0957b409SSimon J. Gerraty }
791*0957b409SSimon J. Gerraty 
792*0957b409SSimon J. Gerraty static void
793*0957b409SSimon J. Gerraty recvpld_ack(br_ssl_engine_context *rc, size_t len)
794*0957b409SSimon J. Gerraty {
795*0957b409SSimon J. Gerraty 	rc->ixa += len;
796*0957b409SSimon J. Gerraty 
797*0957b409SSimon J. Gerraty 	/*
798*0957b409SSimon J. Gerraty 	 * If we read all the available data, then we either expect
799*0957b409SSimon J. Gerraty 	 * the remainder of the current record (if the current record
800*0957b409SSimon J. Gerraty 	 * was not finished; this may happen when encryption is not
801*0957b409SSimon J. Gerraty 	 * active), or go to "ready" state.
802*0957b409SSimon J. Gerraty 	 */
803*0957b409SSimon J. Gerraty 	if (rc->ixa == rc->ixb) {
804*0957b409SSimon J. Gerraty 		if (rc->ixc == 0) {
805*0957b409SSimon J. Gerraty 			make_ready_in(rc);
806*0957b409SSimon J. Gerraty 		} else {
807*0957b409SSimon J. Gerraty 			rc->ixa = rc->ixb = 5;
808*0957b409SSimon J. Gerraty 		}
809*0957b409SSimon J. Gerraty 	}
810*0957b409SSimon J. Gerraty }
811*0957b409SSimon J. Gerraty 
812*0957b409SSimon J. Gerraty static unsigned char *
813*0957b409SSimon J. Gerraty sendpld_buf(const br_ssl_engine_context *rc, size_t *len)
814*0957b409SSimon J. Gerraty {
815*0957b409SSimon J. Gerraty 	/*
816*0957b409SSimon J. Gerraty 	 * Payload data can be injected only if the current mode is
817*0957b409SSimon J. Gerraty 	 * compatible, and oxa != oxb.
818*0957b409SSimon J. Gerraty 	 */
819*0957b409SSimon J. Gerraty 	switch (rc->iomode) {
820*0957b409SSimon J. Gerraty 	case BR_IO_OUT:
821*0957b409SSimon J. Gerraty 	case BR_IO_INOUT:
822*0957b409SSimon J. Gerraty 		*len = rc->oxb - rc->oxa;
823*0957b409SSimon J. Gerraty 		return (*len == 0) ? NULL : (rc->obuf + rc->oxa);
824*0957b409SSimon J. Gerraty 	default:
825*0957b409SSimon J. Gerraty 		*len = 0;
826*0957b409SSimon J. Gerraty 		return NULL;
827*0957b409SSimon J. Gerraty 	}
828*0957b409SSimon J. Gerraty }
829*0957b409SSimon J. Gerraty 
830*0957b409SSimon J. Gerraty /*
831*0957b409SSimon J. Gerraty  * If some payload bytes have been accumulated, then wrap them into
832*0957b409SSimon J. Gerraty  * an outgoing record. Otherwise, this function does nothing, unless
833*0957b409SSimon J. Gerraty  * 'force' is non-zero, in which case an empty record is assembled.
834*0957b409SSimon J. Gerraty  *
835*0957b409SSimon J. Gerraty  * The caller must take care not to invoke this function if the engine
836*0957b409SSimon J. Gerraty  * is not currently ready to receive payload bytes to send.
837*0957b409SSimon J. Gerraty  */
838*0957b409SSimon J. Gerraty static void
839*0957b409SSimon J. Gerraty sendpld_flush(br_ssl_engine_context *rc, int force)
840*0957b409SSimon J. Gerraty {
841*0957b409SSimon J. Gerraty 	size_t xlen;
842*0957b409SSimon J. Gerraty 	unsigned char *buf;
843*0957b409SSimon J. Gerraty 
844*0957b409SSimon J. Gerraty 	if (rc->oxa == rc->oxb) {
845*0957b409SSimon J. Gerraty 		return;
846*0957b409SSimon J. Gerraty 	}
847*0957b409SSimon J. Gerraty 	xlen = rc->oxa - rc->oxc;
848*0957b409SSimon J. Gerraty 	if (xlen == 0 && !force) {
849*0957b409SSimon J. Gerraty 		return;
850*0957b409SSimon J. Gerraty 	}
851*0957b409SSimon J. Gerraty 	buf = rc->out.vtable->encrypt(&rc->out.vtable,
852*0957b409SSimon J. Gerraty 		rc->record_type_out, rc->version_out,
853*0957b409SSimon J. Gerraty 		rc->obuf + rc->oxc, &xlen);
854*0957b409SSimon J. Gerraty 	rc->oxb = rc->oxa = (size_t)(buf - rc->obuf);
855*0957b409SSimon J. Gerraty 	rc->oxc = rc->oxa + xlen;
856*0957b409SSimon J. Gerraty }
857*0957b409SSimon J. Gerraty 
858*0957b409SSimon J. Gerraty static void
859*0957b409SSimon J. Gerraty sendpld_ack(br_ssl_engine_context *rc, size_t len)
860*0957b409SSimon J. Gerraty {
861*0957b409SSimon J. Gerraty 	/*
862*0957b409SSimon J. Gerraty 	 * If using a shared buffer, then we may have to modify the
863*0957b409SSimon J. Gerraty 	 * current mode.
864*0957b409SSimon J. Gerraty 	 */
865*0957b409SSimon J. Gerraty 	if (rc->iomode == BR_IO_INOUT && rc->ibuf == rc->obuf) {
866*0957b409SSimon J. Gerraty 		rc->iomode = BR_IO_OUT;
867*0957b409SSimon J. Gerraty 	}
868*0957b409SSimon J. Gerraty 	rc->oxa += len;
869*0957b409SSimon J. Gerraty 	if (rc->oxa >= rc->oxb) {
870*0957b409SSimon J. Gerraty 		/*
871*0957b409SSimon J. Gerraty 		 * Set oxb to one more than oxa so that sendpld_flush()
872*0957b409SSimon J. Gerraty 		 * does not mistakingly believe that a record is
873*0957b409SSimon J. Gerraty 		 * already prepared and being sent.
874*0957b409SSimon J. Gerraty 		 */
875*0957b409SSimon J. Gerraty 		rc->oxb = rc->oxa + 1;
876*0957b409SSimon J. Gerraty 		sendpld_flush(rc, 0);
877*0957b409SSimon J. Gerraty 	}
878*0957b409SSimon J. Gerraty }
879*0957b409SSimon J. Gerraty 
880*0957b409SSimon J. Gerraty static unsigned char *
881*0957b409SSimon J. Gerraty sendrec_buf(const br_ssl_engine_context *rc, size_t *len)
882*0957b409SSimon J. Gerraty {
883*0957b409SSimon J. Gerraty 	/*
884*0957b409SSimon J. Gerraty 	 * When still gathering payload bytes, oxc points to the start
885*0957b409SSimon J. Gerraty 	 * of the record data, so oxc <= oxa. However, when a full
886*0957b409SSimon J. Gerraty 	 * record has been completed, oxc points to the end of the record,
887*0957b409SSimon J. Gerraty 	 * so oxc > oxa.
888*0957b409SSimon J. Gerraty 	 */
889*0957b409SSimon J. Gerraty 	switch (rc->iomode) {
890*0957b409SSimon J. Gerraty 	case BR_IO_OUT:
891*0957b409SSimon J. Gerraty 	case BR_IO_INOUT:
892*0957b409SSimon J. Gerraty 		if (rc->oxc > rc->oxa) {
893*0957b409SSimon J. Gerraty 			*len = rc->oxc - rc->oxa;
894*0957b409SSimon J. Gerraty 			return rc->obuf + rc->oxa;
895*0957b409SSimon J. Gerraty 		}
896*0957b409SSimon J. Gerraty 		break;
897*0957b409SSimon J. Gerraty 	}
898*0957b409SSimon J. Gerraty 	*len = 0;
899*0957b409SSimon J. Gerraty 	return NULL;
900*0957b409SSimon J. Gerraty }
901*0957b409SSimon J. Gerraty 
902*0957b409SSimon J. Gerraty static void
903*0957b409SSimon J. Gerraty sendrec_ack(br_ssl_engine_context *rc, size_t len)
904*0957b409SSimon J. Gerraty {
905*0957b409SSimon J. Gerraty 	rc->oxb = (rc->oxa += len);
906*0957b409SSimon J. Gerraty 	if (rc->oxa == rc->oxc) {
907*0957b409SSimon J. Gerraty 		make_ready_out(rc);
908*0957b409SSimon J. Gerraty 	}
909*0957b409SSimon J. Gerraty }
910*0957b409SSimon J. Gerraty 
911*0957b409SSimon J. Gerraty /*
912*0957b409SSimon J. Gerraty  * Test whether there is some buffered outgoing record that still must
913*0957b409SSimon J. Gerraty  * sent.
914*0957b409SSimon J. Gerraty  */
915*0957b409SSimon J. Gerraty static inline int
916*0957b409SSimon J. Gerraty has_rec_tosend(const br_ssl_engine_context *rc)
917*0957b409SSimon J. Gerraty {
918*0957b409SSimon J. Gerraty 	return rc->oxa == rc->oxb && rc->oxa != rc->oxc;
919*0957b409SSimon J. Gerraty }
920*0957b409SSimon J. Gerraty 
921*0957b409SSimon J. Gerraty /*
922*0957b409SSimon J. Gerraty  * The "no encryption" mode has no overhead. It limits the payload size
923*0957b409SSimon J. Gerraty  * to the maximum size allowed by the standard (16384 bytes); the caller
924*0957b409SSimon J. Gerraty  * is responsible for possibly enforcing a smaller fragment length.
925*0957b409SSimon J. Gerraty  */
926*0957b409SSimon J. Gerraty static void
927*0957b409SSimon J. Gerraty clear_max_plaintext(const br_sslrec_out_clear_context *cc,
928*0957b409SSimon J. Gerraty 	size_t *start, size_t *end)
929*0957b409SSimon J. Gerraty {
930*0957b409SSimon J. Gerraty 	size_t len;
931*0957b409SSimon J. Gerraty 
932*0957b409SSimon J. Gerraty 	(void)cc;
933*0957b409SSimon J. Gerraty 	len = *end - *start;
934*0957b409SSimon J. Gerraty 	if (len > 16384) {
935*0957b409SSimon J. Gerraty 		*end = *start + 16384;
936*0957b409SSimon J. Gerraty 	}
937*0957b409SSimon J. Gerraty }
938*0957b409SSimon J. Gerraty 
939*0957b409SSimon J. Gerraty /*
940*0957b409SSimon J. Gerraty  * In "no encryption" mode, encryption is trivial (a no-operation) so
941*0957b409SSimon J. Gerraty  * we just have to encode the header.
942*0957b409SSimon J. Gerraty  */
943*0957b409SSimon J. Gerraty static unsigned char *
944*0957b409SSimon J. Gerraty clear_encrypt(br_sslrec_out_clear_context *cc,
945*0957b409SSimon J. Gerraty 	int record_type, unsigned version, void *data, size_t *data_len)
946*0957b409SSimon J. Gerraty {
947*0957b409SSimon J. Gerraty 	unsigned char *buf;
948*0957b409SSimon J. Gerraty 
949*0957b409SSimon J. Gerraty 	(void)cc;
950*0957b409SSimon J. Gerraty 	buf = (unsigned char *)data - 5;
951*0957b409SSimon J. Gerraty 	buf[0] = record_type;
952*0957b409SSimon J. Gerraty 	br_enc16be(buf + 1, version);
953*0957b409SSimon J. Gerraty 	br_enc16be(buf + 3, *data_len);
954*0957b409SSimon J. Gerraty 	*data_len += 5;
955*0957b409SSimon J. Gerraty 	return buf;
956*0957b409SSimon J. Gerraty }
957*0957b409SSimon J. Gerraty 
958*0957b409SSimon J. Gerraty /* see bearssl_ssl.h */
959*0957b409SSimon J. Gerraty const br_sslrec_out_class br_sslrec_out_clear_vtable = {
960*0957b409SSimon J. Gerraty 	sizeof(br_sslrec_out_clear_context),
961*0957b409SSimon J. Gerraty 	(void (*)(const br_sslrec_out_class *const *, size_t *, size_t *))
962*0957b409SSimon J. Gerraty 		&clear_max_plaintext,
963*0957b409SSimon J. Gerraty 	(unsigned char *(*)(const br_sslrec_out_class **,
964*0957b409SSimon J. Gerraty 		int, unsigned, void *, size_t *))
965*0957b409SSimon J. Gerraty 		&clear_encrypt
966*0957b409SSimon J. Gerraty };
967*0957b409SSimon J. Gerraty 
968*0957b409SSimon J. Gerraty /* ==================================================================== */
969*0957b409SSimon J. Gerraty /*
970*0957b409SSimon J. Gerraty  * In this part of the file, we handle the various record types, and
971*0957b409SSimon J. Gerraty  * communications with the handshake processor.
972*0957b409SSimon J. Gerraty  */
973*0957b409SSimon J. Gerraty 
974*0957b409SSimon J. Gerraty /*
975*0957b409SSimon J. Gerraty  * IMPLEMENTATION NOTES
976*0957b409SSimon J. Gerraty  * ====================
977*0957b409SSimon J. Gerraty  *
978*0957b409SSimon J. Gerraty  * The handshake processor is written in T0 and runs as a coroutine.
979*0957b409SSimon J. Gerraty  * It receives the contents of all records except application data, and
980*0957b409SSimon J. Gerraty  * is responsible for producing the contents of all records except
981*0957b409SSimon J. Gerraty  * application data.
982*0957b409SSimon J. Gerraty  *
983*0957b409SSimon J. Gerraty  * A state flag is maintained, which specifies whether application data
984*0957b409SSimon J. Gerraty  * is acceptable or not. When it is set:
985*0957b409SSimon J. Gerraty  *
986*0957b409SSimon J. Gerraty  * -- Application data can be injected as payload data (provided that
987*0957b409SSimon J. Gerraty  *    the output buffer is ready for that).
988*0957b409SSimon J. Gerraty  *
989*0957b409SSimon J. Gerraty  * -- Incoming application data records are accepted, and yield data
990*0957b409SSimon J. Gerraty  *    that the caller may retrieve.
991*0957b409SSimon J. Gerraty  *
992*0957b409SSimon J. Gerraty  * When the flag is cleared, application data is not accepted from the
993*0957b409SSimon J. Gerraty  * application, and incoming application data records trigger an error.
994*0957b409SSimon J. Gerraty  *
995*0957b409SSimon J. Gerraty  *
996*0957b409SSimon J. Gerraty  * Records of type handshake, alert or change-cipher-spec are handled
997*0957b409SSimon J. Gerraty  * by the handshake processor. The handshake processor is written in T0
998*0957b409SSimon J. Gerraty  * and runs as a coroutine; it gets invoked whenever one of the following
999*0957b409SSimon J. Gerraty  * situations is reached:
1000*0957b409SSimon J. Gerraty  *
1001*0957b409SSimon J. Gerraty  * -- An incoming record has type handshake, alert or change-cipher-spec,
1002*0957b409SSimon J. Gerraty  *    and yields data that can be read (zero-length records are thus
1003*0957b409SSimon J. Gerraty  *    ignored).
1004*0957b409SSimon J. Gerraty  *
1005*0957b409SSimon J. Gerraty  * -- An outgoing record has just finished being sent, and the "application
1006*0957b409SSimon J. Gerraty  *    data" flag is cleared.
1007*0957b409SSimon J. Gerraty  *
1008*0957b409SSimon J. Gerraty  * -- The caller wishes to perform a close (call to br_ssl_engine_close()).
1009*0957b409SSimon J. Gerraty  *
1010*0957b409SSimon J. Gerraty  * -- The caller wishes to perform a renegotiation (call to
1011*0957b409SSimon J. Gerraty  *    br_ssl_engine_renegotiate()).
1012*0957b409SSimon J. Gerraty  *
1013*0957b409SSimon J. Gerraty  * Whenever the handshake processor is entered, access to the payload
1014*0957b409SSimon J. Gerraty  * buffers is provided, along with some information about explicit
1015*0957b409SSimon J. Gerraty  * closures or renegotiations.
1016*0957b409SSimon J. Gerraty  */
1017*0957b409SSimon J. Gerraty 
1018*0957b409SSimon J. Gerraty /* see bearssl_ssl.h */
1019*0957b409SSimon J. Gerraty void
1020*0957b409SSimon J. Gerraty br_ssl_engine_set_suites(br_ssl_engine_context *cc,
1021*0957b409SSimon J. Gerraty 	const uint16_t *suites, size_t suites_num)
1022*0957b409SSimon J. Gerraty {
1023*0957b409SSimon J. Gerraty 	if ((suites_num * sizeof *suites) > sizeof cc->suites_buf) {
1024*0957b409SSimon J. Gerraty 		br_ssl_engine_fail(cc, BR_ERR_BAD_PARAM);
1025*0957b409SSimon J. Gerraty 		return;
1026*0957b409SSimon J. Gerraty 	}
1027*0957b409SSimon J. Gerraty 	memcpy(cc->suites_buf, suites, suites_num * sizeof *suites);
1028*0957b409SSimon J. Gerraty 	cc->suites_num = suites_num;
1029*0957b409SSimon J. Gerraty }
1030*0957b409SSimon J. Gerraty 
1031*0957b409SSimon J. Gerraty /*
1032*0957b409SSimon J. Gerraty  * Give control to handshake processor. 'action' is 1 for a close,
1033*0957b409SSimon J. Gerraty  * 2 for a renegotiation, or 0 for a jump due to I/O completion.
1034*0957b409SSimon J. Gerraty  */
1035*0957b409SSimon J. Gerraty static void
1036*0957b409SSimon J. Gerraty jump_handshake(br_ssl_engine_context *cc, int action)
1037*0957b409SSimon J. Gerraty {
1038*0957b409SSimon J. Gerraty 	/*
1039*0957b409SSimon J. Gerraty 	 * We use a loop because the handshake processor actions may
1040*0957b409SSimon J. Gerraty 	 * allow for more actions; namely, if the processor reads all
1041*0957b409SSimon J. Gerraty 	 * input data, then it may allow for output data to be produced,
1042*0957b409SSimon J. Gerraty 	 * in case of a shared in/out buffer.
1043*0957b409SSimon J. Gerraty 	 */
1044*0957b409SSimon J. Gerraty 	for (;;) {
1045*0957b409SSimon J. Gerraty 		size_t hlen_in, hlen_out;
1046*0957b409SSimon J. Gerraty 
1047*0957b409SSimon J. Gerraty 		/*
1048*0957b409SSimon J. Gerraty 		 * Get input buffer. We do not want to provide
1049*0957b409SSimon J. Gerraty 		 * application data to the handshake processor (we could
1050*0957b409SSimon J. Gerraty 		 * get called with an explicit close or renegotiation
1051*0957b409SSimon J. Gerraty 		 * while there is application data ready to be read).
1052*0957b409SSimon J. Gerraty 		 */
1053*0957b409SSimon J. Gerraty 		cc->hbuf_in = recvpld_buf(cc, &hlen_in);
1054*0957b409SSimon J. Gerraty 		if (cc->hbuf_in != NULL
1055*0957b409SSimon J. Gerraty 			&& cc->record_type_in == BR_SSL_APPLICATION_DATA)
1056*0957b409SSimon J. Gerraty 		{
1057*0957b409SSimon J. Gerraty 			hlen_in = 0;
1058*0957b409SSimon J. Gerraty 		}
1059*0957b409SSimon J. Gerraty 
1060*0957b409SSimon J. Gerraty 		/*
1061*0957b409SSimon J. Gerraty 		 * Get output buffer. The handshake processor never
1062*0957b409SSimon J. Gerraty 		 * leaves an unfinished outgoing record, so if there is
1063*0957b409SSimon J. Gerraty 		 * buffered output, then it MUST be some application
1064*0957b409SSimon J. Gerraty 		 * data, so the processor cannot write to it.
1065*0957b409SSimon J. Gerraty 		 */
1066*0957b409SSimon J. Gerraty 		cc->saved_hbuf_out = cc->hbuf_out = sendpld_buf(cc, &hlen_out);
1067*0957b409SSimon J. Gerraty 		if (cc->hbuf_out != NULL && br_ssl_engine_has_pld_to_send(cc)) {
1068*0957b409SSimon J. Gerraty 			hlen_out = 0;
1069*0957b409SSimon J. Gerraty 		}
1070*0957b409SSimon J. Gerraty 
1071*0957b409SSimon J. Gerraty 		/*
1072*0957b409SSimon J. Gerraty 		 * Note: hlen_in and hlen_out can be both non-zero only if
1073*0957b409SSimon J. Gerraty 		 * the input and output buffers are disjoint. Thus, we can
1074*0957b409SSimon J. Gerraty 		 * offer both buffers to the handshake code.
1075*0957b409SSimon J. Gerraty 		 */
1076*0957b409SSimon J. Gerraty 
1077*0957b409SSimon J. Gerraty 		cc->hlen_in = hlen_in;
1078*0957b409SSimon J. Gerraty 		cc->hlen_out = hlen_out;
1079*0957b409SSimon J. Gerraty 		cc->action = action;
1080*0957b409SSimon J. Gerraty 		cc->hsrun(&cc->cpu);
1081*0957b409SSimon J. Gerraty 		if (br_ssl_engine_closed(cc)) {
1082*0957b409SSimon J. Gerraty 			return;
1083*0957b409SSimon J. Gerraty 		}
1084*0957b409SSimon J. Gerraty 		if (cc->hbuf_out != cc->saved_hbuf_out) {
1085*0957b409SSimon J. Gerraty 			sendpld_ack(cc, cc->hbuf_out - cc->saved_hbuf_out);
1086*0957b409SSimon J. Gerraty 		}
1087*0957b409SSimon J. Gerraty 		if (hlen_in != cc->hlen_in) {
1088*0957b409SSimon J. Gerraty 			recvpld_ack(cc, hlen_in - cc->hlen_in);
1089*0957b409SSimon J. Gerraty 			if (cc->hlen_in == 0) {
1090*0957b409SSimon J. Gerraty 				/*
1091*0957b409SSimon J. Gerraty 				 * We read all data bytes, which may have
1092*0957b409SSimon J. Gerraty 				 * released the output buffer in case it
1093*0957b409SSimon J. Gerraty 				 * is shared with the input buffer, and
1094*0957b409SSimon J. Gerraty 				 * the handshake code might be waiting for
1095*0957b409SSimon J. Gerraty 				 * that.
1096*0957b409SSimon J. Gerraty 				 */
1097*0957b409SSimon J. Gerraty 				action = 0;
1098*0957b409SSimon J. Gerraty 				continue;
1099*0957b409SSimon J. Gerraty 			}
1100*0957b409SSimon J. Gerraty 		}
1101*0957b409SSimon J. Gerraty 		break;
1102*0957b409SSimon J. Gerraty 	}
1103*0957b409SSimon J. Gerraty }
1104*0957b409SSimon J. Gerraty 
1105*0957b409SSimon J. Gerraty /* see inner.h */
1106*0957b409SSimon J. Gerraty void
1107*0957b409SSimon J. Gerraty br_ssl_engine_flush_record(br_ssl_engine_context *cc)
1108*0957b409SSimon J. Gerraty {
1109*0957b409SSimon J. Gerraty 	if (cc->hbuf_out != cc->saved_hbuf_out) {
1110*0957b409SSimon J. Gerraty 		sendpld_ack(cc, cc->hbuf_out - cc->saved_hbuf_out);
1111*0957b409SSimon J. Gerraty 	}
1112*0957b409SSimon J. Gerraty 	if (br_ssl_engine_has_pld_to_send(cc)) {
1113*0957b409SSimon J. Gerraty 		sendpld_flush(cc, 0);
1114*0957b409SSimon J. Gerraty 	}
1115*0957b409SSimon J. Gerraty 	cc->saved_hbuf_out = cc->hbuf_out = sendpld_buf(cc, &cc->hlen_out);
1116*0957b409SSimon J. Gerraty }
1117*0957b409SSimon J. Gerraty 
1118*0957b409SSimon J. Gerraty /* see bearssl_ssl.h */
1119*0957b409SSimon J. Gerraty unsigned char *
1120*0957b409SSimon J. Gerraty br_ssl_engine_sendapp_buf(const br_ssl_engine_context *cc, size_t *len)
1121*0957b409SSimon J. Gerraty {
1122*0957b409SSimon J. Gerraty 	if (!(cc->application_data & 1)) {
1123*0957b409SSimon J. Gerraty 		*len = 0;
1124*0957b409SSimon J. Gerraty 		return NULL;
1125*0957b409SSimon J. Gerraty 	}
1126*0957b409SSimon J. Gerraty 	return sendpld_buf(cc, len);
1127*0957b409SSimon J. Gerraty }
1128*0957b409SSimon J. Gerraty 
1129*0957b409SSimon J. Gerraty /* see bearssl_ssl.h */
1130*0957b409SSimon J. Gerraty void
1131*0957b409SSimon J. Gerraty br_ssl_engine_sendapp_ack(br_ssl_engine_context *cc, size_t len)
1132*0957b409SSimon J. Gerraty {
1133*0957b409SSimon J. Gerraty 	sendpld_ack(cc, len);
1134*0957b409SSimon J. Gerraty }
1135*0957b409SSimon J. Gerraty 
1136*0957b409SSimon J. Gerraty /* see bearssl_ssl.h */
1137*0957b409SSimon J. Gerraty unsigned char *
1138*0957b409SSimon J. Gerraty br_ssl_engine_recvapp_buf(const br_ssl_engine_context *cc, size_t *len)
1139*0957b409SSimon J. Gerraty {
1140*0957b409SSimon J. Gerraty 	if (!(cc->application_data & 1)
1141*0957b409SSimon J. Gerraty 		|| cc->record_type_in != BR_SSL_APPLICATION_DATA)
1142*0957b409SSimon J. Gerraty 	{
1143*0957b409SSimon J. Gerraty 		*len = 0;
1144*0957b409SSimon J. Gerraty 		return NULL;
1145*0957b409SSimon J. Gerraty 	}
1146*0957b409SSimon J. Gerraty 	return recvpld_buf(cc, len);
1147*0957b409SSimon J. Gerraty }
1148*0957b409SSimon J. Gerraty 
1149*0957b409SSimon J. Gerraty /* see bearssl_ssl.h */
1150*0957b409SSimon J. Gerraty void
1151*0957b409SSimon J. Gerraty br_ssl_engine_recvapp_ack(br_ssl_engine_context *cc, size_t len)
1152*0957b409SSimon J. Gerraty {
1153*0957b409SSimon J. Gerraty 	recvpld_ack(cc, len);
1154*0957b409SSimon J. Gerraty }
1155*0957b409SSimon J. Gerraty 
1156*0957b409SSimon J. Gerraty /* see bearssl_ssl.h */
1157*0957b409SSimon J. Gerraty unsigned char *
1158*0957b409SSimon J. Gerraty br_ssl_engine_sendrec_buf(const br_ssl_engine_context *cc, size_t *len)
1159*0957b409SSimon J. Gerraty {
1160*0957b409SSimon J. Gerraty 	return sendrec_buf(cc, len);
1161*0957b409SSimon J. Gerraty }
1162*0957b409SSimon J. Gerraty 
1163*0957b409SSimon J. Gerraty /* see bearssl_ssl.h */
1164*0957b409SSimon J. Gerraty void
1165*0957b409SSimon J. Gerraty br_ssl_engine_sendrec_ack(br_ssl_engine_context *cc, size_t len)
1166*0957b409SSimon J. Gerraty {
1167*0957b409SSimon J. Gerraty 	sendrec_ack(cc, len);
1168*0957b409SSimon J. Gerraty 	if (len != 0 && !has_rec_tosend(cc)
1169*0957b409SSimon J. Gerraty 		&& (cc->record_type_out != BR_SSL_APPLICATION_DATA
1170*0957b409SSimon J. Gerraty 		|| (cc->application_data & 1) == 0))
1171*0957b409SSimon J. Gerraty 	{
1172*0957b409SSimon J. Gerraty 		jump_handshake(cc, 0);
1173*0957b409SSimon J. Gerraty 	}
1174*0957b409SSimon J. Gerraty }
1175*0957b409SSimon J. Gerraty 
1176*0957b409SSimon J. Gerraty /* see bearssl_ssl.h */
1177*0957b409SSimon J. Gerraty unsigned char *
1178*0957b409SSimon J. Gerraty br_ssl_engine_recvrec_buf(const br_ssl_engine_context *cc, size_t *len)
1179*0957b409SSimon J. Gerraty {
1180*0957b409SSimon J. Gerraty 	return recvrec_buf(cc, len);
1181*0957b409SSimon J. Gerraty }
1182*0957b409SSimon J. Gerraty 
1183*0957b409SSimon J. Gerraty /* see bearssl_ssl.h */
1184*0957b409SSimon J. Gerraty void
1185*0957b409SSimon J. Gerraty br_ssl_engine_recvrec_ack(br_ssl_engine_context *cc, size_t len)
1186*0957b409SSimon J. Gerraty {
1187*0957b409SSimon J. Gerraty 	unsigned char *buf;
1188*0957b409SSimon J. Gerraty 
1189*0957b409SSimon J. Gerraty 	recvrec_ack(cc, len);
1190*0957b409SSimon J. Gerraty 	if (br_ssl_engine_closed(cc)) {
1191*0957b409SSimon J. Gerraty 		return;
1192*0957b409SSimon J. Gerraty 	}
1193*0957b409SSimon J. Gerraty 
1194*0957b409SSimon J. Gerraty 	/*
1195*0957b409SSimon J. Gerraty 	 * We just received some bytes from the peer. This may have
1196*0957b409SSimon J. Gerraty 	 * yielded some payload bytes, in which case we must process
1197*0957b409SSimon J. Gerraty 	 * them according to the record type.
1198*0957b409SSimon J. Gerraty 	 */
1199*0957b409SSimon J. Gerraty 	buf = recvpld_buf(cc, &len);
1200*0957b409SSimon J. Gerraty 	if (buf != NULL) {
1201*0957b409SSimon J. Gerraty 		switch (cc->record_type_in) {
1202*0957b409SSimon J. Gerraty 		case BR_SSL_CHANGE_CIPHER_SPEC:
1203*0957b409SSimon J. Gerraty 		case BR_SSL_ALERT:
1204*0957b409SSimon J. Gerraty 		case BR_SSL_HANDSHAKE:
1205*0957b409SSimon J. Gerraty 			jump_handshake(cc, 0);
1206*0957b409SSimon J. Gerraty 			break;
1207*0957b409SSimon J. Gerraty 		case BR_SSL_APPLICATION_DATA:
1208*0957b409SSimon J. Gerraty 			if (cc->application_data == 1) {
1209*0957b409SSimon J. Gerraty 				break;
1210*0957b409SSimon J. Gerraty 			}
1211*0957b409SSimon J. Gerraty 
1212*0957b409SSimon J. Gerraty 			/*
1213*0957b409SSimon J. Gerraty 			 * If we are currently closing, and waiting for
1214*0957b409SSimon J. Gerraty 			 * a close_notify from the peer, then incoming
1215*0957b409SSimon J. Gerraty 			 * application data should be discarded.
1216*0957b409SSimon J. Gerraty 			 */
1217*0957b409SSimon J. Gerraty 			if (cc->application_data == 2) {
1218*0957b409SSimon J. Gerraty 				recvpld_ack(cc, len);
1219*0957b409SSimon J. Gerraty 				break;
1220*0957b409SSimon J. Gerraty 			}
1221*0957b409SSimon J. Gerraty 
1222*0957b409SSimon J. Gerraty 			/* Fall through */
1223*0957b409SSimon J. Gerraty 		default:
1224*0957b409SSimon J. Gerraty 			br_ssl_engine_fail(cc, BR_ERR_UNEXPECTED);
1225*0957b409SSimon J. Gerraty 			break;
1226*0957b409SSimon J. Gerraty 		}
1227*0957b409SSimon J. Gerraty 	}
1228*0957b409SSimon J. Gerraty }
1229*0957b409SSimon J. Gerraty 
1230*0957b409SSimon J. Gerraty /* see bearssl_ssl.h */
1231*0957b409SSimon J. Gerraty void
1232*0957b409SSimon J. Gerraty br_ssl_engine_close(br_ssl_engine_context *cc)
1233*0957b409SSimon J. Gerraty {
1234*0957b409SSimon J. Gerraty 	if (!br_ssl_engine_closed(cc)) {
1235*0957b409SSimon J. Gerraty 		jump_handshake(cc, 1);
1236*0957b409SSimon J. Gerraty 	}
1237*0957b409SSimon J. Gerraty }
1238*0957b409SSimon J. Gerraty 
1239*0957b409SSimon J. Gerraty /* see bearssl_ssl.h */
1240*0957b409SSimon J. Gerraty int
1241*0957b409SSimon J. Gerraty br_ssl_engine_renegotiate(br_ssl_engine_context *cc)
1242*0957b409SSimon J. Gerraty {
1243*0957b409SSimon J. Gerraty 	size_t len;
1244*0957b409SSimon J. Gerraty 
1245*0957b409SSimon J. Gerraty 	if (br_ssl_engine_closed(cc) || cc->reneg == 1
1246*0957b409SSimon J. Gerraty 		|| (cc->flags & BR_OPT_NO_RENEGOTIATION) != 0
1247*0957b409SSimon J. Gerraty 		|| br_ssl_engine_recvapp_buf(cc, &len) != NULL)
1248*0957b409SSimon J. Gerraty 	{
1249*0957b409SSimon J. Gerraty 		return 0;
1250*0957b409SSimon J. Gerraty 	}
1251*0957b409SSimon J. Gerraty 	jump_handshake(cc, 2);
1252*0957b409SSimon J. Gerraty 	return 1;
1253*0957b409SSimon J. Gerraty }
1254*0957b409SSimon J. Gerraty 
1255*0957b409SSimon J. Gerraty /* see bearssl.h */
1256*0957b409SSimon J. Gerraty unsigned
1257*0957b409SSimon J. Gerraty br_ssl_engine_current_state(const br_ssl_engine_context *cc)
1258*0957b409SSimon J. Gerraty {
1259*0957b409SSimon J. Gerraty 	unsigned s;
1260*0957b409SSimon J. Gerraty 	size_t len;
1261*0957b409SSimon J. Gerraty 
1262*0957b409SSimon J. Gerraty 	if (br_ssl_engine_closed(cc)) {
1263*0957b409SSimon J. Gerraty 		return BR_SSL_CLOSED;
1264*0957b409SSimon J. Gerraty 	}
1265*0957b409SSimon J. Gerraty 
1266*0957b409SSimon J. Gerraty 	s = 0;
1267*0957b409SSimon J. Gerraty 	if (br_ssl_engine_sendrec_buf(cc, &len) != NULL) {
1268*0957b409SSimon J. Gerraty 		s |= BR_SSL_SENDREC;
1269*0957b409SSimon J. Gerraty 	}
1270*0957b409SSimon J. Gerraty 	if (br_ssl_engine_recvrec_buf(cc, &len) != NULL) {
1271*0957b409SSimon J. Gerraty 		s |= BR_SSL_RECVREC;
1272*0957b409SSimon J. Gerraty 	}
1273*0957b409SSimon J. Gerraty 	if (br_ssl_engine_sendapp_buf(cc, &len) != NULL) {
1274*0957b409SSimon J. Gerraty 		s |= BR_SSL_SENDAPP;
1275*0957b409SSimon J. Gerraty 	}
1276*0957b409SSimon J. Gerraty 	if (br_ssl_engine_recvapp_buf(cc, &len) != NULL) {
1277*0957b409SSimon J. Gerraty 		s |= BR_SSL_RECVAPP;
1278*0957b409SSimon J. Gerraty 	}
1279*0957b409SSimon J. Gerraty 	return s;
1280*0957b409SSimon J. Gerraty }
1281*0957b409SSimon J. Gerraty 
1282*0957b409SSimon J. Gerraty /* see bearssl_ssl.h */
1283*0957b409SSimon J. Gerraty void
1284*0957b409SSimon J. Gerraty br_ssl_engine_flush(br_ssl_engine_context *cc, int force)
1285*0957b409SSimon J. Gerraty {
1286*0957b409SSimon J. Gerraty 	if (!br_ssl_engine_closed(cc) && (cc->application_data & 1) != 0) {
1287*0957b409SSimon J. Gerraty 		sendpld_flush(cc, force);
1288*0957b409SSimon J. Gerraty 	}
1289*0957b409SSimon J. Gerraty }
1290*0957b409SSimon J. Gerraty 
1291*0957b409SSimon J. Gerraty /* see inner.h */
1292*0957b409SSimon J. Gerraty void
1293*0957b409SSimon J. Gerraty br_ssl_engine_hs_reset(br_ssl_engine_context *cc,
1294*0957b409SSimon J. Gerraty 	void (*hsinit)(void *), void (*hsrun)(void *))
1295*0957b409SSimon J. Gerraty {
1296*0957b409SSimon J. Gerraty 	engine_clearbuf(cc);
1297*0957b409SSimon J. Gerraty 	cc->cpu.dp = cc->dp_stack;
1298*0957b409SSimon J. Gerraty 	cc->cpu.rp = cc->rp_stack;
1299*0957b409SSimon J. Gerraty 	hsinit(&cc->cpu);
1300*0957b409SSimon J. Gerraty 	cc->hsrun = hsrun;
1301*0957b409SSimon J. Gerraty 	cc->shutdown_recv = 0;
1302*0957b409SSimon J. Gerraty 	cc->application_data = 0;
1303*0957b409SSimon J. Gerraty 	cc->alert = 0;
1304*0957b409SSimon J. Gerraty 	jump_handshake(cc, 0);
1305*0957b409SSimon J. Gerraty }
1306*0957b409SSimon J. Gerraty 
1307*0957b409SSimon J. Gerraty /* see inner.h */
1308*0957b409SSimon J. Gerraty br_tls_prf_impl
1309*0957b409SSimon J. Gerraty br_ssl_engine_get_PRF(br_ssl_engine_context *cc, int prf_id)
1310*0957b409SSimon J. Gerraty {
1311*0957b409SSimon J. Gerraty 	if (cc->session.version >= BR_TLS12) {
1312*0957b409SSimon J. Gerraty 		if (prf_id == br_sha384_ID) {
1313*0957b409SSimon J. Gerraty 			return cc->prf_sha384;
1314*0957b409SSimon J. Gerraty 		} else {
1315*0957b409SSimon J. Gerraty 			return cc->prf_sha256;
1316*0957b409SSimon J. Gerraty 		}
1317*0957b409SSimon J. Gerraty 	} else {
1318*0957b409SSimon J. Gerraty 		return cc->prf10;
1319*0957b409SSimon J. Gerraty 	}
1320*0957b409SSimon J. Gerraty }
1321*0957b409SSimon J. Gerraty 
1322*0957b409SSimon J. Gerraty /* see inner.h */
1323*0957b409SSimon J. Gerraty void
1324*0957b409SSimon J. Gerraty br_ssl_engine_compute_master(br_ssl_engine_context *cc,
1325*0957b409SSimon J. Gerraty 	int prf_id, const void *pms, size_t pms_len)
1326*0957b409SSimon J. Gerraty {
1327*0957b409SSimon J. Gerraty 	br_tls_prf_impl iprf;
1328*0957b409SSimon J. Gerraty 	br_tls_prf_seed_chunk seed[2] = {
1329*0957b409SSimon J. Gerraty 		{ cc->client_random, sizeof cc->client_random },
1330*0957b409SSimon J. Gerraty 		{ cc->server_random, sizeof cc->server_random }
1331*0957b409SSimon J. Gerraty 	};
1332*0957b409SSimon J. Gerraty 
1333*0957b409SSimon J. Gerraty 	iprf = br_ssl_engine_get_PRF(cc, prf_id);
1334*0957b409SSimon J. Gerraty 	iprf(cc->session.master_secret, sizeof cc->session.master_secret,
1335*0957b409SSimon J. Gerraty 		pms, pms_len, "master secret", 2, seed);
1336*0957b409SSimon J. Gerraty }
1337*0957b409SSimon J. Gerraty 
1338*0957b409SSimon J. Gerraty /*
1339*0957b409SSimon J. Gerraty  * Compute key block.
1340*0957b409SSimon J. Gerraty  */
1341*0957b409SSimon J. Gerraty static void
1342*0957b409SSimon J. Gerraty compute_key_block(br_ssl_engine_context *cc, int prf_id,
1343*0957b409SSimon J. Gerraty 	size_t half_len, unsigned char *kb)
1344*0957b409SSimon J. Gerraty {
1345*0957b409SSimon J. Gerraty 	br_tls_prf_impl iprf;
1346*0957b409SSimon J. Gerraty 	br_tls_prf_seed_chunk seed[2] = {
1347*0957b409SSimon J. Gerraty 		{ cc->server_random, sizeof cc->server_random },
1348*0957b409SSimon J. Gerraty 		{ cc->client_random, sizeof cc->client_random }
1349*0957b409SSimon J. Gerraty 	};
1350*0957b409SSimon J. Gerraty 
1351*0957b409SSimon J. Gerraty 	iprf = br_ssl_engine_get_PRF(cc, prf_id);
1352*0957b409SSimon J. Gerraty 	iprf(kb, half_len << 1,
1353*0957b409SSimon J. Gerraty 		cc->session.master_secret, sizeof cc->session.master_secret,
1354*0957b409SSimon J. Gerraty 		"key expansion", 2, seed);
1355*0957b409SSimon J. Gerraty }
1356*0957b409SSimon J. Gerraty 
1357*0957b409SSimon J. Gerraty /* see inner.h */
1358*0957b409SSimon J. Gerraty void
1359*0957b409SSimon J. Gerraty br_ssl_engine_switch_cbc_in(br_ssl_engine_context *cc,
1360*0957b409SSimon J. Gerraty 	int is_client, int prf_id, int mac_id,
1361*0957b409SSimon J. Gerraty 	const br_block_cbcdec_class *bc_impl, size_t cipher_key_len)
1362*0957b409SSimon J. Gerraty {
1363*0957b409SSimon J. Gerraty 	unsigned char kb[192];
1364*0957b409SSimon J. Gerraty 	unsigned char *cipher_key, *mac_key, *iv;
1365*0957b409SSimon J. Gerraty 	const br_hash_class *imh;
1366*0957b409SSimon J. Gerraty 	size_t mac_key_len, mac_out_len, iv_len;
1367*0957b409SSimon J. Gerraty 
1368*0957b409SSimon J. Gerraty 	imh = br_ssl_engine_get_hash(cc, mac_id);
1369*0957b409SSimon J. Gerraty 	mac_out_len = (imh->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK;
1370*0957b409SSimon J. Gerraty 	mac_key_len = mac_out_len;
1371*0957b409SSimon J. Gerraty 
1372*0957b409SSimon J. Gerraty 	/*
1373*0957b409SSimon J. Gerraty 	 * TLS 1.1+ uses per-record explicit IV, so no IV to generate here.
1374*0957b409SSimon J. Gerraty 	 */
1375*0957b409SSimon J. Gerraty 	if (cc->session.version >= BR_TLS11) {
1376*0957b409SSimon J. Gerraty 		iv_len = 0;
1377*0957b409SSimon J. Gerraty 	} else {
1378*0957b409SSimon J. Gerraty 		iv_len = bc_impl->block_size;
1379*0957b409SSimon J. Gerraty 	}
1380*0957b409SSimon J. Gerraty 	compute_key_block(cc, prf_id,
1381*0957b409SSimon J. Gerraty 		mac_key_len + cipher_key_len + iv_len, kb);
1382*0957b409SSimon J. Gerraty 	if (is_client) {
1383*0957b409SSimon J. Gerraty 		mac_key = &kb[mac_key_len];
1384*0957b409SSimon J. Gerraty 		cipher_key = &kb[(mac_key_len << 1) + cipher_key_len];
1385*0957b409SSimon J. Gerraty 		iv = &kb[((mac_key_len + cipher_key_len) << 1) + iv_len];
1386*0957b409SSimon J. Gerraty 	} else {
1387*0957b409SSimon J. Gerraty 		mac_key = &kb[0];
1388*0957b409SSimon J. Gerraty 		cipher_key = &kb[mac_key_len << 1];
1389*0957b409SSimon J. Gerraty 		iv = &kb[(mac_key_len + cipher_key_len) << 1];
1390*0957b409SSimon J. Gerraty 	}
1391*0957b409SSimon J. Gerraty 	if (iv_len == 0) {
1392*0957b409SSimon J. Gerraty 		iv = NULL;
1393*0957b409SSimon J. Gerraty 	}
1394*0957b409SSimon J. Gerraty 	cc->icbc_in->init(&cc->in.cbc.vtable,
1395*0957b409SSimon J. Gerraty 		bc_impl, cipher_key, cipher_key_len,
1396*0957b409SSimon J. Gerraty 		imh, mac_key, mac_key_len, mac_out_len, iv);
1397*0957b409SSimon J. Gerraty 	cc->incrypt = 1;
1398*0957b409SSimon J. Gerraty }
1399*0957b409SSimon J. Gerraty 
1400*0957b409SSimon J. Gerraty /* see inner.h */
1401*0957b409SSimon J. Gerraty void
1402*0957b409SSimon J. Gerraty br_ssl_engine_switch_cbc_out(br_ssl_engine_context *cc,
1403*0957b409SSimon J. Gerraty 	int is_client, int prf_id, int mac_id,
1404*0957b409SSimon J. Gerraty 	const br_block_cbcenc_class *bc_impl, size_t cipher_key_len)
1405*0957b409SSimon J. Gerraty {
1406*0957b409SSimon J. Gerraty 	unsigned char kb[192];
1407*0957b409SSimon J. Gerraty 	unsigned char *cipher_key, *mac_key, *iv;
1408*0957b409SSimon J. Gerraty 	const br_hash_class *imh;
1409*0957b409SSimon J. Gerraty 	size_t mac_key_len, mac_out_len, iv_len;
1410*0957b409SSimon J. Gerraty 
1411*0957b409SSimon J. Gerraty 	imh = br_ssl_engine_get_hash(cc, mac_id);
1412*0957b409SSimon J. Gerraty 	mac_out_len = (imh->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK;
1413*0957b409SSimon J. Gerraty 	mac_key_len = mac_out_len;
1414*0957b409SSimon J. Gerraty 
1415*0957b409SSimon J. Gerraty 	/*
1416*0957b409SSimon J. Gerraty 	 * TLS 1.1+ uses per-record explicit IV, so no IV to generate here.
1417*0957b409SSimon J. Gerraty 	 */
1418*0957b409SSimon J. Gerraty 	if (cc->session.version >= BR_TLS11) {
1419*0957b409SSimon J. Gerraty 		iv_len = 0;
1420*0957b409SSimon J. Gerraty 	} else {
1421*0957b409SSimon J. Gerraty 		iv_len = bc_impl->block_size;
1422*0957b409SSimon J. Gerraty 	}
1423*0957b409SSimon J. Gerraty 	compute_key_block(cc, prf_id,
1424*0957b409SSimon J. Gerraty 		mac_key_len + cipher_key_len + iv_len, kb);
1425*0957b409SSimon J. Gerraty 	if (is_client) {
1426*0957b409SSimon J. Gerraty 		mac_key = &kb[0];
1427*0957b409SSimon J. Gerraty 		cipher_key = &kb[mac_key_len << 1];
1428*0957b409SSimon J. Gerraty 		iv = &kb[(mac_key_len + cipher_key_len) << 1];
1429*0957b409SSimon J. Gerraty 	} else {
1430*0957b409SSimon J. Gerraty 		mac_key = &kb[mac_key_len];
1431*0957b409SSimon J. Gerraty 		cipher_key = &kb[(mac_key_len << 1) + cipher_key_len];
1432*0957b409SSimon J. Gerraty 		iv = &kb[((mac_key_len + cipher_key_len) << 1) + iv_len];
1433*0957b409SSimon J. Gerraty 	}
1434*0957b409SSimon J. Gerraty 	if (iv_len == 0) {
1435*0957b409SSimon J. Gerraty 		iv = NULL;
1436*0957b409SSimon J. Gerraty 	}
1437*0957b409SSimon J. Gerraty 	cc->icbc_out->init(&cc->out.cbc.vtable,
1438*0957b409SSimon J. Gerraty 		bc_impl, cipher_key, cipher_key_len,
1439*0957b409SSimon J. Gerraty 		imh, mac_key, mac_key_len, mac_out_len, iv);
1440*0957b409SSimon J. Gerraty }
1441*0957b409SSimon J. Gerraty 
1442*0957b409SSimon J. Gerraty /* see inner.h */
1443*0957b409SSimon J. Gerraty void
1444*0957b409SSimon J. Gerraty br_ssl_engine_switch_gcm_in(br_ssl_engine_context *cc,
1445*0957b409SSimon J. Gerraty 	int is_client, int prf_id,
1446*0957b409SSimon J. Gerraty 	const br_block_ctr_class *bc_impl, size_t cipher_key_len)
1447*0957b409SSimon J. Gerraty {
1448*0957b409SSimon J. Gerraty 	unsigned char kb[72];
1449*0957b409SSimon J. Gerraty 	unsigned char *cipher_key, *iv;
1450*0957b409SSimon J. Gerraty 
1451*0957b409SSimon J. Gerraty 	compute_key_block(cc, prf_id, cipher_key_len + 4, kb);
1452*0957b409SSimon J. Gerraty 	if (is_client) {
1453*0957b409SSimon J. Gerraty 		cipher_key = &kb[cipher_key_len];
1454*0957b409SSimon J. Gerraty 		iv = &kb[(cipher_key_len << 1) + 4];
1455*0957b409SSimon J. Gerraty 	} else {
1456*0957b409SSimon J. Gerraty 		cipher_key = &kb[0];
1457*0957b409SSimon J. Gerraty 		iv = &kb[cipher_key_len << 1];
1458*0957b409SSimon J. Gerraty 	}
1459*0957b409SSimon J. Gerraty 	cc->igcm_in->init(&cc->in.gcm.vtable.in,
1460*0957b409SSimon J. Gerraty 		bc_impl, cipher_key, cipher_key_len, cc->ighash, iv);
1461*0957b409SSimon J. Gerraty 	cc->incrypt = 1;
1462*0957b409SSimon J. Gerraty }
1463*0957b409SSimon J. Gerraty 
1464*0957b409SSimon J. Gerraty /* see inner.h */
1465*0957b409SSimon J. Gerraty void
1466*0957b409SSimon J. Gerraty br_ssl_engine_switch_gcm_out(br_ssl_engine_context *cc,
1467*0957b409SSimon J. Gerraty 	int is_client, int prf_id,
1468*0957b409SSimon J. Gerraty 	const br_block_ctr_class *bc_impl, size_t cipher_key_len)
1469*0957b409SSimon J. Gerraty {
1470*0957b409SSimon J. Gerraty 	unsigned char kb[72];
1471*0957b409SSimon J. Gerraty 	unsigned char *cipher_key, *iv;
1472*0957b409SSimon J. Gerraty 
1473*0957b409SSimon J. Gerraty 	compute_key_block(cc, prf_id, cipher_key_len + 4, kb);
1474*0957b409SSimon J. Gerraty 	if (is_client) {
1475*0957b409SSimon J. Gerraty 		cipher_key = &kb[0];
1476*0957b409SSimon J. Gerraty 		iv = &kb[cipher_key_len << 1];
1477*0957b409SSimon J. Gerraty 	} else {
1478*0957b409SSimon J. Gerraty 		cipher_key = &kb[cipher_key_len];
1479*0957b409SSimon J. Gerraty 		iv = &kb[(cipher_key_len << 1) + 4];
1480*0957b409SSimon J. Gerraty 	}
1481*0957b409SSimon J. Gerraty 	cc->igcm_out->init(&cc->out.gcm.vtable.out,
1482*0957b409SSimon J. Gerraty 		bc_impl, cipher_key, cipher_key_len, cc->ighash, iv);
1483*0957b409SSimon J. Gerraty }
1484*0957b409SSimon J. Gerraty 
1485*0957b409SSimon J. Gerraty /* see inner.h */
1486*0957b409SSimon J. Gerraty void
1487*0957b409SSimon J. Gerraty br_ssl_engine_switch_chapol_in(br_ssl_engine_context *cc,
1488*0957b409SSimon J. Gerraty 	int is_client, int prf_id)
1489*0957b409SSimon J. Gerraty {
1490*0957b409SSimon J. Gerraty 	unsigned char kb[88];
1491*0957b409SSimon J. Gerraty 	unsigned char *cipher_key, *iv;
1492*0957b409SSimon J. Gerraty 
1493*0957b409SSimon J. Gerraty 	compute_key_block(cc, prf_id, 44, kb);
1494*0957b409SSimon J. Gerraty 	if (is_client) {
1495*0957b409SSimon J. Gerraty 		cipher_key = &kb[32];
1496*0957b409SSimon J. Gerraty 		iv = &kb[76];
1497*0957b409SSimon J. Gerraty 	} else {
1498*0957b409SSimon J. Gerraty 		cipher_key = &kb[0];
1499*0957b409SSimon J. Gerraty 		iv = &kb[64];
1500*0957b409SSimon J. Gerraty 	}
1501*0957b409SSimon J. Gerraty 	cc->ichapol_in->init(&cc->in.chapol.vtable.in,
1502*0957b409SSimon J. Gerraty 		cc->ichacha, cc->ipoly, cipher_key, iv);
1503*0957b409SSimon J. Gerraty 	cc->incrypt = 1;
1504*0957b409SSimon J. Gerraty }
1505*0957b409SSimon J. Gerraty 
1506*0957b409SSimon J. Gerraty /* see inner.h */
1507*0957b409SSimon J. Gerraty void
1508*0957b409SSimon J. Gerraty br_ssl_engine_switch_chapol_out(br_ssl_engine_context *cc,
1509*0957b409SSimon J. Gerraty 	int is_client, int prf_id)
1510*0957b409SSimon J. Gerraty {
1511*0957b409SSimon J. Gerraty 	unsigned char kb[88];
1512*0957b409SSimon J. Gerraty 	unsigned char *cipher_key, *iv;
1513*0957b409SSimon J. Gerraty 
1514*0957b409SSimon J. Gerraty 	compute_key_block(cc, prf_id, 44, kb);
1515*0957b409SSimon J. Gerraty 	if (is_client) {
1516*0957b409SSimon J. Gerraty 		cipher_key = &kb[0];
1517*0957b409SSimon J. Gerraty 		iv = &kb[64];
1518*0957b409SSimon J. Gerraty 	} else {
1519*0957b409SSimon J. Gerraty 		cipher_key = &kb[32];
1520*0957b409SSimon J. Gerraty 		iv = &kb[76];
1521*0957b409SSimon J. Gerraty 	}
1522*0957b409SSimon J. Gerraty 	cc->ichapol_out->init(&cc->out.chapol.vtable.out,
1523*0957b409SSimon J. Gerraty 		cc->ichacha, cc->ipoly, cipher_key, iv);
1524*0957b409SSimon J. Gerraty }
1525*0957b409SSimon J. Gerraty 
1526*0957b409SSimon J. Gerraty /* see inner.h */
1527*0957b409SSimon J. Gerraty void
1528*0957b409SSimon J. Gerraty br_ssl_engine_switch_ccm_in(br_ssl_engine_context *cc,
1529*0957b409SSimon J. Gerraty 	int is_client, int prf_id,
1530*0957b409SSimon J. Gerraty 	const br_block_ctrcbc_class *bc_impl,
1531*0957b409SSimon J. Gerraty 	size_t cipher_key_len, size_t tag_len)
1532*0957b409SSimon J. Gerraty {
1533*0957b409SSimon J. Gerraty 	unsigned char kb[72];
1534*0957b409SSimon J. Gerraty 	unsigned char *cipher_key, *iv;
1535*0957b409SSimon J. Gerraty 
1536*0957b409SSimon J. Gerraty 	compute_key_block(cc, prf_id, cipher_key_len + 4, kb);
1537*0957b409SSimon J. Gerraty 	if (is_client) {
1538*0957b409SSimon J. Gerraty 		cipher_key = &kb[cipher_key_len];
1539*0957b409SSimon J. Gerraty 		iv = &kb[(cipher_key_len << 1) + 4];
1540*0957b409SSimon J. Gerraty 	} else {
1541*0957b409SSimon J. Gerraty 		cipher_key = &kb[0];
1542*0957b409SSimon J. Gerraty 		iv = &kb[cipher_key_len << 1];
1543*0957b409SSimon J. Gerraty 	}
1544*0957b409SSimon J. Gerraty 	cc->iccm_in->init(&cc->in.ccm.vtable.in,
1545*0957b409SSimon J. Gerraty 		bc_impl, cipher_key, cipher_key_len, iv, tag_len);
1546*0957b409SSimon J. Gerraty 	cc->incrypt = 1;
1547*0957b409SSimon J. Gerraty }
1548*0957b409SSimon J. Gerraty 
1549*0957b409SSimon J. Gerraty /* see inner.h */
1550*0957b409SSimon J. Gerraty void
1551*0957b409SSimon J. Gerraty br_ssl_engine_switch_ccm_out(br_ssl_engine_context *cc,
1552*0957b409SSimon J. Gerraty 	int is_client, int prf_id,
1553*0957b409SSimon J. Gerraty 	const br_block_ctrcbc_class *bc_impl,
1554*0957b409SSimon J. Gerraty 	size_t cipher_key_len, size_t tag_len)
1555*0957b409SSimon J. Gerraty {
1556*0957b409SSimon J. Gerraty 	unsigned char kb[72];
1557*0957b409SSimon J. Gerraty 	unsigned char *cipher_key, *iv;
1558*0957b409SSimon J. Gerraty 
1559*0957b409SSimon J. Gerraty 	compute_key_block(cc, prf_id, cipher_key_len + 4, kb);
1560*0957b409SSimon J. Gerraty 	if (is_client) {
1561*0957b409SSimon J. Gerraty 		cipher_key = &kb[0];
1562*0957b409SSimon J. Gerraty 		iv = &kb[cipher_key_len << 1];
1563*0957b409SSimon J. Gerraty 	} else {
1564*0957b409SSimon J. Gerraty 		cipher_key = &kb[cipher_key_len];
1565*0957b409SSimon J. Gerraty 		iv = &kb[(cipher_key_len << 1) + 4];
1566*0957b409SSimon J. Gerraty 	}
1567*0957b409SSimon J. Gerraty 	cc->iccm_out->init(&cc->out.ccm.vtable.out,
1568*0957b409SSimon J. Gerraty 		bc_impl, cipher_key, cipher_key_len, iv, tag_len);
1569*0957b409SSimon J. Gerraty }
1570