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