1 /* $OpenBSD: clienttest.c,v 1.26 2020/11/19 09:35:50 tb Exp $ */ 2 /* 3 * Copyright (c) 2015 Joel Sing <jsing@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <openssl/ssl.h> 19 20 #include <openssl/dtls1.h> 21 #include <openssl/ssl3.h> 22 23 #include <err.h> 24 #include <stdio.h> 25 #include <string.h> 26 27 #define DTLS_HM_OFFSET (DTLS1_RT_HEADER_LENGTH + DTLS1_HM_HEADER_LENGTH) 28 #define DTLS_RANDOM_OFFSET (DTLS_HM_OFFSET + 2) 29 #define DTLS_CIPHER_OFFSET (DTLS_HM_OFFSET + 38) 30 31 #define SSL3_HM_OFFSET (SSL3_RT_HEADER_LENGTH + SSL3_HM_HEADER_LENGTH) 32 #define SSL3_RANDOM_OFFSET (SSL3_HM_OFFSET + 2) 33 #define SSL3_CIPHER_OFFSET (SSL3_HM_OFFSET + 37) 34 35 static unsigned char cipher_list_dtls1[] = { 36 0xc0, 0x14, 0xc0, 0x0a, 0x00, 0x39, 0xff, 0x85, 37 0x00, 0x88, 0x00, 0x81, 0x00, 0x35, 0x00, 0x84, 38 0xc0, 0x13, 0xc0, 0x09, 0x00, 0x33, 0x00, 0x45, 39 0x00, 0x2f, 0x00, 0x41, 0xc0, 0x12, 0xc0, 0x08, 40 0x00, 0x16, 0x00, 0x0a, 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, 0x60, 0x01, 0x00, 0x00, 46 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 47 0x54, 0xfe, 0xff, 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, 0x00, 0x00, 51 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 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, 0xff, 0x01, 0x00, 0x00, 57 0x04, 0x00, 0x23, 0x00, 0x00, 58 }; 59 60 static unsigned char cipher_list_tls10[] = { 61 0xc0, 0x14, 0xc0, 0x0a, 0x00, 0x39, 0xff, 0x85, 62 0x00, 0x88, 0x00, 0x81, 0x00, 0x35, 0x00, 0x84, 63 0xc0, 0x13, 0xc0, 0x09, 0x00, 0x33, 0x00, 0x45, 64 0x00, 0x2f, 0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07, 65 0x00, 0x05, 0x00, 0x04, 0xc0, 0x12, 0xc0, 0x08, 66 0x00, 0x16, 0x00, 0x0a, 0x00, 0xff, 67 }; 68 69 static unsigned char client_hello_tls10[] = { 70 0x16, 0x03, 0x01, 0x00, 0x73, 0x01, 0x00, 0x00, 71 0x6f, 0x03, 0x01, 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, 0x00, 0x00, 0x00, 75 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0xc0, 0x14, 76 0xc0, 0x0a, 0x00, 0x39, 0xff, 0x85, 0x00, 0x88, 77 0x00, 0x81, 0x00, 0x35, 0x00, 0x84, 0xc0, 0x13, 78 0xc0, 0x09, 0x00, 0x33, 0x00, 0x45, 0x00, 0x2f, 79 0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07, 0x00, 0x05, 80 0x00, 0x04, 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, 81 0x00, 0x0a, 0x00, 0xff, 0x01, 0x00, 0x00, 0x18, 82 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x0a, 83 0x00, 0x0a, 0x00, 0x08, 0x00, 0x1d, 0x00, 0x17, 84 0x00, 0x18, 0x00, 0x19, 0x00, 0x23, 0x00, 0x00, 85 }; 86 87 static unsigned char cipher_list_tls11[] = { 88 0xc0, 0x14, 0xc0, 0x0a, 0x00, 0x39, 0xff, 0x85, 89 0x00, 0x88, 0x00, 0x81, 0x00, 0x35, 0x00, 0x84, 90 0xc0, 0x13, 0xc0, 0x09, 0x00, 0x33, 0x00, 0x45, 91 0x00, 0x2f, 0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07, 92 0x00, 0x05, 0x00, 0x04, 0xc0, 0x12, 0xc0, 0x08, 93 0x00, 0x16, 0x00, 0x0a, 0x00, 0xff, 94 }; 95 96 static unsigned char client_hello_tls11[] = { 97 0x16, 0x03, 0x01, 0x00, 0x73, 0x01, 0x00, 0x00, 98 0x6f, 0x03, 0x02, 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, 0x00, 0x00, 0x00, 102 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0xc0, 0x14, 103 0xc0, 0x0a, 0x00, 0x39, 0xff, 0x85, 0x00, 0x88, 104 0x00, 0x81, 0x00, 0x35, 0x00, 0x84, 0xc0, 0x13, 105 0xc0, 0x09, 0x00, 0x33, 0x00, 0x45, 0x00, 0x2f, 106 0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07, 0x00, 0x05, 107 0x00, 0x04, 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, 108 0x00, 0x0a, 0x00, 0xff, 0x01, 0x00, 0x00, 0x18, 109 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x0a, 110 0x00, 0x0a, 0x00, 0x08, 0x00, 0x1d, 0x00, 0x17, 111 0x00, 0x18, 0x00, 0x19, 0x00, 0x23, 0x00, 0x00, 112 }; 113 114 static unsigned char cipher_list_tls12_aes[] = { 115 0xc0, 0x30, 0xc0, 0x2c, 0xc0, 0x28, 0xc0, 0x24, 116 0xc0, 0x14, 0xc0, 0x0a, 0x00, 0x9f, 0x00, 0x6b, 117 0x00, 0x39, 0xcc, 0xa9, 0xcc, 0xa8, 0xcc, 0xaa, 118 0xff, 0x85, 0x00, 0xc4, 0x00, 0x88, 0x00, 0x81, 119 0x00, 0x9d, 0x00, 0x3d, 0x00, 0x35, 0x00, 0xc0, 120 0x00, 0x84, 0xc0, 0x2f, 0xc0, 0x2b, 0xc0, 0x27, 121 0xc0, 0x23, 0xc0, 0x13, 0xc0, 0x09, 0x00, 0x9e, 122 0x00, 0x67, 0x00, 0x33, 0x00, 0xbe, 0x00, 0x45, 123 0x00, 0x9c, 0x00, 0x3c, 0x00, 0x2f, 0x00, 0xba, 124 0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07, 0x00, 0x05, 125 0x00, 0x04, 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, 126 0x00, 0x0a, 0x00, 0xff, 127 }; 128 129 static unsigned char cipher_list_tls12_chacha[] = { 130 0xcc, 0xa9, 0xcc, 0xa8, 0xcc, 0xaa, 0xc0, 0x30, 131 0xc0, 0x2c, 0xc0, 0x28, 0xc0, 0x24, 0xc0, 0x14, 132 0xc0, 0x0a, 0x00, 0x9f, 0x00, 0x6b, 0x00, 0x39, 133 0xff, 0x85, 0x00, 0xc4, 0x00, 0x88, 0x00, 0x81, 134 0x00, 0x9d, 0x00, 0x3d, 0x00, 0x35, 0x00, 0xc0, 135 0x00, 0x84, 0xc0, 0x2f, 0xc0, 0x2b, 0xc0, 0x27, 136 0xc0, 0x23, 0xc0, 0x13, 0xc0, 0x09, 0x00, 0x9e, 137 0x00, 0x67, 0x00, 0x33, 0x00, 0xbe, 0x00, 0x45, 138 0x00, 0x9c, 0x00, 0x3c, 0x00, 0x2f, 0x00, 0xba, 139 0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07, 0x00, 0x05, 140 0x00, 0x04, 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, 141 0x00, 0x0a, 0x00, 0xff, 142 }; 143 144 static unsigned char client_hello_tls12[] = { 145 0x16, 0x03, 0x01, 0x00, 0xbd, 0x01, 0x00, 0x00, 146 0xb9, 0x03, 0x03, 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, 0x00, 0x00, 0x00, 150 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0xc0, 0x30, 151 0xc0, 0x2c, 0xc0, 0x28, 0xc0, 0x24, 0xc0, 0x14, 152 0xc0, 0x0a, 0x00, 0x9f, 0x00, 0x6b, 0x00, 0x39, 153 0xcc, 0xa9, 0xcc, 0xa8, 0xcc, 0xaa, 0xff, 0x85, 154 0x00, 0xc4, 0x00, 0x88, 0x00, 0x81, 0x00, 0x9d, 155 0x00, 0x3d, 0x00, 0x35, 0x00, 0xc0, 0x00, 0x84, 156 0xc0, 0x2f, 0xc0, 0x2b, 0xc0, 0x27, 0xc0, 0x23, 157 0xc0, 0x13, 0xc0, 0x09, 0x00, 0x9e, 0x00, 0x67, 158 0x00, 0x33, 0x00, 0xbe, 0x00, 0x45, 0x00, 0x9c, 159 0x00, 0x3c, 0x00, 0x2f, 0x00, 0xba, 0x00, 0x41, 160 0xc0, 0x11, 0xc0, 0x07, 0x00, 0x05, 0x00, 0x04, 161 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, 0x00, 0x0a, 162 0x00, 0xff, 0x01, 0x00, 0x00, 0x34, 0x00, 0x0b, 163 0x00, 0x02, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x0a, 164 0x00, 0x08, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18, 165 0x00, 0x19, 0x00, 0x23, 0x00, 0x00, 0x00, 0x0d, 166 0x00, 0x18, 0x00, 0x16, 0x08, 0x06, 0x06, 0x01, 167 0x06, 0x03, 0x08, 0x05, 0x05, 0x01, 0x05, 0x03, 168 0x08, 0x04, 0x04, 0x01, 0x04, 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 #if 0 206 { 207 .desc = "SSLv23 default", 208 .protocol = TLS1_3_VERSION, 209 .random_start = SSL3_RANDOM_OFFSET, 210 .ssl_method = SSLv23_client_method, 211 .ssl_options = 0, 212 }, 213 #endif 214 { 215 .desc = "SSLv23 default (no TLSv1.3)", 216 .protocol = TLS1_2_VERSION, 217 .random_start = SSL3_RANDOM_OFFSET, 218 .ssl_method = SSLv23_client_method, 219 .ssl_options = SSL_OP_NO_TLSv1_3, 220 }, 221 { 222 .desc = "SSLv23 (no TLSv1.2)", 223 .protocol = TLS1_1_VERSION, 224 .random_start = SSL3_RANDOM_OFFSET, 225 .ssl_method = SSLv23_client_method, 226 .ssl_options = SSL_OP_NO_TLSv1_2, 227 }, 228 { 229 .desc = "SSLv23 (no TLSv1.1)", 230 .protocol = TLS1_VERSION, 231 .random_start = SSL3_RANDOM_OFFSET, 232 .ssl_method = SSLv23_client_method, 233 .ssl_options = SSL_OP_NO_TLSv1_1, 234 }, 235 #if 0 236 { 237 .desc = "TLS default", 238 .protocol = TLS1_3_VERSION, 239 .random_start = SSL3_RANDOM_OFFSET, 240 .ssl_method = TLS_client_method, 241 .ssl_options = 0, 242 }, 243 #endif 244 { 245 .desc = "TLS (no TLSv1.3)", 246 .protocol = TLS1_2_VERSION, 247 .random_start = SSL3_RANDOM_OFFSET, 248 .ssl_method = TLS_client_method, 249 .ssl_options = SSL_OP_NO_TLSv1_3, 250 }, 251 { 252 .desc = "TLS (no TLSv1.2)", 253 .protocol = TLS1_1_VERSION, 254 .random_start = SSL3_RANDOM_OFFSET, 255 .ssl_method = TLS_client_method, 256 .ssl_options = SSL_OP_NO_TLSv1_2, 257 }, 258 { 259 .desc = "TLS (no TLSv1.1)", 260 .protocol = TLS1_VERSION, 261 .random_start = SSL3_RANDOM_OFFSET, 262 .ssl_method = TLS_client_method, 263 .ssl_options = SSL_OP_NO_TLSv1_1, 264 }, 265 #if 0 266 { 267 .desc = "TLS (no TLSv1.0, no TLSv1.1)", 268 .protocol = TLS1_3_VERSION, 269 .random_start = SSL3_RANDOM_OFFSET, 270 .ssl_method = TLS_client_method, 271 .ssl_options = SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1, 272 }, 273 #endif 274 #if 0 275 { 276 .desc = "TLS (no TLSv1.0, no TLSv1.1, no TLSv1.2)", 277 .protocol = TLS1_3_VERSION, 278 .random_start = SSL3_RANDOM_OFFSET, 279 .ssl_method = TLS_client_method, 280 .ssl_options = SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2, 281 }, 282 #endif 283 }; 284 285 #define N_CLIENT_HELLO_TESTS \ 286 (sizeof(client_hello_tests) / sizeof(*client_hello_tests)) 287 288 static void 289 hexdump(const unsigned char *buf, size_t len) 290 { 291 size_t i; 292 293 for (i = 1; i <= len; i++) 294 fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 && i != len ? "" : "\n"); 295 296 fprintf(stderr, "\n"); 297 } 298 299 static inline int 300 ssl_aes_is_accelerated(void) 301 { 302 #if defined(__i386__) || defined(__x86_64__) 303 return ((OPENSSL_cpu_caps() & (1ULL << 57)) != 0); 304 #else 305 return (0); 306 #endif 307 } 308 309 static int 310 make_client_hello(int protocol, char **out, size_t *outlen) 311 { 312 size_t client_hello_len, cipher_list_len, cipher_list_offset; 313 const char *client_hello, *cipher_list; 314 char *p; 315 316 *out = NULL; 317 *outlen = 0; 318 319 switch (protocol) { 320 case DTLS1_VERSION: 321 client_hello = client_hello_dtls1; 322 client_hello_len = sizeof(client_hello_dtls1); 323 cipher_list = cipher_list_dtls1; 324 cipher_list_len = sizeof(cipher_list_dtls1); 325 cipher_list_offset = DTLS_CIPHER_OFFSET; 326 break; 327 328 case TLS1_VERSION: 329 client_hello = client_hello_tls10; 330 client_hello_len = sizeof(client_hello_tls10); 331 cipher_list = cipher_list_tls10; 332 cipher_list_len = sizeof(cipher_list_tls10); 333 cipher_list_offset = SSL3_CIPHER_OFFSET; 334 break; 335 336 case TLS1_1_VERSION: 337 client_hello = client_hello_tls11; 338 client_hello_len = sizeof(client_hello_tls11); 339 cipher_list = cipher_list_tls11; 340 cipher_list_len = sizeof(cipher_list_tls11); 341 cipher_list_offset = SSL3_CIPHER_OFFSET; 342 break; 343 344 case TLS1_2_VERSION: 345 client_hello = client_hello_tls12; 346 client_hello_len = sizeof(client_hello_tls12); 347 if (ssl_aes_is_accelerated()) 348 cipher_list = cipher_list_tls12_aes; 349 else 350 cipher_list = cipher_list_tls12_chacha; 351 cipher_list_len = sizeof(cipher_list_tls12_chacha); 352 cipher_list_offset = SSL3_CIPHER_OFFSET; 353 break; 354 355 default: 356 return (-1); 357 } 358 359 if ((p = malloc(client_hello_len)) == NULL) 360 return (-1); 361 362 memcpy(p, client_hello, client_hello_len); 363 memcpy(p + cipher_list_offset, cipher_list, cipher_list_len); 364 365 *out = p; 366 *outlen = client_hello_len; 367 368 return (0); 369 } 370 371 static int 372 client_hello_test(int testno, struct client_hello_test *cht) 373 { 374 BIO *rbio = NULL, *wbio = NULL; 375 SSL_CTX *ssl_ctx = NULL; 376 SSL *ssl = NULL; 377 char *client_hello = NULL; 378 size_t client_hello_len; 379 char *wbuf, rbuf[1]; 380 int ret = 1; 381 long len; 382 383 fprintf(stderr, "Test %i - %s\n", testno, cht->desc); 384 385 /* Providing a small buf causes *_get_server_hello() to return. */ 386 if ((rbio = BIO_new_mem_buf(rbuf, sizeof(rbuf))) == NULL) { 387 fprintf(stderr, "Failed to setup rbio\n"); 388 goto failure; 389 } 390 if ((wbio = BIO_new(BIO_s_mem())) == NULL) { 391 fprintf(stderr, "Failed to setup wbio\n"); 392 goto failure; 393 } 394 395 if ((ssl_ctx = SSL_CTX_new(cht->ssl_method())) == NULL) { 396 fprintf(stderr, "SSL_CTX_new() returned NULL\n"); 397 goto failure; 398 } 399 400 SSL_CTX_set_options(ssl_ctx, cht->ssl_options); 401 402 if ((ssl = SSL_new(ssl_ctx)) == NULL) { 403 fprintf(stderr, "SSL_new() returned NULL\n"); 404 goto failure; 405 } 406 407 rbio->references = 2; 408 wbio->references = 2; 409 410 SSL_set_bio(ssl, rbio, wbio); 411 412 if (SSL_connect(ssl) != 0) { 413 fprintf(stderr, "SSL_connect() returned non-zero\n"); 414 goto failure; 415 } 416 417 len = BIO_get_mem_data(wbio, &wbuf); 418 419 if (make_client_hello(cht->protocol, &client_hello, 420 &client_hello_len) != 0) 421 errx(1, "failed to make client hello"); 422 423 if ((size_t)len != client_hello_len) { 424 fprintf(stderr, "FAIL: test returned ClientHello length %li, " 425 "want %zu\n", len, client_hello_len); 426 fprintf(stderr, "received:\n"); 427 hexdump(wbuf, len); 428 fprintf(stderr, "test data:\n"); 429 hexdump(client_hello, client_hello_len); 430 fprintf(stderr, "\n"); 431 goto failure; 432 } 433 434 /* We expect the client random to differ. */ 435 if (memcmp(&client_hello[cht->random_start], &wbuf[cht->random_start], 436 SSL3_RANDOM_SIZE) == 0) { 437 fprintf(stderr, "FAIL: ClientHello has zeroed random\n"); 438 goto failure; 439 } 440 441 memset(&wbuf[cht->random_start], 0, SSL3_RANDOM_SIZE); 442 443 if (memcmp(client_hello, wbuf, client_hello_len) != 0) { 444 fprintf(stderr, "FAIL: ClientHello differs:\n"); 445 fprintf(stderr, "received:\n"); 446 hexdump(wbuf, len); 447 fprintf(stderr, "test data:\n"); 448 hexdump(client_hello, client_hello_len); 449 fprintf(stderr, "\n"); 450 goto failure; 451 } 452 453 ret = 0; 454 455 failure: 456 SSL_CTX_free(ssl_ctx); 457 SSL_free(ssl); 458 459 rbio->references = 1; 460 wbio->references = 1; 461 462 BIO_free(rbio); 463 BIO_free(wbio); 464 465 free(client_hello); 466 467 return (ret); 468 } 469 470 int 471 main(int argc, char **argv) 472 { 473 int failed = 0; 474 size_t i; 475 476 SSL_library_init(); 477 478 for (i = 0; i < N_CLIENT_HELLO_TESTS; i++) 479 failed |= client_hello_test(i, &client_hello_tests[i]); 480 481 return (failed); 482 } 483