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, 0x15, 0x00, 0x09, 40 0x00, 0xff, 41 }; 42 43 static unsigned char client_hello_dtls1[] = { 44 0x16, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 45 0x00, 0x00, 0x00, 0x00, 0x64, 0x01, 0x00, 0x00, 46 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 47 0x58, 0xfe, 0xff, 0xc3, 0xd6, 0x19, 0xf8, 0x5d, 48 0x6a, 0xe3, 0x6d, 0x16, 0x4a, 0xf7, 0x8f, 0x8e, 49 0x4a, 0x12, 0x87, 0xcf, 0x07, 0x99, 0xa7, 0x92, 50 0x40, 0xbd, 0x06, 0x9f, 0xe9, 0xd2, 0x68, 0x84, 51 0xff, 0x6f, 0xe8, 0x00, 0x00, 0x00, 0x2a, 0xc0, 52 0x14, 0xc0, 0x0a, 0x00, 0x39, 0xff, 0x85, 0x00, 53 0x88, 0x00, 0x81, 0x00, 0x35, 0x00, 0x84, 0xc0, 54 0x13, 0xc0, 0x09, 0x00, 0x33, 0x00, 0x45, 0x00, 55 0x2f, 0x00, 0x41, 0xc0, 0x12, 0xc0, 0x08, 0x00, 56 0x16, 0x00, 0x0a, 0x00, 0x15, 0x00, 0x09, 0x00, 57 0xff, 0x01, 0x00, 0x00, 0x04, 0x00, 0x23, 0x00, 58 0x00, 59 }; 60 61 static unsigned char cipher_list_tls10[] = { 62 0xc0, 0x14, 0xc0, 0x0a, 0x00, 0x39, 0xff, 0x85, 63 0x00, 0x88, 0x00, 0x81, 0x00, 0x35, 0x00, 0x84, 64 0xc0, 0x13, 0xc0, 0x09, 0x00, 0x33, 0x00, 0x45, 65 0x00, 0x2f, 0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07, 66 0x00, 0x05, 0x00, 0x04, 0xc0, 0x12, 0xc0, 0x08, 67 0x00, 0x16, 0x00, 0x0a, 0x00, 0x15, 0x00, 0x09, 68 0x00, 0xff, 69 }; 70 71 static unsigned char client_hello_tls10[] = { 72 0x16, 0x03, 0x01, 0x00, 0x75, 0x01, 0x00, 0x00, 73 0x71, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 74 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 76 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 77 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0xc0, 0x14, 78 0xc0, 0x0a, 0x00, 0x39, 0xff, 0x85, 0x00, 0x88, 79 0x00, 0x81, 0x00, 0x35, 0x00, 0x84, 0xc0, 0x13, 80 0xc0, 0x09, 0x00, 0x33, 0x00, 0x45, 0x00, 0x2f, 81 0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07, 0x00, 0x05, 82 0x00, 0x04, 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, 83 0x00, 0x0a, 0x00, 0x15, 0x00, 0x09, 0x00, 0xff, 84 0x01, 0x00, 0x00, 0x16, 0x00, 0x0b, 0x00, 0x02, 85 0x01, 0x00, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x06, 86 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18, 0x00, 0x23, 87 0x00, 0x00, 88 }; 89 90 static unsigned char cipher_list_tls11[] = { 91 0xc0, 0x14, 0xc0, 0x0a, 0x00, 0x39, 0xff, 0x85, 92 0x00, 0x88, 0x00, 0x81, 0x00, 0x35, 0x00, 0x84, 93 0xc0, 0x13, 0xc0, 0x09, 0x00, 0x33, 0x00, 0x45, 94 0x00, 0x2f, 0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07, 95 0x00, 0x05, 0x00, 0x04, 0xc0, 0x12, 0xc0, 0x08, 96 0x00, 0x16, 0x00, 0x0a, 0x00, 0x15, 0x00, 0x09, 97 0x00, 0xff, 98 }; 99 100 static unsigned char client_hello_tls11[] = { 101 0x16, 0x03, 0x01, 0x00, 0x75, 0x01, 0x00, 0x00, 102 0x71, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 103 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 104 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 105 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 106 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0xc0, 0x14, 107 0xc0, 0x0a, 0x00, 0x39, 0xff, 0x85, 0x00, 0x88, 108 0x00, 0x81, 0x00, 0x35, 0x00, 0x84, 0xc0, 0x13, 109 0xc0, 0x09, 0x00, 0x33, 0x00, 0x45, 0x00, 0x2f, 110 0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07, 0x00, 0x05, 111 0x00, 0x04, 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, 112 0x00, 0x0a, 0x00, 0x15, 0x00, 0x09, 0x00, 0xff, 113 0x01, 0x00, 0x00, 0x16, 0x00, 0x0b, 0x00, 0x02, 114 0x01, 0x00, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x06, 115 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18, 0x00, 0x23, 116 0x00, 0x00, 117 }; 118 119 static unsigned char cipher_list_tls12_aes[] = { 120 0xc0, 0x30, 0xc0, 0x2c, 0xc0, 0x28, 0xc0, 0x24, 121 0xc0, 0x14, 0xc0, 0x0a, 0x00, 0x9f, 0x00, 0x6b, 122 0x00, 0x39, 0xcc, 0xa9, 0xcc, 0xa8, 0xcc, 0xaa, 123 0xff, 0x85, 0x00, 0xc4, 0x00, 0x88, 0x00, 0x81, 124 0x00, 0x9d, 0x00, 0x3d, 0x00, 0x35, 0x00, 0xc0, 125 0x00, 0x84, 0xc0, 0x2f, 0xc0, 0x2b, 0xc0, 0x27, 126 0xc0, 0x23, 0xc0, 0x13, 0xc0, 0x09, 0x00, 0x9e, 127 0x00, 0x67, 0x00, 0x33, 0x00, 0xbe, 0x00, 0x45, 128 0x00, 0x9c, 0x00, 0x3c, 0x00, 0x2f, 0x00, 0xba, 129 0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07, 0x00, 0x05, 130 0x00, 0x04, 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, 131 0x00, 0x0a, 0x00, 0x15, 0x00, 0x09, 0x00, 0xff, 132 }; 133 134 static unsigned char cipher_list_tls12_chacha[] = { 135 0xcc, 0xa9, 0xcc, 0xa8, 0xcc, 0xaa, 0xc0, 0x30, 136 0xc0, 0x2c, 0xc0, 0x28, 0xc0, 0x24, 0xc0, 0x14, 137 0xc0, 0x0a, 0x00, 0x9f, 0x00, 0x6b, 0x00, 0x39, 138 0xff, 0x85, 0x00, 0xc4, 0x00, 0x88, 0x00, 0x81, 139 0x00, 0x9d, 0x00, 0x3d, 0x00, 0x35, 0x00, 0xc0, 140 0x00, 0x84, 0xc0, 0x2f, 0xc0, 0x2b, 0xc0, 0x27, 141 0xc0, 0x23, 0xc0, 0x13, 0xc0, 0x09, 0x00, 0x9e, 142 0x00, 0x67, 0x00, 0x33, 0x00, 0xbe, 0x00, 0x45, 143 0x00, 0x9c, 0x00, 0x3c, 0x00, 0x2f, 0x00, 0xba, 144 0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07, 0x00, 0x05, 145 0x00, 0x04, 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, 146 0x00, 0x0a, 0x00, 0x15, 0x00, 0x09, 0x00, 0xff, 147 }; 148 149 static unsigned char client_hello_tls12[] = { 150 0x16, 0x03, 0x01, 0x00, 0xc3, 0x01, 0x00, 0x00, 151 0xbf, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 152 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 153 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 154 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 155 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xcc, 0xa9, 156 0xcc, 0xa8, 0xcc, 0xaa, 0xc0, 0x30, 0xc0, 0x2c, 157 0xc0, 0x28, 0xc0, 0x24, 0xc0, 0x14, 0xc0, 0x0a, 158 0x00, 0x9f, 0x00, 0x6b, 0x00, 0x39, 0xff, 0x85, 159 0x00, 0xc4, 0x00, 0x88, 0x00, 0x81, 0x00, 0x9d, 160 0x00, 0x3d, 0x00, 0x35, 0x00, 0xc0, 0x00, 0x84, 161 0xc0, 0x2f, 0xc0, 0x2b, 0xc0, 0x27, 0xc0, 0x23, 162 0xc0, 0x13, 0xc0, 0x09, 0x00, 0x9e, 0x00, 0x67, 163 0x00, 0x33, 0x00, 0xbe, 0x00, 0x45, 0x00, 0x9c, 164 0x00, 0x3c, 0x00, 0x2f, 0x00, 0xba, 0x00, 0x41, 165 0xc0, 0x11, 0xc0, 0x07, 0x00, 0x05, 0x00, 0x04, 166 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, 0x00, 0x0a, 167 0x00, 0x15, 0x00, 0x09, 0x00, 0xff, 0x01, 0x00, 168 0x00, 0x36, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 169 0x00, 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x1d, 170 0x00, 0x17, 0x00, 0x18, 0x00, 0x23, 0x00, 0x00, 171 0x00, 0x0d, 0x00, 0x1c, 0x00, 0x1a, 0x06, 0x01, 172 0x06, 0x03, 0xef, 0xef, 0x05, 0x01, 0x05, 0x03, 173 0x04, 0x01, 0x04, 0x03, 0xee, 0xee, 0xed, 0xed, 174 0x03, 0x01, 0x03, 0x03, 0x02, 0x01, 0x02, 0x03, 175 }; 176 177 struct client_hello_test { 178 const unsigned char *desc; 179 const int protocol; 180 const size_t random_start; 181 const SSL_METHOD *(*ssl_method)(void); 182 const long ssl_options; 183 }; 184 185 static struct client_hello_test client_hello_tests[] = { 186 { 187 .desc = "DTLSv1 client", 188 .protocol = DTLS1_VERSION, 189 .random_start = DTLS_RANDOM_OFFSET, 190 .ssl_method = DTLSv1_client_method, 191 }, 192 { 193 .desc = "TLSv1 client", 194 .protocol = TLS1_VERSION, 195 .random_start = SSL3_RANDOM_OFFSET, 196 .ssl_method = TLSv1_client_method, 197 }, 198 { 199 .desc = "TLSv1_1 client", 200 .protocol = TLS1_1_VERSION, 201 .random_start = SSL3_RANDOM_OFFSET, 202 .ssl_method = TLSv1_1_client_method, 203 }, 204 { 205 .desc = "TLSv1_2 client", 206 .protocol = TLS1_2_VERSION, 207 .random_start = SSL3_RANDOM_OFFSET, 208 .ssl_method = TLSv1_2_client_method, 209 }, 210 { 211 .desc = "SSLv23 default", 212 .protocol = TLS1_2_VERSION, 213 .random_start = SSL3_RANDOM_OFFSET, 214 .ssl_method = SSLv23_client_method, 215 .ssl_options = 0, 216 }, 217 { 218 .desc = "SSLv23 (no TLSv1.2)", 219 .protocol = TLS1_1_VERSION, 220 .random_start = SSL3_RANDOM_OFFSET, 221 .ssl_method = SSLv23_client_method, 222 .ssl_options = SSL_OP_NO_TLSv1_2, 223 }, 224 { 225 .desc = "SSLv23 (no TLSv1.1)", 226 .protocol = TLS1_VERSION, 227 .random_start = SSL3_RANDOM_OFFSET, 228 .ssl_method = SSLv23_client_method, 229 .ssl_options = SSL_OP_NO_TLSv1_1, 230 }, 231 { 232 .desc = "TLS default", 233 .protocol = TLS1_2_VERSION, 234 .random_start = SSL3_RANDOM_OFFSET, 235 .ssl_method = TLS_client_method, 236 .ssl_options = 0, 237 }, 238 { 239 .desc = "TLS (no TLSv1.2)", 240 .protocol = TLS1_1_VERSION, 241 .random_start = SSL3_RANDOM_OFFSET, 242 .ssl_method = TLS_client_method, 243 .ssl_options = SSL_OP_NO_TLSv1_2, 244 }, 245 { 246 .desc = "TLS (no TLSv1.1)", 247 .protocol = TLS1_VERSION, 248 .random_start = SSL3_RANDOM_OFFSET, 249 .ssl_method = TLS_client_method, 250 .ssl_options = SSL_OP_NO_TLSv1_1, 251 }, 252 { 253 .desc = "TLS (no TLSv1.0, no TLSv1.1)", 254 .protocol = TLS1_2_VERSION, 255 .random_start = SSL3_RANDOM_OFFSET, 256 .ssl_method = TLS_client_method, 257 .ssl_options = SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1, 258 }, 259 }; 260 261 #define N_CLIENT_HELLO_TESTS \ 262 (sizeof(client_hello_tests) / sizeof(*client_hello_tests)) 263 264 static void 265 hexdump(const unsigned char *buf, size_t len) 266 { 267 size_t i; 268 269 for (i = 1; i <= len; i++) 270 fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n"); 271 272 fprintf(stderr, "\n"); 273 } 274 275 static inline int 276 ssl_aes_is_accelerated(void) 277 { 278 #if defined(__i386__) || defined(__x86_64__) 279 return ((OPENSSL_cpu_caps() & (1ULL << 57)) != 0); 280 #else 281 return (0); 282 #endif 283 } 284 285 static int 286 make_client_hello(int protocol, char **out, size_t *outlen) 287 { 288 size_t client_hello_len, cipher_list_len, cipher_list_offset; 289 const char *client_hello, *cipher_list; 290 char *p; 291 292 *out = NULL; 293 *outlen = 0; 294 295 switch (protocol) { 296 case DTLS1_VERSION: 297 client_hello = client_hello_dtls1; 298 client_hello_len = sizeof(client_hello_dtls1); 299 cipher_list = cipher_list_dtls1; 300 cipher_list_len = sizeof(cipher_list_dtls1); 301 cipher_list_offset = DTLS_CIPHER_OFFSET; 302 break; 303 304 case TLS1_VERSION: 305 client_hello = client_hello_tls10; 306 client_hello_len = sizeof(client_hello_tls10); 307 cipher_list = cipher_list_tls10; 308 cipher_list_len = sizeof(cipher_list_tls10); 309 cipher_list_offset = SSL3_CIPHER_OFFSET; 310 break; 311 312 case TLS1_1_VERSION: 313 client_hello = client_hello_tls11; 314 client_hello_len = sizeof(client_hello_tls11); 315 cipher_list = cipher_list_tls11; 316 cipher_list_len = sizeof(cipher_list_tls11); 317 cipher_list_offset = SSL3_CIPHER_OFFSET; 318 break; 319 320 case TLS1_2_VERSION: 321 client_hello = client_hello_tls12; 322 client_hello_len = sizeof(client_hello_tls12); 323 if (ssl_aes_is_accelerated() == 1) 324 cipher_list = cipher_list_tls12_aes; 325 else 326 cipher_list = cipher_list_tls12_chacha; 327 cipher_list_len = sizeof(cipher_list_tls12_chacha); 328 cipher_list_offset = SSL3_CIPHER_OFFSET; 329 break; 330 331 default: 332 return (-1); 333 } 334 335 if ((p = malloc(client_hello_len)) == NULL) 336 return (-1); 337 338 memcpy(p, client_hello, client_hello_len); 339 memcpy(p + cipher_list_offset, cipher_list, cipher_list_len); 340 341 *out = p; 342 *outlen = client_hello_len; 343 344 return (0); 345 } 346 347 static int 348 client_hello_test(int testno, struct client_hello_test *cht) 349 { 350 BIO *rbio = NULL, *wbio = NULL; 351 SSL_CTX *ssl_ctx = NULL; 352 SSL *ssl = NULL; 353 char *client_hello = NULL; 354 size_t client_hello_len; 355 char *wbuf, rbuf[1]; 356 int ret = 1; 357 size_t i; 358 long len; 359 360 fprintf(stderr, "Test %i - %s\n", testno, cht->desc); 361 362 /* Providing a small buf causes *_get_server_hello() to return. */ 363 if ((rbio = BIO_new_mem_buf(rbuf, sizeof(rbuf))) == NULL) { 364 fprintf(stderr, "Failed to setup rbio\n"); 365 goto failure; 366 } 367 if ((wbio = BIO_new(BIO_s_mem())) == NULL) { 368 fprintf(stderr, "Failed to setup wbio\n"); 369 goto failure; 370 } 371 372 if ((ssl_ctx = SSL_CTX_new(cht->ssl_method())) == NULL) { 373 fprintf(stderr, "SSL_CTX_new() returned NULL\n"); 374 goto failure; 375 } 376 377 SSL_CTX_set_options(ssl_ctx, cht->ssl_options); 378 379 if ((ssl = SSL_new(ssl_ctx)) == NULL) { 380 fprintf(stderr, "SSL_new() returned NULL\n"); 381 goto failure; 382 } 383 384 rbio->references = 2; 385 wbio->references = 2; 386 387 SSL_set_bio(ssl, rbio, wbio); 388 389 if (SSL_connect(ssl) != 0) { 390 fprintf(stderr, "SSL_connect() returned non-zero\n"); 391 goto failure; 392 } 393 394 len = BIO_get_mem_data(wbio, &wbuf); 395 396 if (make_client_hello(cht->protocol, &client_hello, 397 &client_hello_len) != 0) 398 goto failure; 399 400 if ((size_t)len != client_hello_len) { 401 fprintf(stderr, "FAIL: test returned ClientHello length %li, " 402 "want %zu\n", len, client_hello_len); 403 fprintf(stderr, "received:\n"); 404 hexdump(wbuf, len); 405 goto failure; 406 } 407 408 /* We expect the client random to differ. */ 409 i = cht->random_start + SSL3_RANDOM_SIZE; 410 if (memcmp(client_hello, wbuf, cht->random_start) != 0 || 411 memcmp(&client_hello[cht->random_start], 412 &wbuf[cht->random_start], SSL3_RANDOM_SIZE) == 0 || 413 memcmp(&client_hello[i], &wbuf[i], len - i) != 0) { 414 fprintf(stderr, "FAIL: ClientHello differs:\n"); 415 fprintf(stderr, "received:\n"); 416 memset(&wbuf[cht->random_start], 0, SSL3_RANDOM_SIZE); 417 hexdump(wbuf, len); 418 fprintf(stderr, "test data:\n"); 419 hexdump(client_hello, client_hello_len); 420 fprintf(stderr, "\n"); 421 goto failure; 422 } 423 424 ret = 0; 425 426 failure: 427 SSL_CTX_free(ssl_ctx); 428 SSL_free(ssl); 429 430 rbio->references = 1; 431 wbio->references = 1; 432 433 BIO_free(rbio); 434 BIO_free(wbio); 435 436 free(client_hello); 437 438 return (ret); 439 } 440 441 int 442 main(int argc, char **argv) 443 { 444 int failed = 0; 445 size_t i; 446 447 SSL_library_init(); 448 449 for (i = 0; i < N_CLIENT_HELLO_TESTS; i++) 450 failed |= client_hello_test(i, &client_hello_tests[i]); 451 452 return (failed); 453 } 454