1 /* 2 * Copyright (c) 2015 Joel Sing <jsing@openbsd.org> 3 * 4 * Permission to use, copy, modify, and distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #include <openssl/ssl.h> 18 19 #include <openssl/dtls1.h> 20 #include <openssl/ssl3.h> 21 22 #include <err.h> 23 #include <stdio.h> 24 #include <string.h> 25 26 #define DTLS_HM_OFFSET (DTLS1_RT_HEADER_LENGTH + DTLS1_HM_HEADER_LENGTH) 27 #define DTLS_RANDOM_OFFSET (DTLS_HM_OFFSET + 2) 28 #define DTLS_CIPHER_OFFSET (DTLS_HM_OFFSET + 38) 29 30 #define SSL3_HM_OFFSET (SSL3_RT_HEADER_LENGTH + SSL3_HM_HEADER_LENGTH) 31 #define SSL3_RANDOM_OFFSET (SSL3_HM_OFFSET + 2) 32 #define SSL3_CIPHER_OFFSET (SSL3_HM_OFFSET + 37) 33 34 static unsigned char cipher_list_dtls1[] = { 35 0xc0, 0x14, 0xc0, 0x0a, 0x00, 0x39, 0xff, 0x85, 36 0x00, 0x88, 0x00, 0x81, 0x00, 0x35, 0x00, 0x84, 37 0xc0, 0x13, 0xc0, 0x09, 0x00, 0x33, 0x00, 0x45, 38 0x00, 0x2f, 0x00, 0x41, 0xc0, 0x12, 0xc0, 0x08, 39 0x00, 0x16, 0x00, 0x0a, 0x00, 0xff, 40 }; 41 42 static unsigned char client_hello_dtls1[] = { 43 0x16, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 44 0x00, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 45 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 46 0x54, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 47 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 48 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 49 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 50 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0xc0, 51 0x14, 0xc0, 0x0a, 0x00, 0x39, 0xff, 0x85, 0x00, 52 0x88, 0x00, 0x81, 0x00, 0x35, 0x00, 0x84, 0xc0, 53 0x13, 0xc0, 0x09, 0x00, 0x33, 0x00, 0x45, 0x00, 54 0x2f, 0x00, 0x41, 0xc0, 0x12, 0xc0, 0x08, 0x00, 55 0x16, 0x00, 0x0a, 0x00, 0xff, 0x01, 0x00, 0x00, 56 0x04, 0x00, 0x23, 0x00, 0x00, 57 }; 58 59 static unsigned char cipher_list_tls10[] = { 60 0xc0, 0x14, 0xc0, 0x0a, 0x00, 0x39, 0xff, 0x85, 61 0x00, 0x88, 0x00, 0x81, 0x00, 0x35, 0x00, 0x84, 62 0xc0, 0x13, 0xc0, 0x09, 0x00, 0x33, 0x00, 0x45, 63 0x00, 0x2f, 0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07, 64 0x00, 0x05, 0x00, 0x04, 0xc0, 0x12, 0xc0, 0x08, 65 0x00, 0x16, 0x00, 0x0a, 0x00, 0xff, 66 }; 67 68 static unsigned char client_hello_tls10[] = { 69 0x16, 0x03, 0x01, 0x00, 0x71, 0x01, 0x00, 0x00, 70 0x6d, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 71 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 72 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 73 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 74 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0xc0, 0x14, 75 0xc0, 0x0a, 0x00, 0x39, 0xff, 0x85, 0x00, 0x88, 76 0x00, 0x81, 0x00, 0x35, 0x00, 0x84, 0xc0, 0x13, 77 0xc0, 0x09, 0x00, 0x33, 0x00, 0x45, 0x00, 0x2f, 78 0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07, 0x00, 0x05, 79 0x00, 0x04, 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, 80 0x00, 0x0a, 0x00, 0xff, 0x01, 0x00, 0x00, 0x16, 81 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x0a, 82 0x00, 0x08, 0x00, 0x06, 0x00, 0x1d, 0x00, 0x17, 83 0x00, 0x18, 0x00, 0x23, 0x00, 0x00, 84 }; 85 86 static unsigned char cipher_list_tls11[] = { 87 0xc0, 0x14, 0xc0, 0x0a, 0x00, 0x39, 0xff, 0x85, 88 0x00, 0x88, 0x00, 0x81, 0x00, 0x35, 0x00, 0x84, 89 0xc0, 0x13, 0xc0, 0x09, 0x00, 0x33, 0x00, 0x45, 90 0x00, 0x2f, 0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07, 91 0x00, 0x05, 0x00, 0x04, 0xc0, 0x12, 0xc0, 0x08, 92 0x00, 0x16, 0x00, 0x0a, 0x00, 0xff, 93 }; 94 95 static unsigned char client_hello_tls11[] = { 96 0x16, 0x03, 0x01, 0x00, 0x71, 0x01, 0x00, 0x00, 97 0x6d, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 98 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 99 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 100 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 101 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0xc0, 0x14, 102 0xc0, 0x0a, 0x00, 0x39, 0xff, 0x85, 0x00, 0x88, 103 0x00, 0x81, 0x00, 0x35, 0x00, 0x84, 0xc0, 0x13, 104 0xc0, 0x09, 0x00, 0x33, 0x00, 0x45, 0x00, 0x2f, 105 0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07, 0x00, 0x05, 106 0x00, 0x04, 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, 107 0x00, 0x0a, 0x00, 0xff, 0x01, 0x00, 0x00, 0x16, 108 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x0a, 109 0x00, 0x08, 0x00, 0x06, 0x00, 0x1d, 0x00, 0x17, 110 0x00, 0x18, 0x00, 0x23, 0x00, 0x00, 111 }; 112 113 static unsigned char cipher_list_tls12_aes[] = { 114 0xc0, 0x30, 0xc0, 0x2c, 0xc0, 0x28, 0xc0, 0x24, 115 0xc0, 0x14, 0xc0, 0x0a, 0x00, 0x9f, 0x00, 0x6b, 116 0x00, 0x39, 0xcc, 0xa9, 0xcc, 0xa8, 0xcc, 0xaa, 117 0xff, 0x85, 0x00, 0xc4, 0x00, 0x88, 0x00, 0x81, 118 0x00, 0x9d, 0x00, 0x3d, 0x00, 0x35, 0x00, 0xc0, 119 0x00, 0x84, 0xc0, 0x2f, 0xc0, 0x2b, 0xc0, 0x27, 120 0xc0, 0x23, 0xc0, 0x13, 0xc0, 0x09, 0x00, 0x9e, 121 0x00, 0x67, 0x00, 0x33, 0x00, 0xbe, 0x00, 0x45, 122 0x00, 0x9c, 0x00, 0x3c, 0x00, 0x2f, 0x00, 0xba, 123 0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07, 0x00, 0x05, 124 0x00, 0x04, 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, 125 0x00, 0x0a, 0x00, 0xff, 126 }; 127 128 static unsigned char cipher_list_tls12_chacha[] = { 129 0xcc, 0xa9, 0xcc, 0xa8, 0xcc, 0xaa, 0xc0, 0x30, 130 0xc0, 0x2c, 0xc0, 0x28, 0xc0, 0x24, 0xc0, 0x14, 131 0xc0, 0x0a, 0x00, 0x9f, 0x00, 0x6b, 0x00, 0x39, 132 0xff, 0x85, 0x00, 0xc4, 0x00, 0x88, 0x00, 0x81, 133 0x00, 0x9d, 0x00, 0x3d, 0x00, 0x35, 0x00, 0xc0, 134 0x00, 0x84, 0xc0, 0x2f, 0xc0, 0x2b, 0xc0, 0x27, 135 0xc0, 0x23, 0xc0, 0x13, 0xc0, 0x09, 0x00, 0x9e, 136 0x00, 0x67, 0x00, 0x33, 0x00, 0xbe, 0x00, 0x45, 137 0x00, 0x9c, 0x00, 0x3c, 0x00, 0x2f, 0x00, 0xba, 138 0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07, 0x00, 0x05, 139 0x00, 0x04, 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, 140 0x00, 0x0a, 0x00, 0xff, 141 }; 142 143 static unsigned char client_hello_tls12[] = { 144 0x16, 0x03, 0x01, 0x00, 0xbf, 0x01, 0x00, 0x00, 145 0xbb, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 146 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 147 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 148 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 149 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0xcc, 0xa9, 150 0xcc, 0xa8, 0xcc, 0xaa, 0xc0, 0x30, 0xc0, 0x2c, 151 0xc0, 0x28, 0xc0, 0x24, 0xc0, 0x14, 0xc0, 0x0a, 152 0x00, 0x9f, 0x00, 0x6b, 0x00, 0x39, 0xff, 0x85, 153 0x00, 0xc4, 0x00, 0x88, 0x00, 0x81, 0x00, 0x9d, 154 0x00, 0x3d, 0x00, 0x35, 0x00, 0xc0, 0x00, 0x84, 155 0xc0, 0x2f, 0xc0, 0x2b, 0xc0, 0x27, 0xc0, 0x23, 156 0xc0, 0x13, 0xc0, 0x09, 0x00, 0x9e, 0x00, 0x67, 157 0x00, 0x33, 0x00, 0xbe, 0x00, 0x45, 0x00, 0x9c, 158 0x00, 0x3c, 0x00, 0x2f, 0x00, 0xba, 0x00, 0x41, 159 0xc0, 0x11, 0xc0, 0x07, 0x00, 0x05, 0x00, 0x04, 160 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, 0x00, 0x0a, 161 0x00, 0xff, 0x01, 0x00, 0x00, 0x36, 0x00, 0x0b, 162 0x00, 0x02, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x08, 163 0x00, 0x06, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18, 164 0x00, 0x23, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x1c, 165 0x00, 0x1a, 0x06, 0x01, 0x06, 0x03, 0xef, 0xef, 166 0x05, 0x01, 0x05, 0x03, 0x04, 0x01, 0x04, 0x03, 167 0xee, 0xee, 0xed, 0xed, 0x03, 0x01, 0x03, 0x03, 168 0x02, 0x01, 0x02, 0x03, 169 }; 170 171 struct client_hello_test { 172 const unsigned char *desc; 173 const int protocol; 174 const size_t random_start; 175 const SSL_METHOD *(*ssl_method)(void); 176 const long ssl_options; 177 }; 178 179 static struct client_hello_test client_hello_tests[] = { 180 { 181 .desc = "DTLSv1 client", 182 .protocol = DTLS1_VERSION, 183 .random_start = DTLS_RANDOM_OFFSET, 184 .ssl_method = DTLSv1_client_method, 185 }, 186 { 187 .desc = "TLSv1 client", 188 .protocol = TLS1_VERSION, 189 .random_start = SSL3_RANDOM_OFFSET, 190 .ssl_method = TLSv1_client_method, 191 }, 192 { 193 .desc = "TLSv1_1 client", 194 .protocol = TLS1_1_VERSION, 195 .random_start = SSL3_RANDOM_OFFSET, 196 .ssl_method = TLSv1_1_client_method, 197 }, 198 { 199 .desc = "TLSv1_2 client", 200 .protocol = TLS1_2_VERSION, 201 .random_start = SSL3_RANDOM_OFFSET, 202 .ssl_method = TLSv1_2_client_method, 203 }, 204 { 205 .desc = "SSLv23 default", 206 .protocol = TLS1_2_VERSION, 207 .random_start = SSL3_RANDOM_OFFSET, 208 .ssl_method = SSLv23_client_method, 209 .ssl_options = 0, 210 }, 211 { 212 .desc = "SSLv23 (no TLSv1.2)", 213 .protocol = TLS1_1_VERSION, 214 .random_start = SSL3_RANDOM_OFFSET, 215 .ssl_method = SSLv23_client_method, 216 .ssl_options = SSL_OP_NO_TLSv1_2, 217 }, 218 { 219 .desc = "SSLv23 (no TLSv1.1)", 220 .protocol = TLS1_VERSION, 221 .random_start = SSL3_RANDOM_OFFSET, 222 .ssl_method = SSLv23_client_method, 223 .ssl_options = SSL_OP_NO_TLSv1_1, 224 }, 225 { 226 .desc = "TLS default", 227 .protocol = TLS1_2_VERSION, 228 .random_start = SSL3_RANDOM_OFFSET, 229 .ssl_method = TLS_client_method, 230 .ssl_options = 0, 231 }, 232 { 233 .desc = "TLS (no TLSv1.2)", 234 .protocol = TLS1_1_VERSION, 235 .random_start = SSL3_RANDOM_OFFSET, 236 .ssl_method = TLS_client_method, 237 .ssl_options = SSL_OP_NO_TLSv1_2, 238 }, 239 { 240 .desc = "TLS (no TLSv1.1)", 241 .protocol = TLS1_VERSION, 242 .random_start = SSL3_RANDOM_OFFSET, 243 .ssl_method = TLS_client_method, 244 .ssl_options = SSL_OP_NO_TLSv1_1, 245 }, 246 { 247 .desc = "TLS (no TLSv1.0, no TLSv1.1)", 248 .protocol = TLS1_2_VERSION, 249 .random_start = SSL3_RANDOM_OFFSET, 250 .ssl_method = TLS_client_method, 251 .ssl_options = SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1, 252 }, 253 }; 254 255 #define N_CLIENT_HELLO_TESTS \ 256 (sizeof(client_hello_tests) / sizeof(*client_hello_tests)) 257 258 static void 259 hexdump(const unsigned char *buf, size_t len) 260 { 261 size_t i; 262 263 for (i = 1; i <= len; i++) 264 fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n"); 265 266 fprintf(stderr, "\n"); 267 } 268 269 static inline int 270 ssl_aes_is_accelerated(void) 271 { 272 #if defined(__i386__) || defined(__x86_64__) 273 return ((OPENSSL_cpu_caps() & (1ULL << 57)) != 0); 274 #else 275 return (0); 276 #endif 277 } 278 279 static int 280 make_client_hello(int protocol, char **out, size_t *outlen) 281 { 282 size_t client_hello_len, cipher_list_len, cipher_list_offset; 283 const char *client_hello, *cipher_list; 284 char *p; 285 286 *out = NULL; 287 *outlen = 0; 288 289 switch (protocol) { 290 case DTLS1_VERSION: 291 client_hello = client_hello_dtls1; 292 client_hello_len = sizeof(client_hello_dtls1); 293 cipher_list = cipher_list_dtls1; 294 cipher_list_len = sizeof(cipher_list_dtls1); 295 cipher_list_offset = DTLS_CIPHER_OFFSET; 296 break; 297 298 case TLS1_VERSION: 299 client_hello = client_hello_tls10; 300 client_hello_len = sizeof(client_hello_tls10); 301 cipher_list = cipher_list_tls10; 302 cipher_list_len = sizeof(cipher_list_tls10); 303 cipher_list_offset = SSL3_CIPHER_OFFSET; 304 break; 305 306 case TLS1_1_VERSION: 307 client_hello = client_hello_tls11; 308 client_hello_len = sizeof(client_hello_tls11); 309 cipher_list = cipher_list_tls11; 310 cipher_list_len = sizeof(cipher_list_tls11); 311 cipher_list_offset = SSL3_CIPHER_OFFSET; 312 break; 313 314 case TLS1_2_VERSION: 315 client_hello = client_hello_tls12; 316 client_hello_len = sizeof(client_hello_tls12); 317 if (ssl_aes_is_accelerated() == 1) 318 cipher_list = cipher_list_tls12_aes; 319 else 320 cipher_list = cipher_list_tls12_chacha; 321 cipher_list_len = sizeof(cipher_list_tls12_chacha); 322 cipher_list_offset = SSL3_CIPHER_OFFSET; 323 break; 324 325 default: 326 return (-1); 327 } 328 329 if ((p = malloc(client_hello_len)) == NULL) 330 return (-1); 331 332 memcpy(p, client_hello, client_hello_len); 333 memcpy(p + cipher_list_offset, cipher_list, cipher_list_len); 334 335 *out = p; 336 *outlen = client_hello_len; 337 338 return (0); 339 } 340 341 static int 342 client_hello_test(int testno, struct client_hello_test *cht) 343 { 344 BIO *rbio = NULL, *wbio = NULL; 345 SSL_CTX *ssl_ctx = NULL; 346 SSL *ssl = NULL; 347 char *client_hello = NULL; 348 size_t client_hello_len; 349 char *wbuf, rbuf[1]; 350 int ret = 1; 351 size_t i; 352 long len; 353 354 fprintf(stderr, "Test %i - %s\n", testno, cht->desc); 355 356 /* Providing a small buf causes *_get_server_hello() to return. */ 357 if ((rbio = BIO_new_mem_buf(rbuf, sizeof(rbuf))) == NULL) { 358 fprintf(stderr, "Failed to setup rbio\n"); 359 goto failure; 360 } 361 if ((wbio = BIO_new(BIO_s_mem())) == NULL) { 362 fprintf(stderr, "Failed to setup wbio\n"); 363 goto failure; 364 } 365 366 if ((ssl_ctx = SSL_CTX_new(cht->ssl_method())) == NULL) { 367 fprintf(stderr, "SSL_CTX_new() returned NULL\n"); 368 goto failure; 369 } 370 371 SSL_CTX_set_options(ssl_ctx, cht->ssl_options); 372 373 if ((ssl = SSL_new(ssl_ctx)) == NULL) { 374 fprintf(stderr, "SSL_new() returned NULL\n"); 375 goto failure; 376 } 377 378 rbio->references = 2; 379 wbio->references = 2; 380 381 SSL_set_bio(ssl, rbio, wbio); 382 383 if (SSL_connect(ssl) != 0) { 384 fprintf(stderr, "SSL_connect() returned non-zero\n"); 385 goto failure; 386 } 387 388 len = BIO_get_mem_data(wbio, &wbuf); 389 390 if (make_client_hello(cht->protocol, &client_hello, 391 &client_hello_len) != 0) 392 goto failure; 393 394 if ((size_t)len != client_hello_len) { 395 fprintf(stderr, "FAIL: test returned ClientHello length %li, " 396 "want %zu\n", len, client_hello_len); 397 fprintf(stderr, "received:\n"); 398 hexdump(wbuf, len); 399 goto failure; 400 } 401 402 /* We expect the client random to differ. */ 403 i = cht->random_start + SSL3_RANDOM_SIZE; 404 if (memcmp(client_hello, wbuf, cht->random_start) != 0 || 405 memcmp(&client_hello[cht->random_start], 406 &wbuf[cht->random_start], SSL3_RANDOM_SIZE) == 0 || 407 memcmp(&client_hello[i], &wbuf[i], len - i) != 0) { 408 fprintf(stderr, "FAIL: ClientHello differs:\n"); 409 fprintf(stderr, "received:\n"); 410 memset(&wbuf[cht->random_start], 0, SSL3_RANDOM_SIZE); 411 hexdump(wbuf, len); 412 fprintf(stderr, "test data:\n"); 413 hexdump(client_hello, client_hello_len); 414 fprintf(stderr, "\n"); 415 goto failure; 416 } 417 418 ret = 0; 419 420 failure: 421 SSL_CTX_free(ssl_ctx); 422 SSL_free(ssl); 423 424 rbio->references = 1; 425 wbio->references = 1; 426 427 BIO_free(rbio); 428 BIO_free(wbio); 429 430 free(client_hello); 431 432 return (ret); 433 } 434 435 int 436 main(int argc, char **argv) 437 { 438 int failed = 0; 439 size_t i; 440 441 SSL_library_init(); 442 443 for (i = 0; i < N_CLIENT_HELLO_TESTS; i++) 444 failed |= client_hello_test(i, &client_hello_tests[i]); 445 446 return (failed); 447 } 448