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, 0xbb, 0x01, 0x00, 0x00, 145 0xb7, 0x03, 0x03, 0x2b, 0x39, 0xcc, 0x56, 0xfc, 146 0xc4, 0x98, 0x8e, 0xfc, 0x22, 0x89, 0xc5, 0x1e, 147 0xa9, 0x88, 0xbd, 0x6e, 0xd8, 0xd1, 0xd6, 0xc1, 148 0xc3, 0x12, 0xe8, 0xe0, 0x1e, 0xfa, 0xa8, 0x21, 149 0xd9, 0x2d, 0x4d, 0x00, 0x00, 0x5c, 0xc0, 0x30, 150 0xc0, 0x2c, 0xc0, 0x28, 0xc0, 0x24, 0xc0, 0x14, 151 0xc0, 0x0a, 0x00, 0x9f, 0x00, 0x6b, 0x00, 0x39, 152 0xcc, 0xa9, 0xcc, 0xa8, 0xcc, 0xaa, 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, 0x32, 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, 0x18, 165 0x00, 0x16, 0x08, 0x06, 0x06, 0x01, 0x06, 0x03, 166 0x08, 0x05, 0x05, 0x01, 0x05, 0x03, 0x08, 0x04, 167 0x04, 0x01, 0x04, 0x03, 0x02, 0x01, 0x02, 0x03, 168 }; 169 170 struct client_hello_test { 171 const unsigned char *desc; 172 const int protocol; 173 const size_t random_start; 174 const SSL_METHOD *(*ssl_method)(void); 175 const long ssl_options; 176 }; 177 178 static struct client_hello_test client_hello_tests[] = { 179 { 180 .desc = "DTLSv1 client", 181 .protocol = DTLS1_VERSION, 182 .random_start = DTLS_RANDOM_OFFSET, 183 .ssl_method = DTLSv1_client_method, 184 }, 185 { 186 .desc = "TLSv1 client", 187 .protocol = TLS1_VERSION, 188 .random_start = SSL3_RANDOM_OFFSET, 189 .ssl_method = TLSv1_client_method, 190 }, 191 { 192 .desc = "TLSv1_1 client", 193 .protocol = TLS1_1_VERSION, 194 .random_start = SSL3_RANDOM_OFFSET, 195 .ssl_method = TLSv1_1_client_method, 196 }, 197 { 198 .desc = "TLSv1_2 client", 199 .protocol = TLS1_2_VERSION, 200 .random_start = SSL3_RANDOM_OFFSET, 201 .ssl_method = TLSv1_2_client_method, 202 }, 203 { 204 .desc = "SSLv23 default", 205 .protocol = TLS1_2_VERSION, 206 .random_start = SSL3_RANDOM_OFFSET, 207 .ssl_method = SSLv23_client_method, 208 .ssl_options = 0, 209 }, 210 { 211 .desc = "SSLv23 (no TLSv1.2)", 212 .protocol = TLS1_1_VERSION, 213 .random_start = SSL3_RANDOM_OFFSET, 214 .ssl_method = SSLv23_client_method, 215 .ssl_options = SSL_OP_NO_TLSv1_2, 216 }, 217 { 218 .desc = "SSLv23 (no TLSv1.1)", 219 .protocol = TLS1_VERSION, 220 .random_start = SSL3_RANDOM_OFFSET, 221 .ssl_method = SSLv23_client_method, 222 .ssl_options = SSL_OP_NO_TLSv1_1, 223 }, 224 { 225 .desc = "TLS default", 226 .protocol = TLS1_2_VERSION, 227 .random_start = SSL3_RANDOM_OFFSET, 228 .ssl_method = TLS_client_method, 229 .ssl_options = 0, 230 }, 231 { 232 .desc = "TLS (no TLSv1.2)", 233 .protocol = TLS1_1_VERSION, 234 .random_start = SSL3_RANDOM_OFFSET, 235 .ssl_method = TLS_client_method, 236 .ssl_options = SSL_OP_NO_TLSv1_2, 237 }, 238 { 239 .desc = "TLS (no TLSv1.1)", 240 .protocol = TLS1_VERSION, 241 .random_start = SSL3_RANDOM_OFFSET, 242 .ssl_method = TLS_client_method, 243 .ssl_options = SSL_OP_NO_TLSv1_1, 244 }, 245 { 246 .desc = "TLS (no TLSv1.0, no TLSv1.1)", 247 .protocol = TLS1_2_VERSION, 248 .random_start = SSL3_RANDOM_OFFSET, 249 .ssl_method = TLS_client_method, 250 .ssl_options = SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1, 251 }, 252 }; 253 254 #define N_CLIENT_HELLO_TESTS \ 255 (sizeof(client_hello_tests) / sizeof(*client_hello_tests)) 256 257 static void 258 hexdump(const unsigned char *buf, size_t len) 259 { 260 size_t i; 261 262 for (i = 1; i <= len; i++) 263 fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n"); 264 265 fprintf(stderr, "\n"); 266 } 267 268 static inline int 269 ssl_aes_is_accelerated(void) 270 { 271 #if defined(__i386__) || defined(__x86_64__) 272 return ((OPENSSL_cpu_caps() & (1ULL << 57)) != 0); 273 #else 274 return (0); 275 #endif 276 } 277 278 static int 279 make_client_hello(int protocol, char **out, size_t *outlen) 280 { 281 size_t client_hello_len, cipher_list_len, cipher_list_offset; 282 const char *client_hello, *cipher_list; 283 char *p; 284 285 *out = NULL; 286 *outlen = 0; 287 288 switch (protocol) { 289 case DTLS1_VERSION: 290 client_hello = client_hello_dtls1; 291 client_hello_len = sizeof(client_hello_dtls1); 292 cipher_list = cipher_list_dtls1; 293 cipher_list_len = sizeof(cipher_list_dtls1); 294 cipher_list_offset = DTLS_CIPHER_OFFSET; 295 break; 296 297 case TLS1_VERSION: 298 client_hello = client_hello_tls10; 299 client_hello_len = sizeof(client_hello_tls10); 300 cipher_list = cipher_list_tls10; 301 cipher_list_len = sizeof(cipher_list_tls10); 302 cipher_list_offset = SSL3_CIPHER_OFFSET; 303 break; 304 305 case TLS1_1_VERSION: 306 client_hello = client_hello_tls11; 307 client_hello_len = sizeof(client_hello_tls11); 308 cipher_list = cipher_list_tls11; 309 cipher_list_len = sizeof(cipher_list_tls11); 310 cipher_list_offset = SSL3_CIPHER_OFFSET; 311 break; 312 313 case TLS1_2_VERSION: 314 client_hello = client_hello_tls12; 315 client_hello_len = sizeof(client_hello_tls12); 316 if (ssl_aes_is_accelerated() == 1) 317 cipher_list = cipher_list_tls12_aes; 318 else 319 cipher_list = cipher_list_tls12_chacha; 320 cipher_list_len = sizeof(cipher_list_tls12_chacha); 321 cipher_list_offset = SSL3_CIPHER_OFFSET; 322 break; 323 324 default: 325 return (-1); 326 } 327 328 if ((p = malloc(client_hello_len)) == NULL) 329 return (-1); 330 331 memcpy(p, client_hello, client_hello_len); 332 memcpy(p + cipher_list_offset, cipher_list, cipher_list_len); 333 334 *out = p; 335 *outlen = client_hello_len; 336 337 return (0); 338 } 339 340 static int 341 client_hello_test(int testno, struct client_hello_test *cht) 342 { 343 BIO *rbio = NULL, *wbio = NULL; 344 SSL_CTX *ssl_ctx = NULL; 345 SSL *ssl = NULL; 346 char *client_hello = NULL; 347 size_t client_hello_len; 348 char *wbuf, rbuf[1]; 349 int ret = 1; 350 size_t i; 351 long len; 352 353 fprintf(stderr, "Test %i - %s\n", testno, cht->desc); 354 355 /* Providing a small buf causes *_get_server_hello() to return. */ 356 if ((rbio = BIO_new_mem_buf(rbuf, sizeof(rbuf))) == NULL) { 357 fprintf(stderr, "Failed to setup rbio\n"); 358 goto failure; 359 } 360 if ((wbio = BIO_new(BIO_s_mem())) == NULL) { 361 fprintf(stderr, "Failed to setup wbio\n"); 362 goto failure; 363 } 364 365 if ((ssl_ctx = SSL_CTX_new(cht->ssl_method())) == NULL) { 366 fprintf(stderr, "SSL_CTX_new() returned NULL\n"); 367 goto failure; 368 } 369 370 SSL_CTX_set_options(ssl_ctx, cht->ssl_options); 371 372 if ((ssl = SSL_new(ssl_ctx)) == NULL) { 373 fprintf(stderr, "SSL_new() returned NULL\n"); 374 goto failure; 375 } 376 377 rbio->references = 2; 378 wbio->references = 2; 379 380 SSL_set_bio(ssl, rbio, wbio); 381 382 if (SSL_connect(ssl) != 0) { 383 fprintf(stderr, "SSL_connect() returned non-zero\n"); 384 goto failure; 385 } 386 387 len = BIO_get_mem_data(wbio, &wbuf); 388 389 if (make_client_hello(cht->protocol, &client_hello, 390 &client_hello_len) != 0) 391 goto failure; 392 393 if ((size_t)len != client_hello_len) { 394 fprintf(stderr, "FAIL: test returned ClientHello length %li, " 395 "want %zu\n", len, client_hello_len); 396 fprintf(stderr, "received:\n"); 397 hexdump(wbuf, len); 398 goto failure; 399 } 400 401 /* We expect the client random to differ. */ 402 i = cht->random_start + SSL3_RANDOM_SIZE; 403 if (memcmp(client_hello, wbuf, cht->random_start) != 0 || 404 memcmp(&client_hello[cht->random_start], 405 &wbuf[cht->random_start], SSL3_RANDOM_SIZE) == 0 || 406 memcmp(&client_hello[i], &wbuf[i], len - i) != 0) { 407 fprintf(stderr, "FAIL: ClientHello differs:\n"); 408 fprintf(stderr, "received:\n"); 409 memset(&wbuf[cht->random_start], 0, SSL3_RANDOM_SIZE); 410 hexdump(wbuf, len); 411 fprintf(stderr, "test data:\n"); 412 hexdump(client_hello, client_hello_len); 413 fprintf(stderr, "\n"); 414 goto failure; 415 } 416 417 ret = 0; 418 419 failure: 420 SSL_CTX_free(ssl_ctx); 421 SSL_free(ssl); 422 423 rbio->references = 1; 424 wbio->references = 1; 425 426 BIO_free(rbio); 427 BIO_free(wbio); 428 429 free(client_hello); 430 431 return (ret); 432 } 433 434 int 435 main(int argc, char **argv) 436 { 437 int failed = 0; 438 size_t i; 439 440 SSL_library_init(); 441 442 for (i = 0; i < N_CLIENT_HELLO_TESTS; i++) 443 failed |= client_hello_test(i, &client_hello_tests[i]); 444 445 return (failed); 446 } 447