1 /* $OpenBSD: ssl_packet.c,v 1.8 2018/11/08 22:28:52 jsing Exp $ */ 2 /* 3 * Copyright (c) 2016, 2017 Joel Sing <jsing@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include "ssl_locl.h" 19 20 #include "bytestring.h" 21 22 static int 23 ssl_is_sslv2_client_hello(CBS *header) 24 { 25 uint16_t record_length; 26 uint8_t message_type; 27 CBS cbs; 28 29 CBS_dup(header, &cbs); 30 31 if (!CBS_get_u16(&cbs, &record_length) || 32 !CBS_get_u8(&cbs, &message_type)) 33 return 0; 34 35 /* 36 * The SSLv2 record length field uses variable length (2 or 3 byte) 37 * encoding. Given the size of a client hello, we expect/require the 38 * 2-byte form which is indicated by a one in the most significant bit. 39 */ 40 if ((record_length & 0x8000) == 0) 41 return 0; 42 if ((record_length & ~0x8000) < 3) 43 return 0; 44 if (message_type != SSL2_MT_CLIENT_HELLO) 45 return 0; 46 47 return 1; 48 } 49 50 static int 51 ssl_is_sslv3_handshake(CBS *header) 52 { 53 uint16_t record_version; 54 uint8_t record_type; 55 CBS cbs; 56 57 CBS_dup(header, &cbs); 58 59 if (!CBS_get_u8(&cbs, &record_type) || 60 !CBS_get_u16(&cbs, &record_version)) 61 return 0; 62 63 if (record_type != SSL3_RT_HANDSHAKE) 64 return 0; 65 if ((record_version >> 8) != SSL3_VERSION_MAJOR) 66 return 0; 67 68 return 1; 69 } 70 71 static int 72 ssl_convert_sslv2_client_hello(SSL *s) 73 { 74 CBB cbb, handshake, client_hello, cipher_suites, compression, session_id; 75 CBS cbs, challenge, cipher_specs, session; 76 uint16_t record_length, client_version, cipher_specs_length; 77 uint16_t session_id_length, challenge_length; 78 unsigned char *client_random = NULL, *data = NULL; 79 size_t data_len, pad_len, len; 80 uint32_t cipher_spec; 81 uint8_t message_type; 82 unsigned char *pad; 83 int ret = -1; 84 int n; 85 86 memset(&cbb, 0, sizeof(cbb)); 87 88 CBS_init(&cbs, s->internal->packet, SSL3_RT_HEADER_LENGTH); 89 90 if (!CBS_get_u16(&cbs, &record_length) || 91 !CBS_get_u8(&cbs, &message_type) || 92 !CBS_get_u16(&cbs, &client_version)) 93 return -1; 94 95 /* 96 * The SSLv2 record length field uses variable length (2 or 3 byte) 97 * encoding. Given the size of a client hello, we expect/require the 98 * 2-byte form which is indicated by a one in the most significant bit. 99 * Also note that the record length value does not include the bytes 100 * used for the record length field. 101 */ 102 if ((record_length & 0x8000) == 0) 103 return -1; 104 record_length &= ~0x8000; 105 if (record_length < SSL3_RT_HEADER_LENGTH - 2) 106 return -1; 107 if (message_type != SSL2_MT_CLIENT_HELLO) 108 return -1; 109 110 if (record_length < 9) { 111 SSLerror(s, SSL_R_RECORD_LENGTH_MISMATCH); 112 return -1; 113 } 114 if (record_length > 4096) { 115 SSLerror(s, SSL_R_RECORD_TOO_LARGE); 116 return -1; 117 } 118 119 n = ssl3_packet_extend(s, record_length + 2); 120 if (n != record_length + 2) 121 return n; 122 123 tls1_transcript_record(s, s->internal->packet + 2, 124 s->internal->packet_length - 2); 125 s->internal->mac_packet = 0; 126 127 if (s->internal->msg_callback) 128 s->internal->msg_callback(0, SSL2_VERSION, 0, 129 s->internal->packet + 2, s->internal->packet_length - 2, s, 130 s->internal->msg_callback_arg); 131 132 /* Decode the SSLv2 record containing the client hello. */ 133 CBS_init(&cbs, s->internal->packet, s->internal->packet_length); 134 135 if (!CBS_get_u16(&cbs, &record_length)) 136 return -1; 137 if (!CBS_get_u8(&cbs, &message_type)) 138 return -1; 139 if (!CBS_get_u16(&cbs, &client_version)) 140 return -1; 141 if (!CBS_get_u16(&cbs, &cipher_specs_length)) 142 return -1; 143 if (!CBS_get_u16(&cbs, &session_id_length)) 144 return -1; 145 if (!CBS_get_u16(&cbs, &challenge_length)) 146 return -1; 147 if (!CBS_get_bytes(&cbs, &cipher_specs, cipher_specs_length)) 148 return -1; 149 if (!CBS_get_bytes(&cbs, &session, session_id_length)) 150 return -1; 151 if (!CBS_get_bytes(&cbs, &challenge, challenge_length)) 152 return -1; 153 if (CBS_len(&cbs) != 0) { 154 SSLerror(s, SSL_R_RECORD_LENGTH_MISMATCH); 155 return -1; 156 } 157 158 /* 159 * Convert SSLv2 challenge to SSLv3/TLS client random, by truncating or 160 * left-padding with zero bytes. 161 */ 162 if ((client_random = malloc(SSL3_RANDOM_SIZE)) == NULL) 163 goto err; 164 if (!CBB_init_fixed(&cbb, client_random, SSL3_RANDOM_SIZE)) 165 goto err; 166 if ((len = CBS_len(&challenge)) > SSL3_RANDOM_SIZE) 167 len = SSL3_RANDOM_SIZE; 168 pad_len = SSL3_RANDOM_SIZE - len; 169 if (!CBB_add_space(&cbb, &pad, pad_len)) 170 goto err; 171 memset(pad, 0, pad_len); 172 if (!CBB_add_bytes(&cbb, CBS_data(&challenge), len)) 173 goto err; 174 if (!CBB_finish(&cbb, NULL, NULL)) 175 goto err; 176 177 /* Build SSLv3/TLS record with client hello. */ 178 if (!CBB_init(&cbb, SSL3_RT_MAX_PLAIN_LENGTH)) 179 goto err; 180 if (!CBB_add_u8(&cbb, SSL3_RT_HANDSHAKE)) 181 goto err; 182 if (!CBB_add_u16(&cbb, 0x0301)) 183 goto err; 184 if (!CBB_add_u16_length_prefixed(&cbb, &handshake)) 185 goto err; 186 if (!CBB_add_u8(&handshake, SSL3_MT_CLIENT_HELLO)) 187 goto err; 188 if (!CBB_add_u24_length_prefixed(&handshake, &client_hello)) 189 goto err; 190 if (!CBB_add_u16(&client_hello, client_version)) 191 goto err; 192 if (!CBB_add_bytes(&client_hello, client_random, SSL3_RANDOM_SIZE)) 193 goto err; 194 if (!CBB_add_u8_length_prefixed(&client_hello, &session_id)) 195 goto err; 196 if (!CBB_add_u16_length_prefixed(&client_hello, &cipher_suites)) 197 goto err; 198 while (CBS_len(&cipher_specs) > 0) { 199 if (!CBS_get_u24(&cipher_specs, &cipher_spec)) 200 goto err; 201 if ((cipher_spec & 0xff0000) != 0) 202 continue; 203 if (!CBB_add_u16(&cipher_suites, cipher_spec & 0xffff)) 204 goto err; 205 } 206 if (!CBB_add_u8_length_prefixed(&client_hello, &compression)) 207 goto err; 208 if (!CBB_add_u8(&compression, 0)) 209 goto err; 210 if (!CBB_finish(&cbb, &data, &data_len)) 211 goto err; 212 213 if (data_len > S3I(s)->rbuf.len) 214 goto err; 215 216 s->internal->packet = S3I(s)->rbuf.buf; 217 s->internal->packet_length = data_len; 218 memcpy(s->internal->packet, data, data_len); 219 ret = 1; 220 221 err: 222 CBB_cleanup(&cbb); 223 free(client_random); 224 free(data); 225 226 return (ret); 227 } 228 229 /* 230 * Potentially do legacy processing on the first packet received by a TLS 231 * server. We return 1 if we want SSLv3/TLS record processing to continue 232 * normally, otherwise we must set an SSLerr and return -1. 233 */ 234 int 235 ssl_server_legacy_first_packet(SSL *s) 236 { 237 uint16_t min_version; 238 const char *data; 239 CBS header; 240 241 if (SSL_IS_DTLS(s)) 242 return 1; 243 244 CBS_init(&header, s->internal->packet, SSL3_RT_HEADER_LENGTH); 245 246 if (ssl_is_sslv3_handshake(&header) == 1) 247 return 1; 248 249 /* Only continue if this is not a version locked method. */ 250 if (s->method->internal->min_version == s->method->internal->max_version) 251 return 1; 252 253 if (ssl_is_sslv2_client_hello(&header) == 1) { 254 /* Only permit SSLv2 client hellos if TLSv1.0 is enabled. */ 255 if (ssl_enabled_version_range(s, &min_version, NULL) != 1) { 256 SSLerror(s, SSL_R_NO_PROTOCOLS_AVAILABLE); 257 return -1; 258 } 259 if (min_version > TLS1_VERSION) 260 return 1; 261 262 if (ssl_convert_sslv2_client_hello(s) != 1) { 263 SSLerror(s, SSL_R_BAD_PACKET_LENGTH); 264 return -1; 265 } 266 267 return 1; 268 } 269 270 /* Ensure that we have SSL3_RT_HEADER_LENGTH (5 bytes) of the packet. */ 271 if (CBS_len(&header) != SSL3_RT_HEADER_LENGTH) { 272 SSLerror(s, ERR_R_INTERNAL_ERROR); 273 return -1; 274 } 275 data = (const char *)CBS_data(&header); 276 277 /* Is this a cleartext protocol? */ 278 if (strncmp("GET ", data, 4) == 0 || 279 strncmp("POST ", data, 5) == 0 || 280 strncmp("HEAD ", data, 5) == 0 || 281 strncmp("PUT ", data, 4) == 0) { 282 SSLerror(s, SSL_R_HTTP_REQUEST); 283 return -1; 284 } 285 if (strncmp("CONNE", data, 5) == 0) { 286 SSLerror(s, SSL_R_HTTPS_PROXY_REQUEST); 287 return -1; 288 } 289 290 SSLerror(s, SSL_R_UNKNOWN_PROTOCOL); 291 292 return -1; 293 } 294