Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / boringssl / src / ssl / test / bssl_shim.cc
1 /* Copyright (c) 2014, Google Inc.
2  *
3  * Permission to use, copy, modify, and/or distribute this software for any
4  * purpose with or without fee is hereby granted, provided that the above
5  * copyright notice and this permission notice appear in all copies.
6  *
7  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14
15 #include <arpa/inet.h>
16 #include <netinet/in.h>
17 #include <signal.h>
18 #include <sys/socket.h>
19 #include <sys/types.h>
20 #include <unistd.h>
21
22 #include <openssl/bio.h>
23 #include <openssl/bytestring.h>
24 #include <openssl/ssl.h>
25
26 #include "async_bio.h"
27
28 static int usage(const char *program) {
29   fprintf(stderr, "Usage: %s (client|server) (normal|resume) [flags...]\n",
30           program);
31   return 1;
32 }
33
34 static const char *expected_server_name = NULL;
35 static int early_callback_called = 0;
36
37 static int select_certificate_callback(const struct ssl_early_callback_ctx *ctx) {
38   early_callback_called = 1;
39
40   if (!expected_server_name) {
41     return 1;
42   }
43
44   const uint8_t *extension_data;
45   size_t extension_len;
46   CBS extension, server_name_list, host_name;
47   uint8_t name_type;
48
49   if (!SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
50                                             &extension_data,
51                                             &extension_len)) {
52     fprintf(stderr, "Could not find server_name extension.\n");
53     return -1;
54   }
55
56   CBS_init(&extension, extension_data, extension_len);
57   if (!CBS_get_u16_length_prefixed(&extension, &server_name_list) ||
58       CBS_len(&extension) != 0 ||
59       !CBS_get_u8(&server_name_list, &name_type) ||
60       name_type != TLSEXT_NAMETYPE_host_name ||
61       !CBS_get_u16_length_prefixed(&server_name_list, &host_name) ||
62       CBS_len(&server_name_list) != 0) {
63     fprintf(stderr, "Could not decode server_name extension.\n");
64     return -1;
65   }
66
67   if (!CBS_mem_equal(&host_name, (const uint8_t*)expected_server_name,
68                      strlen(expected_server_name))) {
69     fprintf(stderr, "Server name mismatch.\n");
70   }
71
72   return 1;
73 }
74
75 static int skip_verify(int preverify_ok, X509_STORE_CTX *store_ctx) {
76   return 1;
77 }
78
79 static const char *advertise_npn = NULL;
80
81 static int next_protos_advertised_callback(SSL *ssl,
82                                            const uint8_t **out,
83                                            unsigned int *out_len,
84                                            void *arg) {
85   if (!advertise_npn)
86     return SSL_TLSEXT_ERR_NOACK;
87
88   // TODO(davidben): Support passing byte strings with NULs to the
89   // test shim.
90   *out = (const uint8_t*)advertise_npn;
91   *out_len = strlen(advertise_npn);
92   return SSL_TLSEXT_ERR_OK;
93 }
94
95 static const char *select_next_proto = NULL;
96
97 static int next_proto_select_callback(SSL* ssl,
98                                       uint8_t** out,
99                                       uint8_t* outlen,
100                                       const uint8_t* in,
101                                       unsigned inlen,
102                                       void* arg) {
103   if (!select_next_proto)
104     return SSL_TLSEXT_ERR_NOACK;
105
106   *out = (uint8_t*)select_next_proto;
107   *outlen = strlen(select_next_proto);
108   return SSL_TLSEXT_ERR_OK;
109 }
110
111 static SSL_CTX *setup_ctx(int is_server) {
112   if (!SSL_library_init()) {
113     return NULL;
114   }
115
116   SSL_CTX *ssl_ctx = NULL;
117   DH *dh = NULL;
118
119   ssl_ctx = SSL_CTX_new(
120       is_server ? SSLv23_server_method() : SSLv23_client_method());
121   if (ssl_ctx == NULL) {
122     goto err;
123   }
124
125   if (!SSL_CTX_set_ecdh_auto(ssl_ctx, 1)) {
126     goto err;
127   }
128
129   if (!SSL_CTX_set_cipher_list(ssl_ctx, "ALL")) {
130     goto err;
131   }
132
133   dh = DH_get_2048_256(NULL);
134   if (!SSL_CTX_set_tmp_dh(ssl_ctx, dh)) {
135     goto err;
136   }
137
138   SSL_CTX_set_session_cache_mode(ssl_ctx, SSL_SESS_CACHE_BOTH);
139
140   ssl_ctx->select_certificate_cb = select_certificate_callback;
141
142   SSL_CTX_set_next_protos_advertised_cb(
143       ssl_ctx, next_protos_advertised_callback, NULL);
144   SSL_CTX_set_next_proto_select_cb(
145       ssl_ctx, next_proto_select_callback, NULL);
146
147   DH_free(dh);
148   return ssl_ctx;
149
150  err:
151   if (dh != NULL) {
152     DH_free(dh);
153   }
154   if (ssl_ctx != NULL) {
155     SSL_CTX_free(ssl_ctx);
156   }
157   return NULL;
158 }
159
160 static int retry_async(SSL *ssl, int ret, BIO *bio) {
161   // No error; don't retry.
162   if (ret >= 0) {
163     return 0;
164   }
165   // See if we needed to read or write more. If so, allow one byte through on
166   // the appropriate end to maximally stress the state machine.
167   int err = SSL_get_error(ssl, ret);
168   if (err == SSL_ERROR_WANT_READ) {
169     async_bio_allow_read(bio, 1);
170     return 1;
171   } else if (err == SSL_ERROR_WANT_WRITE) {
172     async_bio_allow_write(bio, 1);
173     return 1;
174   }
175   return 0;
176 }
177
178 static int do_exchange(SSL_SESSION **out_session,
179                        SSL_CTX *ssl_ctx,
180                        int argc,
181                        char **argv,
182                        int is_server,
183                        int is_resume,
184                        int fd,
185                        SSL_SESSION *session) {
186   bool async = false, write_different_record_sizes = false;
187   const char *expected_certificate_types = NULL;
188   const char *expected_next_proto = NULL;
189   expected_server_name = NULL;
190   early_callback_called = 0;
191   advertise_npn = NULL;
192
193   SSL *ssl = SSL_new(ssl_ctx);
194   if (ssl == NULL) {
195     BIO_print_errors_fp(stdout);
196     return 1;
197   }
198
199   for (int i = 0; i < argc; i++) {
200     if (strcmp(argv[i], "-fallback-scsv") == 0) {
201       if (!SSL_enable_fallback_scsv(ssl)) {
202         BIO_print_errors_fp(stdout);
203         return 1;
204       }
205     } else if (strcmp(argv[i], "-key-file") == 0) {
206       i++;
207       if (i >= argc) {
208         fprintf(stderr, "Missing parameter\n");
209         return 1;
210       }
211       if (!SSL_use_PrivateKey_file(ssl, argv[i], SSL_FILETYPE_PEM)) {
212         BIO_print_errors_fp(stdout);
213         return 1;
214       }
215     } else if (strcmp(argv[i], "-cert-file") == 0) {
216       i++;
217       if (i >= argc) {
218         fprintf(stderr, "Missing parameter\n");
219         return 1;
220       }
221       if (!SSL_use_certificate_file(ssl, argv[i], SSL_FILETYPE_PEM)) {
222         BIO_print_errors_fp(stdout);
223         return 1;
224       }
225     } else if (strcmp(argv[i], "-expect-server-name") == 0) {
226       i++;
227       if (i >= argc) {
228         fprintf(stderr, "Missing parameter\n");
229         return 1;
230       }
231       expected_server_name = argv[i];
232     } else if (strcmp(argv[i], "-expect-certificate-types") == 0) {
233       i++;
234       if (i >= argc) {
235         fprintf(stderr, "Missing parameter\n");
236         return 1;
237       }
238       // Conveniently, 00 is not a certificate type.
239       expected_certificate_types = argv[i];
240     } else if (strcmp(argv[i], "-require-any-client-certificate") == 0) {
241       SSL_set_verify(ssl, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
242                      skip_verify);
243     } else if (strcmp(argv[i], "-advertise-npn") == 0) {
244       i++;
245       if (i >= argc) {
246         fprintf(stderr, "Missing parameter\n");
247         return 1;
248       }
249       advertise_npn = argv[i];
250     } else if (strcmp(argv[i], "-expect-next-proto") == 0) {
251       i++;
252       if (i >= argc) {
253         fprintf(stderr, "Missing parameter\n");
254         return 1;
255       }
256       expected_next_proto = argv[i];
257     } else if (strcmp(argv[i], "-false-start") == 0) {
258       SSL_set_mode(ssl, SSL_MODE_HANDSHAKE_CUTTHROUGH);
259     } else if (strcmp(argv[i], "-select-next-proto") == 0) {
260       i++;
261       if (i >= argc) {
262         fprintf(stderr, "Missing parameter\n");
263         return 1;
264       }
265       select_next_proto = argv[i];
266     } else if (strcmp(argv[i], "-async") == 0) {
267       async = true;
268     } else if (strcmp(argv[i], "-write-different-record-sizes") == 0) {
269       write_different_record_sizes = true;
270     } else if (strcmp(argv[i], "-cbc-record-splitting") == 0) {
271       SSL_set_mode(ssl, SSL_MODE_CBC_RECORD_SPLITTING);
272     } else if (strcmp(argv[i], "-partial-write") == 0) {
273       SSL_set_mode(ssl, SSL_MODE_ENABLE_PARTIAL_WRITE);
274     } else {
275       fprintf(stderr, "Unknown argument: %s\n", argv[i]);
276       return 1;
277     }
278   }
279
280   BIO *bio = BIO_new_fd(fd, 1 /* take ownership */);
281   if (bio == NULL) {
282     BIO_print_errors_fp(stdout);
283     return 1;
284   }
285   if (async) {
286     BIO *async = async_bio_create();
287     BIO_push(async, bio);
288     bio = async;
289   }
290   SSL_set_bio(ssl, bio, bio);
291
292   if (session != NULL) {
293     if (SSL_set_session(ssl, session) != 1) {
294       fprintf(stderr, "failed to set session\n");
295       return 2;
296     }
297   }
298
299   int ret;
300   do {
301     if (is_server) {
302       ret = SSL_accept(ssl);
303     } else {
304       ret = SSL_connect(ssl);
305     }
306   } while (async && retry_async(ssl, ret, bio));
307   if (ret != 1) {
308     SSL_free(ssl);
309     BIO_print_errors_fp(stdout);
310     return 2;
311   }
312
313   if (is_resume && !SSL_session_reused(ssl)) {
314     fprintf(stderr, "session was not reused\n");
315     return 2;
316   }
317
318   if (expected_server_name) {
319     const char *server_name =
320         SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
321     if (strcmp(server_name, expected_server_name) != 0) {
322       fprintf(stderr, "servername mismatch (got %s; want %s)\n",
323               server_name, expected_server_name);
324       return 2;
325     }
326
327     if (!early_callback_called) {
328       fprintf(stderr, "early callback not called\n");
329       return 2;
330     }
331   }
332
333   if (expected_certificate_types) {
334     uint8_t *certificate_types;
335     int num_certificate_types =
336       SSL_get0_certificate_types(ssl, &certificate_types);
337     if (num_certificate_types != (int)strlen(expected_certificate_types) ||
338         memcmp(certificate_types,
339                expected_certificate_types,
340                num_certificate_types) != 0) {
341       fprintf(stderr, "certificate types mismatch\n");
342       return 2;
343     }
344   }
345
346   if (expected_next_proto) {
347     const uint8_t *next_proto;
348     unsigned next_proto_len;
349     SSL_get0_next_proto_negotiated(ssl, &next_proto, &next_proto_len);
350     if (next_proto_len != strlen(expected_next_proto) ||
351         memcmp(next_proto, expected_next_proto, next_proto_len) != 0) {
352       fprintf(stderr, "negotiated next proto mismatch\n");
353       return 2;
354     }
355   }
356
357   if (write_different_record_sizes) {
358     // This mode writes a number of different record sizes in an attempt to
359     // trip up the CBC record splitting code.
360     uint8_t buf[32769];
361     memset(buf, 0x42, sizeof(buf));
362     static const size_t kRecordSizes[] = {
363         0, 1, 255, 256, 257, 16383, 16384, 16385, 32767, 32768, 32769};
364     for (size_t i = 0; i < sizeof(kRecordSizes) / sizeof(kRecordSizes[0]);
365          i++) {
366       int w;
367       const size_t len = kRecordSizes[i];
368       size_t off = 0;
369
370       if (len > sizeof(buf)) {
371         fprintf(stderr, "Bad kRecordSizes value.\n");
372         return 5;
373       }
374
375       do {
376         w = SSL_write(ssl, buf + off, len - off);
377         if (w > 0) {
378           off += (size_t) w;
379         }
380       } while ((async && retry_async(ssl, w, bio)) || (w > 0 && off < len));
381
382       if (w < 0 || off != len) {
383         SSL_free(ssl);
384         BIO_print_errors_fp(stdout);
385         return 4;
386       }
387     }
388   } else {
389     for (;;) {
390       uint8_t buf[512];
391       int n;
392       do {
393         n = SSL_read(ssl, buf, sizeof(buf));
394       } while (async && retry_async(ssl, n, bio));
395       if (n < 0) {
396         SSL_free(ssl);
397         BIO_print_errors_fp(stdout);
398         return 3;
399       } else if (n == 0) {
400         break;
401       } else {
402         for (int i = 0; i < n; i++) {
403           buf[i] ^= 0xff;
404         }
405         int w;
406         do {
407           w = SSL_write(ssl, buf, n);
408         } while (async && retry_async(ssl, w, bio));
409         if (w != n) {
410           SSL_free(ssl);
411           BIO_print_errors_fp(stdout);
412           return 4;
413         }
414       }
415     }
416   }
417
418   if (out_session) {
419     *out_session = SSL_get1_session(ssl);
420   }
421
422   SSL_shutdown(ssl);
423   SSL_free(ssl);
424   return 0;
425 }
426
427 int main(int argc, char **argv) {
428   int is_server, resume;
429
430   signal(SIGPIPE, SIG_IGN);
431
432   if (argc < 3) {
433     return usage(argv[0]);
434   }
435
436   if (strcmp(argv[1], "client") == 0) {
437     is_server = 0;
438   } else if (strcmp(argv[1], "server") == 0) {
439     is_server = 1;
440   } else {
441     return usage(argv[0]);
442   }
443
444   if (strcmp(argv[2], "normal") == 0) {
445     resume = 0;
446   } else if (strcmp(argv[2], "resume") == 0) {
447     resume = 1;
448   } else {
449     return usage(argv[0]);
450   }
451
452   SSL_CTX *ssl_ctx = setup_ctx(is_server);
453   if (ssl_ctx == NULL) {
454     BIO_print_errors_fp(stdout);
455     return 1;
456   }
457
458   SSL_SESSION *session;
459   int ret = do_exchange(&session,
460                         ssl_ctx,
461                         argc - 3, argv + 3,
462                         is_server, 0 /* is_resume */,
463                         3 /* fd */, NULL /* session */);
464   if (ret != 0) {
465     return ret;
466   }
467
468   if (resume) {
469     int ret = do_exchange(NULL,
470                           ssl_ctx, argc - 3, argv + 3,
471                           is_server, 1 /* is_resume */,
472                           4 /* fd */,
473                           is_server ? NULL : session);
474     if (ret != 0) {
475       return ret;
476     }
477   }
478
479   SSL_SESSION_free(session);
480   SSL_CTX_free(ssl_ctx);
481   return 0;
482 }