third_party/boringssl-with-bazel/src/ssl/test/handshaker.cc
Go to the documentation of this file.
1 /* Copyright (c) 2018, 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 <assert.h>
16 #include <errno.h>
17 #include <fcntl.h>
18 #include <signal.h>
19 #include <unistd.h>
20 
21 #include <memory>
22 
23 #include <openssl/bytestring.h>
24 #include <openssl/rand.h>
25 #include <openssl/ssl.h>
26 
27 #include "handshake_util.h"
28 #include "test_config.h"
29 #include "test_state.h"
30 
31 using namespace bssl;
32 
33 namespace {
34 
35 ssize_t read_eintr(int fd, void *out, size_t len) {
36  ssize_t ret;
37  do {
38  ret = read(fd, out, len);
39  } while (ret < 0 && errno == EINTR);
40  return ret;
41 }
42 
43 ssize_t write_eintr(int fd, const void *in, size_t len) {
44  ssize_t ret;
45  do {
46  ret = write(fd, in, len);
47  } while (ret < 0 && errno == EINTR);
48  return ret;
49 }
50 
51 bool HandbackReady(SSL *ssl, int ret) {
52  return ret < 0 && SSL_get_error(ssl, ret) == SSL_ERROR_HANDBACK;
53 }
54 
55 bool Handshaker(const TestConfig *config, int rfd, int wfd,
56  Span<const uint8_t> input, int control) {
57  UniquePtr<SSL_CTX> ctx = config->SetupCtx(/*old_ctx=*/nullptr);
58  if (!ctx) {
59  return false;
60  }
61  UniquePtr<SSL> ssl =
62  config->NewSSL(ctx.get(), /*session=*/nullptr, /*test_state=*/nullptr);
63  if (!ssl) {
64  return false;
65  }
66 
67  // Set |O_NONBLOCK| in order to break out of the loop when we hit
68  // |SSL_ERROR_WANT_READ|, so that we can send |kControlMsgWantRead| to the
69  // proxy.
70  if (fcntl(rfd, F_SETFL, O_NONBLOCK) != 0) {
71  perror("fcntl");
72  return false;
73  }
74  SSL_set_rfd(ssl.get(), rfd);
75  SSL_set_wfd(ssl.get(), wfd);
76 
77  CBS cbs, handoff;
78  CBS_init(&cbs, input.data(), input.size());
79  if (!CBS_get_asn1_element(&cbs, &handoff, CBS_ASN1_SEQUENCE) ||
80  !DeserializeContextState(&cbs, ctx.get()) ||
81  !SetTestState(ssl.get(), TestState::Deserialize(&cbs, ctx.get())) ||
82  !GetTestState(ssl.get()) ||
83  !SSL_apply_handoff(ssl.get(), handoff)) {
84  fprintf(stderr, "Handoff application failed.\n");
85  return false;
86  }
87 
88  int ret = 0;
89  for (;;) {
91  "SSL_do_handshake", ssl.get(),
92  [&]() -> int { return SSL_do_handshake(ssl.get()); });
93  if (SSL_get_error(ssl.get(), ret) == SSL_ERROR_WANT_READ) {
94  // Synchronize with the proxy, i.e. don't let the handshake continue until
95  // the proxy has sent more data.
96  char msg = kControlMsgWantRead;
97  if (write_eintr(control, &msg, 1) != 1 ||
98  read_eintr(control, &msg, 1) != 1 ||
99  msg != kControlMsgWriteCompleted) {
100  fprintf(stderr, "read via proxy failed\n");
101  return false;
102  }
103  continue;
104  }
105  if (!RetryAsync(ssl.get(), ret)) {
106  break;
107  }
108  }
109  if (!HandbackReady(ssl.get(), ret)) {
110  fprintf(stderr, "Handshaker: %s\n",
113  return false;
114  }
115 
116  ScopedCBB output;
117  CBB handback;
118  if (!CBB_init(output.get(), 1024) ||
119  !CBB_add_u24_length_prefixed(output.get(), &handback) ||
120  !SSL_serialize_handback(ssl.get(), &handback) ||
121  !SerializeContextState(ctx.get(), output.get()) ||
122  !GetTestState(ssl.get())->Serialize(output.get())) {
123  fprintf(stderr, "Handback serialisation failed.\n");
124  return false;
125  }
126 
127  char msg = kControlMsgDone;
128  if (write_eintr(control, &msg, 1) == -1 ||
129  write_eintr(control, CBB_data(output.get()), CBB_len(output.get())) ==
130  -1) {
131  perror("write");
132  return false;
133  }
134  return true;
135 }
136 
137 bool GenerateHandshakeHint(const TestConfig *config,
138  bssl::Span<const uint8_t> request, int control) {
139  // The handshake hint contains the ClientHello and the capabilities string.
140  CBS cbs = request;
141  CBS client_hello, capabilities;
142  if (!CBS_get_u24_length_prefixed(&cbs, &client_hello) ||
143  !CBS_get_u24_length_prefixed(&cbs, &capabilities) || //
144  CBS_len(&cbs) != 0) {
145  fprintf(stderr, "Handshaker: Could not parse hint request\n");
146  return false;
147  }
148 
149  UniquePtr<SSL_CTX> ctx = config->SetupCtx(/*old_ctx=*/nullptr);
150  if (!ctx) {
151  return false;
152  }
153 
154  UniquePtr<SSL> ssl =
155  config->NewSSL(ctx.get(), /*session=*/nullptr,
156  std::unique_ptr<TestState>(new TestState));
157  if (!ssl) {
158  return false;
159  }
160 
161  // TODO(davidben): When split handshakes is replaced, move this into |NewSSL|.
162  assert(config->is_server);
163  SSL_set_accept_state(ssl.get());
164 
166  ssl.get(), CBS_data(&client_hello), CBS_len(&client_hello),
167  CBS_data(&capabilities), CBS_len(&capabilities))) {
168  fprintf(stderr, "Handshaker: SSL_request_handshake_hints failed\n");
169  return false;
170  }
171 
172  int ret = 0;
173  do {
174  ret = CheckIdempotentError("SSL_do_handshake", ssl.get(),
175  [&] { return SSL_do_handshake(ssl.get()); });
176  } while (RetryAsync(ssl.get(), ret));
177 
178  if (ret > 0) {
179  fprintf(stderr, "Handshaker: handshake unexpectedly succeeded.\n");
180  return false;
181  }
182 
184  // Errors here may be expected if the test is testing a failing case. The
185  // shim should continue executing without a hint, so we report an error
186  // "successfully". This allows the shim to distinguish this from the other
187  // unexpected error cases.
188  //
189  // We intentionally avoid printing the error in this case, to avoid mixing
190  // up test expectations with errors from the shim.
191  char msg = kControlMsgError;
192  if (write_eintr(control, &msg, 1) == -1) {
193  return false;
194  }
195  return true;
196  }
197 
198  bssl::ScopedCBB hints;
199  if (!CBB_init(hints.get(), 256) ||
200  !SSL_serialize_handshake_hints(ssl.get(), hints.get())) {
201  fprintf(stderr, "Handshaker: failed to serialize handshake hints\n");
202  return false;
203  }
204 
205  char msg = kControlMsgDone;
206  if (write_eintr(control, &msg, 1) == -1 ||
207  write_eintr(control, CBB_data(hints.get()), CBB_len(hints.get())) == -1) {
208  perror("write");
209  return false;
210  }
211 
212  return true;
213 }
214 
215 int SignalError() {
216  const char msg = kControlMsgError;
217  if (write_eintr(kFdControl, &msg, 1) != 1) {
218  return 2;
219  }
220  return 1;
221 }
222 
223 } // namespace
224 
225 int main(int argc, char **argv) {
226  TestConfig initial_config, resume_config, retry_config;
227  if (!ParseConfig(argc - 1, argv + 1, /*is_shim=*/false, &initial_config,
228  &resume_config, &retry_config)) {
229  return SignalError();
230  }
231  const TestConfig *config =
232  initial_config.handshaker_resume ? &resume_config : &initial_config;
233 #if defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE)
234  if (initial_config.handshaker_resume) {
235  // If the PRNG returns exactly the same values when trying to resume then a
236  // "random" session ID will happen to exactly match the session ID
237  // "randomly" generated on the initial connection. The client will thus
238  // incorrectly believe that the server is resuming.
239  uint8_t byte;
240  RAND_bytes(&byte, 1);
241  }
242 #endif // BORINGSSL_UNSAFE_DETERMINISTIC_MODE
243 
244  // read() will return the entire message in one go, because it's a datagram
245  // socket.
246  constexpr size_t kBufSize = 1024 * 1024;
247  std::vector<uint8_t> request(kBufSize);
248  ssize_t len = read_eintr(kFdControl, request.data(), request.size());
249  if (len == -1) {
250  perror("read");
251  return 2;
252  }
253  request.resize(static_cast<size_t>(len));
254 
255  if (config->handshake_hints) {
256  if (!GenerateHandshakeHint(config, request, kFdControl)) {
257  return SignalError();
258  }
259  } else {
260  if (!Handshaker(config, kFdProxyToHandshaker, kFdHandshakerToProxy,
261  request, kFdControl)) {
262  return SignalError();
263  }
264  }
265  return 0;
266 }
main
int main(int argc, char **argv)
Definition: third_party/boringssl-with-bazel/src/ssl/test/handshaker.cc:225
CBS_get_u24_length_prefixed
#define CBS_get_u24_length_prefixed
Definition: boringssl_prefix_symbols.h:1077
CBB_data
#define CBB_data
Definition: boringssl_prefix_symbols.h:1040
CBB_init
#define CBB_init
Definition: boringssl_prefix_symbols.h:1047
gen_build_yaml.out
dictionary out
Definition: src/benchmark/gen_build_yaml.py:24
RAND_bytes
#define RAND_bytes
Definition: boringssl_prefix_symbols.h:2060
cbs_st
Definition: bytestring.h:39
SSL_request_handshake_hints
#define SSL_request_handshake_hints
Definition: boringssl_prefix_symbols.h:427
ctx
Definition: benchmark-async.c:30
GetTestState
TestState * GetTestState(const SSL *ssl)
Definition: test_state.cc:62
TestState::Serialize
bool Serialize(CBB *out) const
Definition: test_state.cc:130
CBS_data
#define CBS_data
Definition: boringssl_prefix_symbols.h:1057
SSL_set_accept_state
#define SSL_set_accept_state
Definition: boringssl_prefix_symbols.h:450
test_state.h
write
#define write
Definition: test-fs.c:47
SSL_ERROR_WANT_READ
#define SSL_ERROR_WANT_READ
Definition: ssl.h:494
benchmark.request
request
Definition: benchmark.py:77
ERR_print_errors_fp
#define ERR_print_errors_fp
Definition: boringssl_prefix_symbols.h:1437
CBS_len
#define CBS_len
Definition: boringssl_prefix_symbols.h:1089
SerializeContextState
bool SerializeContextState(SSL_CTX *ctx, CBB *cbb)
Definition: test_state.cc:85
bssl
Definition: hpke_test.cc:37
cbs
const CBS * cbs
Definition: third_party/boringssl-with-bazel/src/crypto/trust_token/internal.h:107
CBS_init
#define CBS_init
Definition: boringssl_prefix_symbols.h:1085
TestConfig
Definition: third_party/boringssl-with-bazel/src/ssl/test/test_config.h:27
uint8_t
unsigned char uint8_t
Definition: stdint-msvc2008.h:78
test_config.h
TestConfig::handshaker_resume
bool handshaker_resume
Definition: third_party/boringssl-with-bazel/src/ssl/test/test_config.h:186
python_utils.port_server.stderr
stderr
Definition: port_server.py:51
TestState::Deserialize
static std::unique_ptr< TestState > Deserialize(CBS *cbs, SSL_CTX *ctx)
Definition: test_state.cc:149
ParseConfig
bool ParseConfig(int argc, char **argv, bool is_shim, TestConfig *out_initial, TestConfig *out_resume, TestConfig *out_retry)
Definition: third_party/boringssl-with-bazel/src/ssl/test/test_config.cc:428
bytestring.h
in
const char * in
Definition: third_party/abseil-cpp/absl/strings/internal/str_format/parser_test.cc:391
ssize_t
intptr_t ssize_t
Definition: win.h:27
SSL_get_error
#define SSL_get_error
Definition: boringssl_prefix_symbols.h:340
config
struct config_s config
gmock_output_test.output
output
Definition: bloaty/third_party/googletest/googlemock/test/gmock_output_test.py:175
ssl_st
Definition: third_party/boringssl-with-bazel/src/ssl/internal.h:3698
SSL_ERROR_HANDBACK
#define SSL_ERROR_HANDBACK
Definition: ssl.h:580
handshake_util.h
TestState
Definition: test_state.h:27
SSL_error_description
#define SSL_error_description
Definition: boringssl_prefix_symbols.h:306
Span< const uint8_t >
msg
std::string msg
Definition: client_interceptors_end2end_test.cc:372
SSL_ERROR_HANDSHAKE_HINTS_READY
#define SSL_ERROR_HANDSHAKE_HINTS_READY
Definition: ssl.h:592
RetryAsync
bool RetryAsync(SSL *ssl, int ret)
Definition: handshake_util.cc:43
ssl.h
SSL_serialize_handshake_hints
#define SSL_serialize_handshake_hints
Definition: boringssl_prefix_symbols.h:432
SetTestState
bool SetTestState(SSL *ssl, std::unique_ptr< TestState > state)
Definition: test_state.cc:52
ares::byte
unsigned char byte
Definition: ares-test.h:33
read
int read(izstream &zs, T *x, Items items)
Definition: bloaty/third_party/zlib/contrib/iostream2/zstream.h:115
rand.h
SSL_set_wfd
#define SSL_set_wfd
Definition: boringssl_prefix_symbols.h:514
ret
UniquePtr< SSL_SESSION > ret
Definition: ssl_x509.cc:1029
SSL_set_rfd
#define SSL_set_rfd
Definition: boringssl_prefix_symbols.h:490
SSL_apply_handoff
bool SSL_apply_handoff(SSL *ssl, Span< const uint8_t > handoff)
Definition: handoff.cc:238
input
std::string input
Definition: bloaty/third_party/protobuf/src/google/protobuf/io/tokenizer_unittest.cc:197
CBB_len
#define CBB_len
Definition: boringssl_prefix_symbols.h:1049
CBS_get_asn1_element
#define CBS_get_asn1_element
Definition: boringssl_prefix_symbols.h:1063
len
int len
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:46
CBS_ASN1_SEQUENCE
#define CBS_ASN1_SEQUENCE
Definition: bytestring.h:214
SSL_serialize_handback
bool SSL_serialize_handback(const SSL *ssl, CBB *out)
Definition: handoff.cc:279
DeserializeContextState
bool DeserializeContextState(CBS *cbs, SSL_CTX *ctx)
Definition: test_state.cc:106
errno.h
CheckIdempotentError
int CheckIdempotentError(const char *name, SSL *ssl, std::function< int()> func)
Definition: handshake_util.cc:109
cbb_st
Definition: bytestring.h:375
CBB_add_u24_length_prefixed
#define CBB_add_u24_length_prefixed
Definition: boringssl_prefix_symbols.h:1031


grpc
Author(s):
autogenerated on Fri May 16 2025 02:59:00