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