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