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, 0x73, 0x01, 0x00, 0x00, 70 0x6f, 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, 0x18, 81 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x0a, 82 0x00, 0x0a, 0x00, 0x08, 0x00, 0x1d, 0x00, 0x17, 83 0x00, 0x18, 0x00, 0x19, 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, 0x73, 0x01, 0x00, 0x00, 97 0x6f, 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, 0x18, 108 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x0a, 109 0x00, 0x0a, 0x00, 0x08, 0x00, 0x1d, 0x00, 0x17, 110 0x00, 0x18, 0x00, 0x19, 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, 0xbd, 0x01, 0x00, 0x00, 145 0xb9, 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, 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, 0x34, 0x00, 0x0b, 162 0x00, 0x02, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x0a, 163 0x00, 0x08, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18, 164 0x00, 0x19, 0x00, 0x23, 0x00, 0x00, 0x00, 0x0d, 165 0x00, 0x18, 0x00, 0x16, 0x08, 0x06, 0x06, 0x01, 166 0x06, 0x03, 0x08, 0x05, 0x05, 0x01, 0x05, 0x03, 167 0x08, 0x04, 0x04, 0x01, 0x04, 0x03, 0x02, 0x01, 168 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 #if 0 205 { 206 .desc = "SSLv23 default", 207 .protocol = TLS1_3_VERSION, 208 .random_start = SSL3_RANDOM_OFFSET, 209 .ssl_method = SSLv23_client_method, 210 .ssl_options = 0, 211 }, 212 #endif 213 { 214 .desc = "SSLv23 default (no TLSv1.3)", 215 .protocol = TLS1_2_VERSION, 216 .random_start = SSL3_RANDOM_OFFSET, 217 .ssl_method = SSLv23_client_method, 218 .ssl_options = SSL_OP_NO_TLSv1_3, 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 #if 0 235 { 236 .desc = "TLS default", 237 .protocol = TLS1_3_VERSION, 238 .random_start = SSL3_RANDOM_OFFSET, 239 .ssl_method = TLS_client_method, 240 .ssl_options = 0, 241 }, 242 #endif 243 { 244 .desc = "TLS (no TLSv1.3)", 245 .protocol = TLS1_2_VERSION, 246 .random_start = SSL3_RANDOM_OFFSET, 247 .ssl_method = TLS_client_method, 248 .ssl_options = SSL_OP_NO_TLSv1_3, 249 }, 250 { 251 .desc = "TLS (no TLSv1.2)", 252 .protocol = TLS1_1_VERSION, 253 .random_start = SSL3_RANDOM_OFFSET, 254 .ssl_method = TLS_client_method, 255 .ssl_options = SSL_OP_NO_TLSv1_2, 256 }, 257 { 258 .desc = "TLS (no TLSv1.1)", 259 .protocol = TLS1_VERSION, 260 .random_start = SSL3_RANDOM_OFFSET, 261 .ssl_method = TLS_client_method, 262 .ssl_options = SSL_OP_NO_TLSv1_1, 263 }, 264 #if 0 265 { 266 .desc = "TLS (no TLSv1.0, no TLSv1.1)", 267 .protocol = TLS1_3_VERSION, 268 .random_start = SSL3_RANDOM_OFFSET, 269 .ssl_method = TLS_client_method, 270 .ssl_options = SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1, 271 }, 272 #endif 273 #if 0 274 { 275 .desc = "TLS (no TLSv1.0, no TLSv1.1, no TLSv1.2)", 276 .protocol = TLS1_3_VERSION, 277 .random_start = SSL3_RANDOM_OFFSET, 278 .ssl_method = TLS_client_method, 279 .ssl_options = SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2, 280 }, 281 #endif 282 }; 283 284 #define N_CLIENT_HELLO_TESTS \ 285 (sizeof(client_hello_tests) / sizeof(*client_hello_tests)) 286 287 static void 288 hexdump(const unsigned char *buf, size_t len) 289 { 290 size_t i; 291 292 for (i = 1; i <= len; i++) 293 fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 && i != len ? "" : "\n"); 294 295 fprintf(stderr, "\n"); 296 } 297 298 static inline int 299 ssl_aes_is_accelerated(void) 300 { 301 #if defined(__i386__) || defined(__x86_64__) 302 return ((OPENSSL_cpu_caps() & (1ULL << 57)) != 0); 303 #else 304 return (0); 305 #endif 306 } 307 308 static int 309 make_client_hello(int protocol, char **out, size_t *outlen) 310 { 311 size_t client_hello_len, cipher_list_len, cipher_list_offset; 312 const char *client_hello, *cipher_list; 313 char *p; 314 315 *out = NULL; 316 *outlen = 0; 317 318 switch (protocol) { 319 case DTLS1_VERSION: 320 client_hello = client_hello_dtls1; 321 client_hello_len = sizeof(client_hello_dtls1); 322 cipher_list = cipher_list_dtls1; 323 cipher_list_len = sizeof(cipher_list_dtls1); 324 cipher_list_offset = DTLS_CIPHER_OFFSET; 325 break; 326 327 case TLS1_VERSION: 328 client_hello = client_hello_tls10; 329 client_hello_len = sizeof(client_hello_tls10); 330 cipher_list = cipher_list_tls10; 331 cipher_list_len = sizeof(cipher_list_tls10); 332 cipher_list_offset = SSL3_CIPHER_OFFSET; 333 break; 334 335 case TLS1_1_VERSION: 336 client_hello = client_hello_tls11; 337 client_hello_len = sizeof(client_hello_tls11); 338 cipher_list = cipher_list_tls11; 339 cipher_list_len = sizeof(cipher_list_tls11); 340 cipher_list_offset = SSL3_CIPHER_OFFSET; 341 break; 342 343 case TLS1_2_VERSION: 344 client_hello = client_hello_tls12; 345 client_hello_len = sizeof(client_hello_tls12); 346 if (ssl_aes_is_accelerated()) 347 cipher_list = cipher_list_tls12_aes; 348 else 349 cipher_list = cipher_list_tls12_chacha; 350 cipher_list_len = sizeof(cipher_list_tls12_chacha); 351 cipher_list_offset = SSL3_CIPHER_OFFSET; 352 break; 353 354 default: 355 return (-1); 356 } 357 358 if ((p = malloc(client_hello_len)) == NULL) 359 return (-1); 360 361 memcpy(p, client_hello, client_hello_len); 362 memcpy(p + cipher_list_offset, cipher_list, cipher_list_len); 363 364 *out = p; 365 *outlen = client_hello_len; 366 367 return (0); 368 } 369 370 static int 371 client_hello_test(int testno, struct client_hello_test *cht) 372 { 373 BIO *rbio = NULL, *wbio = NULL; 374 SSL_CTX *ssl_ctx = NULL; 375 SSL *ssl = NULL; 376 char *client_hello = NULL; 377 size_t client_hello_len; 378 char *wbuf, rbuf[1]; 379 int ret = 1; 380 long len; 381 382 fprintf(stderr, "Test %i - %s\n", testno, cht->desc); 383 384 /* Providing a small buf causes *_get_server_hello() to return. */ 385 if ((rbio = BIO_new_mem_buf(rbuf, sizeof(rbuf))) == NULL) { 386 fprintf(stderr, "Failed to setup rbio\n"); 387 goto failure; 388 } 389 if ((wbio = BIO_new(BIO_s_mem())) == NULL) { 390 fprintf(stderr, "Failed to setup wbio\n"); 391 goto failure; 392 } 393 394 if ((ssl_ctx = SSL_CTX_new(cht->ssl_method())) == NULL) { 395 fprintf(stderr, "SSL_CTX_new() returned NULL\n"); 396 goto failure; 397 } 398 399 SSL_CTX_set_options(ssl_ctx, cht->ssl_options); 400 401 if ((ssl = SSL_new(ssl_ctx)) == NULL) { 402 fprintf(stderr, "SSL_new() returned NULL\n"); 403 goto failure; 404 } 405 406 rbio->references = 2; 407 wbio->references = 2; 408 409 SSL_set_bio(ssl, rbio, wbio); 410 411 if (SSL_connect(ssl) != 0) { 412 fprintf(stderr, "SSL_connect() returned non-zero\n"); 413 goto failure; 414 } 415 416 len = BIO_get_mem_data(wbio, &wbuf); 417 418 if (make_client_hello(cht->protocol, &client_hello, 419 &client_hello_len) != 0) 420 errx(1, "failed to make client hello"); 421 422 if ((size_t)len != client_hello_len) { 423 fprintf(stderr, "FAIL: test returned ClientHello length %li, " 424 "want %zu\n", len, client_hello_len); 425 fprintf(stderr, "received:\n"); 426 hexdump(wbuf, len); 427 fprintf(stderr, "test data:\n"); 428 hexdump(client_hello, client_hello_len); 429 fprintf(stderr, "\n"); 430 goto failure; 431 } 432 433 /* We expect the client random to differ. */ 434 if (memcmp(&client_hello[cht->random_start], &wbuf[cht->random_start], 435 SSL3_RANDOM_SIZE) == 0) { 436 fprintf(stderr, "FAIL: ClientHello has zeroed random\n"); 437 goto failure; 438 } 439 440 memset(&wbuf[cht->random_start], 0, SSL3_RANDOM_SIZE); 441 442 if (memcmp(client_hello, wbuf, client_hello_len) != 0) { 443 fprintf(stderr, "FAIL: ClientHello differs:\n"); 444 fprintf(stderr, "received:\n"); 445 hexdump(wbuf, len); 446 fprintf(stderr, "test data:\n"); 447 hexdump(client_hello, client_hello_len); 448 fprintf(stderr, "\n"); 449 goto failure; 450 } 451 452 ret = 0; 453 454 failure: 455 SSL_CTX_free(ssl_ctx); 456 SSL_free(ssl); 457 458 rbio->references = 1; 459 wbio->references = 1; 460 461 BIO_free(rbio); 462 BIO_free(wbio); 463 464 free(client_hello); 465 466 return (ret); 467 } 468 469 int 470 main(int argc, char **argv) 471 { 472 int failed = 0; 473 size_t i; 474 475 SSL_library_init(); 476 477 for (i = 0; i < N_CLIENT_HELLO_TESTS; i++) 478 failed |= client_hello_test(i, &client_hello_tests[i]); 479 480 return (failed); 481 } 482