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