|
|
|
/* Copyright (c) 2014, Google Inc.
|
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
* copyright notice and this permission notice appear in all copies.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
|
|
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
|
|
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
|
|
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
|
|
|
|
|
|
|
#include "test_config.h"
|
|
|
|
|
|
|
|
#include <assert.h>
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
#include <ctype.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
#include <algorithm>
|
|
|
|
#include <functional>
|
|
|
|
#include <limits>
|
|
|
|
#include <memory>
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
#include <type_traits>
|
|
|
|
|
|
|
|
#include <openssl/base64.h>
|
|
|
|
#include <openssl/hmac.h>
|
|
|
|
#include <openssl/hpke.h>
|
|
|
|
#include <openssl/rand.h>
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
#include <openssl/span.h>
|
|
|
|
#include <openssl/ssl.h>
|
|
|
|
|
|
|
|
#include "../../crypto/internal.h"
|
|
|
|
#include "../internal.h"
|
|
|
|
#include "handshake_util.h"
|
|
|
|
#include "mock_quic_transport.h"
|
|
|
|
#include "test_state.h"
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
struct Flag {
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
const char *name;
|
|
|
|
bool has_param;
|
Pass IPv6 vs IPv4 down to the shim
The runner currently tries to listen on IPv6 and then falls back to IPv4
on error. The shim does the same. If they pick different ones, this
breaks down.
Normally, fallback happens because the system doesn't have IPv6, and
both sides will make the same decision. But if binding to IPv6 fails for
other reasons, they may mismatch. We're observing them fail due to what
seems to port exhaustion. When this happens, shim and runner don't
agree on the same address family.
Instead, just tell the shim which address to connect to. This doesn't
fix the underlying port exhaustion problem, but it does seem to fix the
flakes. Although given we are still exhausting ports and falling back to
IPv4, it doesn't truly fix it. Later CLs will address port exhaustion by
using a single server port.
This changes the runner <-> shim protocol, but hopefully in a fairly
obvious way that others using BoGo can easily follow. It shouldn't break
our cross-version tests because we keep runner and shim at the same
versio there.
To avoid needing to make an incompatible change to the shim <->
handshaker protocol, which would impact our cross-version tests, this
introduces a mechanism for the shim omit flags when talking to the
handshaker. The handshaker doesn't need to know how to connect to the
runner.
Also print the error string on Windows. Sadly this is a bit tedious.
Change-Id: Ic8bda9a854a115c206c05a659a2e34f544b844a6
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/60885
Auto-Submit: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
1 year ago
|
|
|
// skip_handshaker, if true, causes this flag to be skipped when
|
|
|
|
// forwarding flags to the handshaker. This should be used with flags
|
|
|
|
// that only impact connecting to the runner.
|
|
|
|
bool skip_handshaker;
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
// If |has_param| is false, |param| will be nullptr.
|
|
|
|
std::function<bool(TestConfig *config, const char *param)> set_param;
|
|
|
|
};
|
|
|
|
|
Pass IPv6 vs IPv4 down to the shim
The runner currently tries to listen on IPv6 and then falls back to IPv4
on error. The shim does the same. If they pick different ones, this
breaks down.
Normally, fallback happens because the system doesn't have IPv6, and
both sides will make the same decision. But if binding to IPv6 fails for
other reasons, they may mismatch. We're observing them fail due to what
seems to port exhaustion. When this happens, shim and runner don't
agree on the same address family.
Instead, just tell the shim which address to connect to. This doesn't
fix the underlying port exhaustion problem, but it does seem to fix the
flakes. Although given we are still exhausting ports and falling back to
IPv4, it doesn't truly fix it. Later CLs will address port exhaustion by
using a single server port.
This changes the runner <-> shim protocol, but hopefully in a fairly
obvious way that others using BoGo can easily follow. It shouldn't break
our cross-version tests because we keep runner and shim at the same
versio there.
To avoid needing to make an incompatible change to the shim <->
handshaker protocol, which would impact our cross-version tests, this
introduces a mechanism for the shim omit flags when talking to the
handshaker. The handshaker doesn't need to know how to connect to the
runner.
Also print the error string on Windows. Sadly this is a bit tedious.
Change-Id: Ic8bda9a854a115c206c05a659a2e34f544b844a6
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/60885
Auto-Submit: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
1 year ago
|
|
|
Flag BoolFlag(const char *name, bool TestConfig::*field,
|
|
|
|
bool skip_handshaker = false) {
|
|
|
|
return Flag{name, false, skip_handshaker,
|
|
|
|
[=](TestConfig *config, const char *) -> bool {
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
config->*field = true;
|
|
|
|
return true;
|
|
|
|
}};
|
|
|
|
}
|
|
|
|
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
template <typename T>
|
|
|
|
bool StringToInt(T *out, const char *str) {
|
|
|
|
static_assert(std::is_integral<T>::value, "not an integral type");
|
|
|
|
|
|
|
|
// |strtoull| allows leading '-' with wraparound. Additionally, both
|
|
|
|
// functions accept empty strings and leading whitespace.
|
|
|
|
if (!OPENSSL_isdigit(static_cast<unsigned char>(*str)) &&
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
(!std::is_signed<T>::value || *str != '-')) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
errno = 0;
|
|
|
|
char *end;
|
|
|
|
if (std::is_signed<T>::value) {
|
|
|
|
static_assert(sizeof(T) <= sizeof(long long),
|
|
|
|
"type too large for long long");
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
long long value = strtoll(str, &end, 10);
|
|
|
|
if (value < static_cast<long long>(std::numeric_limits<T>::min()) ||
|
|
|
|
value > static_cast<long long>(std::numeric_limits<T>::max())) {
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
return false;
|
|
|
|
}
|
|
|
|
*out = static_cast<T>(value);
|
|
|
|
} else {
|
|
|
|
static_assert(sizeof(T) <= sizeof(unsigned long long),
|
|
|
|
"type too large for unsigned long long");
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
unsigned long long value = strtoull(str, &end, 10);
|
|
|
|
if (value >
|
|
|
|
static_cast<unsigned long long>(std::numeric_limits<T>::max())) {
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
return false;
|
|
|
|
}
|
|
|
|
*out = static_cast<T>(value);
|
|
|
|
}
|
|
|
|
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
// Check for overflow and that the whole input was consumed.
|
|
|
|
return errno != ERANGE && *end == '\0';
|
|
|
|
}
|
|
|
|
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
template <typename T>
|
Pass IPv6 vs IPv4 down to the shim
The runner currently tries to listen on IPv6 and then falls back to IPv4
on error. The shim does the same. If they pick different ones, this
breaks down.
Normally, fallback happens because the system doesn't have IPv6, and
both sides will make the same decision. But if binding to IPv6 fails for
other reasons, they may mismatch. We're observing them fail due to what
seems to port exhaustion. When this happens, shim and runner don't
agree on the same address family.
Instead, just tell the shim which address to connect to. This doesn't
fix the underlying port exhaustion problem, but it does seem to fix the
flakes. Although given we are still exhausting ports and falling back to
IPv4, it doesn't truly fix it. Later CLs will address port exhaustion by
using a single server port.
This changes the runner <-> shim protocol, but hopefully in a fairly
obvious way that others using BoGo can easily follow. It shouldn't break
our cross-version tests because we keep runner and shim at the same
versio there.
To avoid needing to make an incompatible change to the shim <->
handshaker protocol, which would impact our cross-version tests, this
introduces a mechanism for the shim omit flags when talking to the
handshaker. The handshaker doesn't need to know how to connect to the
runner.
Also print the error string on Windows. Sadly this is a bit tedious.
Change-Id: Ic8bda9a854a115c206c05a659a2e34f544b844a6
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/60885
Auto-Submit: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
1 year ago
|
|
|
Flag IntFlag(const char *name, T TestConfig::*field,
|
|
|
|
bool skip_handshaker = false) {
|
|
|
|
return Flag{name, true, skip_handshaker,
|
|
|
|
[=](TestConfig *config, const char *param) -> bool {
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
return StringToInt(&(config->*field), param);
|
|
|
|
}};
|
|
|
|
}
|
|
|
|
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
template <typename T>
|
Pass IPv6 vs IPv4 down to the shim
The runner currently tries to listen on IPv6 and then falls back to IPv4
on error. The shim does the same. If they pick different ones, this
breaks down.
Normally, fallback happens because the system doesn't have IPv6, and
both sides will make the same decision. But if binding to IPv6 fails for
other reasons, they may mismatch. We're observing them fail due to what
seems to port exhaustion. When this happens, shim and runner don't
agree on the same address family.
Instead, just tell the shim which address to connect to. This doesn't
fix the underlying port exhaustion problem, but it does seem to fix the
flakes. Although given we are still exhausting ports and falling back to
IPv4, it doesn't truly fix it. Later CLs will address port exhaustion by
using a single server port.
This changes the runner <-> shim protocol, but hopefully in a fairly
obvious way that others using BoGo can easily follow. It shouldn't break
our cross-version tests because we keep runner and shim at the same
versio there.
To avoid needing to make an incompatible change to the shim <->
handshaker protocol, which would impact our cross-version tests, this
introduces a mechanism for the shim omit flags when talking to the
handshaker. The handshaker doesn't need to know how to connect to the
runner.
Also print the error string on Windows. Sadly this is a bit tedious.
Change-Id: Ic8bda9a854a115c206c05a659a2e34f544b844a6
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/60885
Auto-Submit: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
1 year ago
|
|
|
Flag IntVectorFlag(const char *name, std::vector<T> TestConfig::*field,
|
|
|
|
bool skip_handshaker = false) {
|
|
|
|
return Flag{name, true, skip_handshaker,
|
|
|
|
[=](TestConfig *config, const char *param) -> bool {
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
T value;
|
|
|
|
if (!StringToInt(&value, param)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
(config->*field).push_back(value);
|
|
|
|
return true;
|
|
|
|
}};
|
|
|
|
}
|
|
|
|
|
Pass IPv6 vs IPv4 down to the shim
The runner currently tries to listen on IPv6 and then falls back to IPv4
on error. The shim does the same. If they pick different ones, this
breaks down.
Normally, fallback happens because the system doesn't have IPv6, and
both sides will make the same decision. But if binding to IPv6 fails for
other reasons, they may mismatch. We're observing them fail due to what
seems to port exhaustion. When this happens, shim and runner don't
agree on the same address family.
Instead, just tell the shim which address to connect to. This doesn't
fix the underlying port exhaustion problem, but it does seem to fix the
flakes. Although given we are still exhausting ports and falling back to
IPv4, it doesn't truly fix it. Later CLs will address port exhaustion by
using a single server port.
This changes the runner <-> shim protocol, but hopefully in a fairly
obvious way that others using BoGo can easily follow. It shouldn't break
our cross-version tests because we keep runner and shim at the same
versio there.
To avoid needing to make an incompatible change to the shim <->
handshaker protocol, which would impact our cross-version tests, this
introduces a mechanism for the shim omit flags when talking to the
handshaker. The handshaker doesn't need to know how to connect to the
runner.
Also print the error string on Windows. Sadly this is a bit tedious.
Change-Id: Ic8bda9a854a115c206c05a659a2e34f544b844a6
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/60885
Auto-Submit: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
1 year ago
|
|
|
Flag StringFlag(const char *name, std::string TestConfig::*field,
|
|
|
|
bool skip_handshaker = false) {
|
|
|
|
return Flag{name, true, skip_handshaker,
|
|
|
|
[=](TestConfig *config, const char *param) -> bool {
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
config->*field = param;
|
|
|
|
return true;
|
|
|
|
}};
|
|
|
|
}
|
|
|
|
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
// TODO(davidben): When we can depend on C++17 or Abseil, switch this to
|
|
|
|
// std::optional or absl::optional.
|
|
|
|
Flag OptionalStringFlag(const char *name,
|
Pass IPv6 vs IPv4 down to the shim
The runner currently tries to listen on IPv6 and then falls back to IPv4
on error. The shim does the same. If they pick different ones, this
breaks down.
Normally, fallback happens because the system doesn't have IPv6, and
both sides will make the same decision. But if binding to IPv6 fails for
other reasons, they may mismatch. We're observing them fail due to what
seems to port exhaustion. When this happens, shim and runner don't
agree on the same address family.
Instead, just tell the shim which address to connect to. This doesn't
fix the underlying port exhaustion problem, but it does seem to fix the
flakes. Although given we are still exhausting ports and falling back to
IPv4, it doesn't truly fix it. Later CLs will address port exhaustion by
using a single server port.
This changes the runner <-> shim protocol, but hopefully in a fairly
obvious way that others using BoGo can easily follow. It shouldn't break
our cross-version tests because we keep runner and shim at the same
versio there.
To avoid needing to make an incompatible change to the shim <->
handshaker protocol, which would impact our cross-version tests, this
introduces a mechanism for the shim omit flags when talking to the
handshaker. The handshaker doesn't need to know how to connect to the
runner.
Also print the error string on Windows. Sadly this is a bit tedious.
Change-Id: Ic8bda9a854a115c206c05a659a2e34f544b844a6
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/60885
Auto-Submit: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
1 year ago
|
|
|
std::unique_ptr<std::string> TestConfig::*field,
|
|
|
|
bool skip_handshaker = false) {
|
|
|
|
return Flag{name, true, skip_handshaker,
|
|
|
|
[=](TestConfig *config, const char *param) -> bool {
|
|
|
|
(config->*field) = std::make_unique<std::string>(param);
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
return true;
|
|
|
|
}};
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DecodeBase64(std::string *out, const std::string &in) {
|
|
|
|
size_t len;
|
|
|
|
if (!EVP_DecodedLength(&len, in.size())) {
|
|
|
|
fprintf(stderr, "Invalid base64: %s.\n", in.c_str());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
std::vector<uint8_t> buf(len);
|
|
|
|
if (!EVP_DecodeBase64(buf.data(), &len, buf.size(),
|
|
|
|
reinterpret_cast<const uint8_t *>(in.data()),
|
|
|
|
in.size())) {
|
|
|
|
fprintf(stderr, "Invalid base64: %s.\n", in.c_str());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
out->assign(reinterpret_cast<const char *>(buf.data()), len);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
Pass IPv6 vs IPv4 down to the shim
The runner currently tries to listen on IPv6 and then falls back to IPv4
on error. The shim does the same. If they pick different ones, this
breaks down.
Normally, fallback happens because the system doesn't have IPv6, and
both sides will make the same decision. But if binding to IPv6 fails for
other reasons, they may mismatch. We're observing them fail due to what
seems to port exhaustion. When this happens, shim and runner don't
agree on the same address family.
Instead, just tell the shim which address to connect to. This doesn't
fix the underlying port exhaustion problem, but it does seem to fix the
flakes. Although given we are still exhausting ports and falling back to
IPv4, it doesn't truly fix it. Later CLs will address port exhaustion by
using a single server port.
This changes the runner <-> shim protocol, but hopefully in a fairly
obvious way that others using BoGo can easily follow. It shouldn't break
our cross-version tests because we keep runner and shim at the same
versio there.
To avoid needing to make an incompatible change to the shim <->
handshaker protocol, which would impact our cross-version tests, this
introduces a mechanism for the shim omit flags when talking to the
handshaker. The handshaker doesn't need to know how to connect to the
runner.
Also print the error string on Windows. Sadly this is a bit tedious.
Change-Id: Ic8bda9a854a115c206c05a659a2e34f544b844a6
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/60885
Auto-Submit: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
1 year ago
|
|
|
Flag Base64Flag(const char *name, std::string TestConfig::*field,
|
|
|
|
bool skip_handshaker = false) {
|
|
|
|
return Flag{name, true, skip_handshaker,
|
|
|
|
[=](TestConfig *config, const char *param) -> bool {
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
return DecodeBase64(&(config->*field), param);
|
|
|
|
}};
|
|
|
|
}
|
|
|
|
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
Flag Base64VectorFlag(const char *name,
|
Pass IPv6 vs IPv4 down to the shim
The runner currently tries to listen on IPv6 and then falls back to IPv4
on error. The shim does the same. If they pick different ones, this
breaks down.
Normally, fallback happens because the system doesn't have IPv6, and
both sides will make the same decision. But if binding to IPv6 fails for
other reasons, they may mismatch. We're observing them fail due to what
seems to port exhaustion. When this happens, shim and runner don't
agree on the same address family.
Instead, just tell the shim which address to connect to. This doesn't
fix the underlying port exhaustion problem, but it does seem to fix the
flakes. Although given we are still exhausting ports and falling back to
IPv4, it doesn't truly fix it. Later CLs will address port exhaustion by
using a single server port.
This changes the runner <-> shim protocol, but hopefully in a fairly
obvious way that others using BoGo can easily follow. It shouldn't break
our cross-version tests because we keep runner and shim at the same
versio there.
To avoid needing to make an incompatible change to the shim <->
handshaker protocol, which would impact our cross-version tests, this
introduces a mechanism for the shim omit flags when talking to the
handshaker. The handshaker doesn't need to know how to connect to the
runner.
Also print the error string on Windows. Sadly this is a bit tedious.
Change-Id: Ic8bda9a854a115c206c05a659a2e34f544b844a6
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/60885
Auto-Submit: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
1 year ago
|
|
|
std::vector<std::string> TestConfig::*field,
|
|
|
|
bool skip_handshaker = false) {
|
|
|
|
return Flag{name, true, skip_handshaker,
|
|
|
|
[=](TestConfig *config, const char *param) -> bool {
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
std::string value;
|
|
|
|
if (!DecodeBase64(&value, param)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
(config->*field).push_back(std::move(value));
|
|
|
|
return true;
|
|
|
|
}};
|
|
|
|
}
|
|
|
|
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
Flag StringPairVectorFlag(
|
|
|
|
const char *name,
|
Pass IPv6 vs IPv4 down to the shim
The runner currently tries to listen on IPv6 and then falls back to IPv4
on error. The shim does the same. If they pick different ones, this
breaks down.
Normally, fallback happens because the system doesn't have IPv6, and
both sides will make the same decision. But if binding to IPv6 fails for
other reasons, they may mismatch. We're observing them fail due to what
seems to port exhaustion. When this happens, shim and runner don't
agree on the same address family.
Instead, just tell the shim which address to connect to. This doesn't
fix the underlying port exhaustion problem, but it does seem to fix the
flakes. Although given we are still exhausting ports and falling back to
IPv4, it doesn't truly fix it. Later CLs will address port exhaustion by
using a single server port.
This changes the runner <-> shim protocol, but hopefully in a fairly
obvious way that others using BoGo can easily follow. It shouldn't break
our cross-version tests because we keep runner and shim at the same
versio there.
To avoid needing to make an incompatible change to the shim <->
handshaker protocol, which would impact our cross-version tests, this
introduces a mechanism for the shim omit flags when talking to the
handshaker. The handshaker doesn't need to know how to connect to the
runner.
Also print the error string on Windows. Sadly this is a bit tedious.
Change-Id: Ic8bda9a854a115c206c05a659a2e34f544b844a6
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/60885
Auto-Submit: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
1 year ago
|
|
|
std::vector<std::pair<std::string, std::string>> TestConfig::*field,
|
|
|
|
bool skip_handshaker = false) {
|
|
|
|
return Flag{name, true, skip_handshaker,
|
|
|
|
[=](TestConfig *config, const char *param) -> bool {
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
const char *comma = strchr(param, ',');
|
|
|
|
if (!comma) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
(config->*field)
|
|
|
|
.push_back(std::make_pair(std::string(param, comma - param),
|
|
|
|
std::string(comma + 1)));
|
|
|
|
return true;
|
|
|
|
}};
|
|
|
|
}
|
|
|
|
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
std::vector<Flag> SortedFlags() {
|
|
|
|
std::vector<Flag> flags = {
|
Pass IPv6 vs IPv4 down to the shim
The runner currently tries to listen on IPv6 and then falls back to IPv4
on error. The shim does the same. If they pick different ones, this
breaks down.
Normally, fallback happens because the system doesn't have IPv6, and
both sides will make the same decision. But if binding to IPv6 fails for
other reasons, they may mismatch. We're observing them fail due to what
seems to port exhaustion. When this happens, shim and runner don't
agree on the same address family.
Instead, just tell the shim which address to connect to. This doesn't
fix the underlying port exhaustion problem, but it does seem to fix the
flakes. Although given we are still exhausting ports and falling back to
IPv4, it doesn't truly fix it. Later CLs will address port exhaustion by
using a single server port.
This changes the runner <-> shim protocol, but hopefully in a fairly
obvious way that others using BoGo can easily follow. It shouldn't break
our cross-version tests because we keep runner and shim at the same
versio there.
To avoid needing to make an incompatible change to the shim <->
handshaker protocol, which would impact our cross-version tests, this
introduces a mechanism for the shim omit flags when talking to the
handshaker. The handshaker doesn't need to know how to connect to the
runner.
Also print the error string on Windows. Sadly this is a bit tedious.
Change-Id: Ic8bda9a854a115c206c05a659a2e34f544b844a6
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/60885
Auto-Submit: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
1 year ago
|
|
|
IntFlag("-port", &TestConfig::port, /*skip_handshaker=*/true),
|
|
|
|
BoolFlag("-ipv6", &TestConfig::ipv6, /*skip_handshaker=*/true),
|
|
|
|
IntFlag("-shim-id", &TestConfig::shim_id, /*skip_handshaker=*/true),
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
BoolFlag("-server", &TestConfig::is_server),
|
|
|
|
BoolFlag("-dtls", &TestConfig::is_dtls),
|
|
|
|
BoolFlag("-quic", &TestConfig::is_quic),
|
|
|
|
IntFlag("-resume-count", &TestConfig::resume_count),
|
|
|
|
StringFlag("-write-settings", &TestConfig::write_settings),
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
BoolFlag("-fallback-scsv", &TestConfig::fallback_scsv),
|
|
|
|
IntVectorFlag("-signing-prefs", &TestConfig::signing_prefs),
|
|
|
|
IntVectorFlag("-verify-prefs", &TestConfig::verify_prefs),
|
|
|
|
IntVectorFlag("-expect-peer-verify-pref",
|
|
|
|
&TestConfig::expect_peer_verify_prefs),
|
|
|
|
IntVectorFlag("-curves", &TestConfig::curves),
|
|
|
|
StringFlag("-key-file", &TestConfig::key_file),
|
|
|
|
StringFlag("-cert-file", &TestConfig::cert_file),
|
Generate certs on the fly in runner, pass trusted cert to shim
Rather than using the pre-generated certificates, generate them on the
fly. This allows TLS stacks for which certificate validation and
verification are coupled to work as expected. Certificates and keys are
written to temporary files which are then passed to the shim, and
cleaned up on exit. This requires reworking how testCase passes
certs/keys by adding a new field, sendCertificate, rather than manually
setting the -cert-file and -key-file flags. Incidentally the
rsaChainCertificate is removed, since it was essentially unused, and all
tests that used it also work with rsaCertificate. Finally, include a
single SAN ("test") in all certificates, which fixes some TLS stacks
which require this to operate (such as rustls, which currently
regenerates all the certificates currently in the tree to add a SAN).
Additionally, add a new flag, -trust-cert, which tells the the shim
which certificates it should trust. Shims for TLS stacks which
can completely decouple validation and verification of X509 certificates
(like BoringSSL) can ignore this flag, but for stacks where this
functionality is somewhat more intertwined (like Go), this allows the
shim to properly process the sent certificates.
Change-Id: Ic5c63e18fb2b852cc693aacb3b06cfe7993bc90c
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/62565
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
1 year ago
|
|
|
StringFlag("-trust-cert", &TestConfig::trust_cert),
|
|
|
|
StringFlag("-expect-server-name", &TestConfig::expect_server_name),
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
BoolFlag("-enable-ech-grease", &TestConfig::enable_ech_grease),
|
|
|
|
Base64VectorFlag("-ech-server-config", &TestConfig::ech_server_configs),
|
|
|
|
Base64VectorFlag("-ech-server-key", &TestConfig::ech_server_keys),
|
|
|
|
IntVectorFlag("-ech-is-retry-config", &TestConfig::ech_is_retry_config),
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
BoolFlag("-expect-ech-accept", &TestConfig::expect_ech_accept),
|
|
|
|
StringFlag("-expect-ech-name-override",
|
|
|
|
&TestConfig::expect_ech_name_override),
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
BoolFlag("-expect-no-ech-name-override",
|
|
|
|
&TestConfig::expect_no_ech_name_override),
|
|
|
|
Base64Flag("-expect-ech-retry-configs",
|
|
|
|
&TestConfig::expect_ech_retry_configs),
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
BoolFlag("-expect-no-ech-retry-configs",
|
|
|
|
&TestConfig::expect_no_ech_retry_configs),
|
|
|
|
Base64Flag("-ech-config-list", &TestConfig::ech_config_list),
|
|
|
|
Base64Flag("-expect-certificate-types",
|
|
|
|
&TestConfig::expect_certificate_types),
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
BoolFlag("-require-any-client-certificate",
|
|
|
|
&TestConfig::require_any_client_certificate),
|
|
|
|
StringFlag("-advertise-npn", &TestConfig::advertise_npn),
|
|
|
|
StringFlag("-expect-next-proto", &TestConfig::expect_next_proto),
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
BoolFlag("-false-start", &TestConfig::false_start),
|
|
|
|
StringFlag("-select-next-proto", &TestConfig::select_next_proto),
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
BoolFlag("-async", &TestConfig::async),
|
|
|
|
BoolFlag("-write-different-record-sizes",
|
|
|
|
&TestConfig::write_different_record_sizes),
|
|
|
|
BoolFlag("-cbc-record-splitting", &TestConfig::cbc_record_splitting),
|
|
|
|
BoolFlag("-partial-write", &TestConfig::partial_write),
|
|
|
|
BoolFlag("-no-tls13", &TestConfig::no_tls13),
|
|
|
|
BoolFlag("-no-tls12", &TestConfig::no_tls12),
|
|
|
|
BoolFlag("-no-tls11", &TestConfig::no_tls11),
|
|
|
|
BoolFlag("-no-tls1", &TestConfig::no_tls1),
|
|
|
|
BoolFlag("-no-ticket", &TestConfig::no_ticket),
|
|
|
|
Base64Flag("-expect-channel-id", &TestConfig::expect_channel_id),
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
BoolFlag("-enable-channel-id", &TestConfig::enable_channel_id),
|
|
|
|
StringFlag("-send-channel-id", &TestConfig::send_channel_id),
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
BoolFlag("-shim-writes-first", &TestConfig::shim_writes_first),
|
|
|
|
StringFlag("-host-name", &TestConfig::host_name),
|
|
|
|
StringFlag("-advertise-alpn", &TestConfig::advertise_alpn),
|
|
|
|
StringFlag("-expect-alpn", &TestConfig::expect_alpn),
|
|
|
|
StringFlag("-expect-late-alpn", &TestConfig::expect_late_alpn),
|
|
|
|
StringFlag("-expect-advertised-alpn",
|
|
|
|
&TestConfig::expect_advertised_alpn),
|
|
|
|
StringFlag("-select-alpn", &TestConfig::select_alpn),
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
BoolFlag("-decline-alpn", &TestConfig::decline_alpn),
|
|
|
|
BoolFlag("-reject-alpn", &TestConfig::reject_alpn),
|
|
|
|
BoolFlag("-select-empty-alpn", &TestConfig::select_empty_alpn),
|
|
|
|
BoolFlag("-defer-alps", &TestConfig::defer_alps),
|
|
|
|
StringPairVectorFlag("-application-settings",
|
|
|
|
&TestConfig::application_settings),
|
|
|
|
OptionalStringFlag("-expect-peer-application-settings",
|
|
|
|
&TestConfig::expect_peer_application_settings),
|
Check client certificate types in TLS <= 1.2
TLS <= 1.2 servers indicate supported client certificate key types with
a certificate_types field in the CertificateRequest. Historically, we've
just ignored this field, because we've always outsourced certificate
selection to the caller anyway. This meant that, if you configured an
RSA client certificate in response to a server that requested only ECDSA
certificates, we would happily send the certificate and leave it to the
server to decide if it was happy.
Strictly speaking, this was in violation of RFC 5246:
- The end-entity certificate provided by the client MUST contain a
key that is compatible with certificate_types. [...]
Although prior TLS versions didn't say anything useful about this either
way.
Once we move certificate selection into the library, we'll want to start
evaluating supported algorithms ourselves. A natural implementation of
it will, as a side effect, cause us to enforce this match, even when
only a single certificate is configured. Since this is unlikely to have
any real compatibility impact (every TLS server I've seen just hardcodes
this list), let's just try turning it on. On the off chance it does
break someone, I've left a flag, SSL_set_check_client_certificate_type,
for folks to turn this check off. The flag will most likely be
unnecessary, in which case we can retire it after a few months.
If this does cause a problem, we can opt to turn it off for the default
certificate, or only enable it when multiple certificates are
configured, or lean on the sigalgs list (doesn't work for 1.0/1.1), but
these all result in some slightly suboptimal behavior, so I think we
should treat them as contingency plans.
Update-Note: A TLS 1.2 (or below) client, using client certificates,
connecting to a TLS server which doesn't support its certificate type
will now fail the connection slightly earlier, rather than sending the
certificate and waiting for the server to reject it. The connection
should fail either way, but now it will fail earlier with
SSL_R_UNKNOWN_CERTIFICATE_TYPE. If the server was buggy and did not
correctly advertise its own capabilities (very very unlikely), this may
cause a connection to fail despite previously succeeding. We have
included a temporary API, SSL_set_check_client_certificate_type, to
disable this behavior in the unlikely event this has any impact, but
please contact the BoringSSL team if you need it, as it will interfere
with improvements down the line.
This change does not affect servers requesting client certificates, only
clients sending them.
Bug: 249
Change-Id: I159bc444c4ee79fbe5c476d4253b48d58d2538be
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/66687
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Bob Beck <bbe@google.com>
9 months ago
|
|
|
BoolFlag("-alps-use-new-codepoint", &TestConfig::alps_use_new_codepoint),
|
|
|
|
Base64Flag("-quic-transport-params", &TestConfig::quic_transport_params),
|
|
|
|
Base64Flag("-expect-quic-transport-params",
|
|
|
|
&TestConfig::expect_quic_transport_params),
|
|
|
|
IntFlag("-quic-use-legacy-codepoint",
|
|
|
|
&TestConfig::quic_use_legacy_codepoint),
|
|
|
|
BoolFlag("-expect-session-miss", &TestConfig::expect_session_miss),
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
BoolFlag("-expect-extended-master-secret",
|
|
|
|
&TestConfig::expect_extended_master_secret),
|
|
|
|
StringFlag("-psk", &TestConfig::psk),
|
|
|
|
StringFlag("-psk-identity", &TestConfig::psk_identity),
|
|
|
|
StringFlag("-srtp-profiles", &TestConfig::srtp_profiles),
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
BoolFlag("-enable-ocsp-stapling", &TestConfig::enable_ocsp_stapling),
|
|
|
|
BoolFlag("-enable-signed-cert-timestamps",
|
|
|
|
&TestConfig::enable_signed_cert_timestamps),
|
|
|
|
Base64Flag("-expect-signed-cert-timestamps",
|
|
|
|
&TestConfig::expect_signed_cert_timestamps),
|
|
|
|
IntFlag("-min-version", &TestConfig::min_version),
|
|
|
|
IntFlag("-max-version", &TestConfig::max_version),
|
|
|
|
IntFlag("-expect-version", &TestConfig::expect_version),
|
|
|
|
IntFlag("-mtu", &TestConfig::mtu),
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
BoolFlag("-implicit-handshake", &TestConfig::implicit_handshake),
|
|
|
|
BoolFlag("-use-early-callback", &TestConfig::use_early_callback),
|
|
|
|
BoolFlag("-fail-early-callback", &TestConfig::fail_early_callback),
|
|
|
|
BoolFlag("-install-ddos-callback", &TestConfig::install_ddos_callback),
|
|
|
|
BoolFlag("-fail-ddos-callback", &TestConfig::fail_ddos_callback),
|
|
|
|
BoolFlag("-fail-cert-callback", &TestConfig::fail_cert_callback),
|
|
|
|
StringFlag("-cipher", &TestConfig::cipher),
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
BoolFlag("-handshake-never-done", &TestConfig::handshake_never_done),
|
|
|
|
IntFlag("-export-keying-material", &TestConfig::export_keying_material),
|
|
|
|
StringFlag("-export-label", &TestConfig::export_label),
|
|
|
|
StringFlag("-export-context", &TestConfig::export_context),
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
BoolFlag("-use-export-context", &TestConfig::use_export_context),
|
|
|
|
BoolFlag("-tls-unique", &TestConfig::tls_unique),
|
|
|
|
BoolFlag("-expect-ticket-renewal", &TestConfig::expect_ticket_renewal),
|
|
|
|
BoolFlag("-expect-no-session", &TestConfig::expect_no_session),
|
|
|
|
BoolFlag("-expect-ticket-supports-early-data",
|
|
|
|
&TestConfig::expect_ticket_supports_early_data),
|
|
|
|
BoolFlag("-expect-accept-early-data",
|
|
|
|
&TestConfig::expect_accept_early_data),
|
|
|
|
BoolFlag("-expect-reject-early-data",
|
|
|
|
&TestConfig::expect_reject_early_data),
|
|
|
|
BoolFlag("-expect-no-offer-early-data",
|
|
|
|
&TestConfig::expect_no_offer_early_data),
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
BoolFlag("-use-ticket-callback", &TestConfig::use_ticket_callback),
|
|
|
|
BoolFlag("-renew-ticket", &TestConfig::renew_ticket),
|
|
|
|
BoolFlag("-enable-early-data", &TestConfig::enable_early_data),
|
|
|
|
Base64Flag("-ocsp-response", &TestConfig::ocsp_response),
|
|
|
|
Base64Flag("-expect-ocsp-response", &TestConfig::expect_ocsp_response),
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
BoolFlag("-check-close-notify", &TestConfig::check_close_notify),
|
|
|
|
BoolFlag("-shim-shuts-down", &TestConfig::shim_shuts_down),
|
|
|
|
BoolFlag("-verify-fail", &TestConfig::verify_fail),
|
|
|
|
BoolFlag("-verify-peer", &TestConfig::verify_peer),
|
|
|
|
BoolFlag("-verify-peer-if-no-obc", &TestConfig::verify_peer_if_no_obc),
|
|
|
|
BoolFlag("-expect-verify-result", &TestConfig::expect_verify_result),
|
|
|
|
Base64Flag("-signed-cert-timestamps",
|
|
|
|
&TestConfig::signed_cert_timestamps),
|
|
|
|
IntFlag("-expect-total-renegotiations",
|
|
|
|
&TestConfig::expect_total_renegotiations),
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
BoolFlag("-renegotiate-once", &TestConfig::renegotiate_once),
|
|
|
|
BoolFlag("-renegotiate-freely", &TestConfig::renegotiate_freely),
|
|
|
|
BoolFlag("-renegotiate-ignore", &TestConfig::renegotiate_ignore),
|
|
|
|
BoolFlag("-renegotiate-explicit", &TestConfig::renegotiate_explicit),
|
|
|
|
BoolFlag("-forbid-renegotiation-after-handshake",
|
|
|
|
&TestConfig::forbid_renegotiation_after_handshake),
|
|
|
|
IntFlag("-expect-peer-signature-algorithm",
|
|
|
|
&TestConfig::expect_peer_signature_algorithm),
|
|
|
|
IntFlag("-expect-curve-id", &TestConfig::expect_curve_id),
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
BoolFlag("-use-old-client-cert-callback",
|
|
|
|
&TestConfig::use_old_client_cert_callback),
|
|
|
|
IntFlag("-initial-timeout-duration-ms",
|
|
|
|
&TestConfig::initial_timeout_duration_ms),
|
|
|
|
StringFlag("-use-client-ca-list", &TestConfig::use_client_ca_list),
|
|
|
|
StringFlag("-expect-client-ca-list", &TestConfig::expect_client_ca_list),
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
BoolFlag("-send-alert", &TestConfig::send_alert),
|
|
|
|
BoolFlag("-peek-then-read", &TestConfig::peek_then_read),
|
|
|
|
BoolFlag("-enable-grease", &TestConfig::enable_grease),
|
|
|
|
BoolFlag("-permute-extensions", &TestConfig::permute_extensions),
|
|
|
|
IntFlag("-max-cert-list", &TestConfig::max_cert_list),
|
|
|
|
Base64Flag("-ticket-key", &TestConfig::ticket_key),
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
BoolFlag("-use-exporter-between-reads",
|
|
|
|
&TestConfig::use_exporter_between_reads),
|
|
|
|
IntFlag("-expect-cipher-aes", &TestConfig::expect_cipher_aes),
|
|
|
|
IntFlag("-expect-cipher-no-aes", &TestConfig::expect_cipher_no_aes),
|
|
|
|
IntFlag("-expect-cipher", &TestConfig::expect_cipher),
|
|
|
|
StringFlag("-expect-peer-cert-file", &TestConfig::expect_peer_cert_file),
|
|
|
|
IntFlag("-resumption-delay", &TestConfig::resumption_delay),
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
BoolFlag("-retain-only-sha256-client-cert",
|
|
|
|
&TestConfig::retain_only_sha256_client_cert),
|
|
|
|
BoolFlag("-expect-sha256-client-cert",
|
|
|
|
&TestConfig::expect_sha256_client_cert),
|
|
|
|
BoolFlag("-read-with-unfinished-write",
|
|
|
|
&TestConfig::read_with_unfinished_write),
|
|
|
|
BoolFlag("-expect-secure-renegotiation",
|
|
|
|
&TestConfig::expect_secure_renegotiation),
|
|
|
|
BoolFlag("-expect-no-secure-renegotiation",
|
|
|
|
&TestConfig::expect_no_secure_renegotiation),
|
|
|
|
IntFlag("-max-send-fragment", &TestConfig::max_send_fragment),
|
|
|
|
IntFlag("-read-size", &TestConfig::read_size),
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
BoolFlag("-expect-session-id", &TestConfig::expect_session_id),
|
|
|
|
BoolFlag("-expect-no-session-id", &TestConfig::expect_no_session_id),
|
|
|
|
IntFlag("-expect-ticket-age-skew", &TestConfig::expect_ticket_age_skew),
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
BoolFlag("-no-op-extra-handshake", &TestConfig::no_op_extra_handshake),
|
|
|
|
BoolFlag("-handshake-twice", &TestConfig::handshake_twice),
|
|
|
|
BoolFlag("-allow-unknown-alpn-protos",
|
|
|
|
&TestConfig::allow_unknown_alpn_protos),
|
|
|
|
BoolFlag("-use-custom-verify-callback",
|
|
|
|
&TestConfig::use_custom_verify_callback),
|
|
|
|
StringFlag("-expect-msg-callback", &TestConfig::expect_msg_callback),
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
BoolFlag("-allow-false-start-without-alpn",
|
|
|
|
&TestConfig::allow_false_start_without_alpn),
|
|
|
|
BoolFlag("-handoff", &TestConfig::handoff),
|
|
|
|
BoolFlag("-handshake-hints", &TestConfig::handshake_hints),
|
|
|
|
BoolFlag("-allow-hint-mismatch", &TestConfig::allow_hint_mismatch),
|
|
|
|
BoolFlag("-use-ocsp-callback", &TestConfig::use_ocsp_callback),
|
|
|
|
BoolFlag("-set-ocsp-in-callback", &TestConfig::set_ocsp_in_callback),
|
|
|
|
BoolFlag("-decline-ocsp-callback", &TestConfig::decline_ocsp_callback),
|
|
|
|
BoolFlag("-fail-ocsp-callback", &TestConfig::fail_ocsp_callback),
|
|
|
|
BoolFlag("-install-cert-compression-algs",
|
|
|
|
&TestConfig::install_cert_compression_algs),
|
|
|
|
IntFlag("-install-one-cert-compression-alg",
|
|
|
|
&TestConfig::install_one_cert_compression_alg),
|
|
|
|
BoolFlag("-reverify-on-resume", &TestConfig::reverify_on_resume),
|
Default SSL_set_enforce_rsa_key_usage to enabled.
This relands
https://boringssl-review.googlesource.com/c/boringssl/+/54606, which was
temporarily reverted.
Update-Note: By default, clients will now require RSA server
certificates used in TLS 1.2 and earlier to include the keyEncipherment
or digitalSignature bit. keyEncipherment is required if using RSA key
exchange. digitalSignature is required if using ECDHE_RSA key exchange.
If unsure, TLS RSA server signatures should include both, but some
deployments may wish to include only one if separating keys, or simply
disabling RSA key exchange. The latter is useful to mitigate either the
Bleichenbacher attack (from 1998, most recently resurfaced in 2017 as
ROBOT), or to strengthen TLS 1.3 downgrade protections, which is
particularly important for enterprise environments using client
certificates (aka "mTLS") because, prior to TLS 1.3, the TLS client
certificate flow was insufficiently encrypted or authenticated. Without
reflecting an RSA key exchange disable into key usage, and then the
client checking it, an attacker can spoof a CertificateRequest as coming
from some server.
This aligns with standard security requirements for using X.509
certificates, specified in RFC 5280, section 4.2.1.3, and reiterated in
TLS as early as TLS 1.0, RFC 2246, section 7.4.2, published 24 years ago
on January 1999. Constraints on usage of keys are important to mitigate
cross-protocol attacks, a class of cryptographic attacks that is
well-studied in the literature.
We already checked this for each of ECDSA, TLS 1.3, and servers
verifying client certificates, so this just fills in the remaining hole.
As a result, this change is also important for avoiding some weird
behaviors when configuration changes transition a server in or out of
this hole. (We've seen connection failures get misattributed to TLS 1.3
when it was really a certificate misconfiguration.)
Chrome has also enforced this for some time with publicly-trusted
certificates. As a temporary measure for callers that need more time,
the SSL_set_enforce_rsa_key_usage API, added to BoringSSL in January
2019, still exists where we need to turn this off.
Fixed: 519
Change-Id: I91bf2cfb04c92aec7875e640f90ba6f837146dc1
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/58805
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Bob Beck <bbe@google.com>
2 years ago
|
|
|
BoolFlag("-ignore-rsa-key-usage", &TestConfig::ignore_rsa_key_usage),
|
|
|
|
BoolFlag("-expect-key-usage-invalid",
|
|
|
|
&TestConfig::expect_key_usage_invalid),
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
BoolFlag("-is-handshaker-supported",
|
|
|
|
&TestConfig::is_handshaker_supported),
|
|
|
|
BoolFlag("-handshaker-resume", &TestConfig::handshaker_resume),
|
|
|
|
StringFlag("-handshaker-path", &TestConfig::handshaker_path),
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
BoolFlag("-jdk11-workaround", &TestConfig::jdk11_workaround),
|
|
|
|
BoolFlag("-server-preference", &TestConfig::server_preference),
|
|
|
|
BoolFlag("-export-traffic-secrets", &TestConfig::export_traffic_secrets),
|
|
|
|
BoolFlag("-key-update", &TestConfig::key_update),
|
|
|
|
BoolFlag("-expect-delegated-credential-used",
|
|
|
|
&TestConfig::expect_delegated_credential_used),
|
|
|
|
StringFlag("-delegated-credential", &TestConfig::delegated_credential),
|
|
|
|
StringFlag("-expect-early-data-reason",
|
|
|
|
&TestConfig::expect_early_data_reason),
|
|
|
|
BoolFlag("-expect-hrr", &TestConfig::expect_hrr),
|
|
|
|
BoolFlag("-expect-no-hrr", &TestConfig::expect_no_hrr),
|
|
|
|
BoolFlag("-wait-for-debugger", &TestConfig::wait_for_debugger),
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
StringFlag("-quic-early-data-context",
|
|
|
|
&TestConfig::quic_early_data_context),
|
|
|
|
IntFlag("-early-write-after-message",
|
|
|
|
&TestConfig::early_write_after_message),
|
|
|
|
BoolFlag("-fips-202205", &TestConfig::fips_202205),
|
|
|
|
BoolFlag("-wpa-202304", &TestConfig::wpa_202304),
|
Check client certificate types in TLS <= 1.2
TLS <= 1.2 servers indicate supported client certificate key types with
a certificate_types field in the CertificateRequest. Historically, we've
just ignored this field, because we've always outsourced certificate
selection to the caller anyway. This meant that, if you configured an
RSA client certificate in response to a server that requested only ECDSA
certificates, we would happily send the certificate and leave it to the
server to decide if it was happy.
Strictly speaking, this was in violation of RFC 5246:
- The end-entity certificate provided by the client MUST contain a
key that is compatible with certificate_types. [...]
Although prior TLS versions didn't say anything useful about this either
way.
Once we move certificate selection into the library, we'll want to start
evaluating supported algorithms ourselves. A natural implementation of
it will, as a side effect, cause us to enforce this match, even when
only a single certificate is configured. Since this is unlikely to have
any real compatibility impact (every TLS server I've seen just hardcodes
this list), let's just try turning it on. On the off chance it does
break someone, I've left a flag, SSL_set_check_client_certificate_type,
for folks to turn this check off. The flag will most likely be
unnecessary, in which case we can retire it after a few months.
If this does cause a problem, we can opt to turn it off for the default
certificate, or only enable it when multiple certificates are
configured, or lean on the sigalgs list (doesn't work for 1.0/1.1), but
these all result in some slightly suboptimal behavior, so I think we
should treat them as contingency plans.
Update-Note: A TLS 1.2 (or below) client, using client certificates,
connecting to a TLS server which doesn't support its certificate type
will now fail the connection slightly earlier, rather than sending the
certificate and waiting for the server to reject it. The connection
should fail either way, but now it will fail earlier with
SSL_R_UNKNOWN_CERTIFICATE_TYPE. If the server was buggy and did not
correctly advertise its own capabilities (very very unlikely), this may
cause a connection to fail despite previously succeeding. We have
included a temporary API, SSL_set_check_client_certificate_type, to
disable this behavior in the unlikely event this has any impact, but
please contact the BoringSSL team if you need it, as it will interfere
with improvements down the line.
This change does not affect servers requesting client certificates, only
clients sending them.
Bug: 249
Change-Id: I159bc444c4ee79fbe5c476d4253b48d58d2538be
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/66687
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Bob Beck <bbe@google.com>
9 months ago
|
|
|
BoolFlag("-no-check-client-certificate-type",
|
|
|
|
&TestConfig::no_check_client_certificate_type),
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
};
|
|
|
|
std::sort(flags.begin(), flags.end(), [](const Flag &a, const Flag &b) {
|
|
|
|
return strcmp(a.name, b.name) < 0;
|
|
|
|
});
|
|
|
|
return flags;
|
|
|
|
}
|
|
|
|
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
const Flag *FindFlag(const char *name) {
|
|
|
|
static const std::vector<Flag> kSortedFlags = SortedFlags();
|
|
|
|
auto iter = std::lower_bound(kSortedFlags.begin(), kSortedFlags.end(), name,
|
|
|
|
[](const Flag &flag, const char *key) {
|
|
|
|
return strcmp(flag.name, key) < 0;
|
|
|
|
});
|
|
|
|
if (iter == kSortedFlags.end() || strcmp(iter->name, name) != 0) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
return &*iter;
|
|
|
|
}
|
|
|
|
|
|
|
|
// RemovePrefix checks if |*str| begins with |prefix| + "-". If so, it advances
|
|
|
|
// |*str| past |prefix| (but not past the "-") and returns true. Otherwise, it
|
|
|
|
// returns false and leaves |*str| unmodified.
|
|
|
|
bool RemovePrefix(const char **str, const char *prefix) {
|
|
|
|
size_t prefix_len = strlen(prefix);
|
|
|
|
if (strncmp(*str, prefix, strlen(prefix)) == 0 && (*str)[prefix_len] == '-') {
|
|
|
|
*str += strlen(prefix);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
bool ParseConfig(int argc, char **argv, bool is_shim,
|
|
|
|
TestConfig *out_initial,
|
|
|
|
TestConfig *out_resume,
|
|
|
|
TestConfig *out_retry) {
|
|
|
|
for (int i = 0; i < argc; i++) {
|
|
|
|
bool skip = false;
|
Pass IPv6 vs IPv4 down to the shim
The runner currently tries to listen on IPv6 and then falls back to IPv4
on error. The shim does the same. If they pick different ones, this
breaks down.
Normally, fallback happens because the system doesn't have IPv6, and
both sides will make the same decision. But if binding to IPv6 fails for
other reasons, they may mismatch. We're observing them fail due to what
seems to port exhaustion. When this happens, shim and runner don't
agree on the same address family.
Instead, just tell the shim which address to connect to. This doesn't
fix the underlying port exhaustion problem, but it does seem to fix the
flakes. Although given we are still exhausting ports and falling back to
IPv4, it doesn't truly fix it. Later CLs will address port exhaustion by
using a single server port.
This changes the runner <-> shim protocol, but hopefully in a fairly
obvious way that others using BoGo can easily follow. It shouldn't break
our cross-version tests because we keep runner and shim at the same
versio there.
To avoid needing to make an incompatible change to the shim <->
handshaker protocol, which would impact our cross-version tests, this
introduces a mechanism for the shim omit flags when talking to the
handshaker. The handshaker doesn't need to know how to connect to the
runner.
Also print the error string on Windows. Sadly this is a bit tedious.
Change-Id: Ic8bda9a854a115c206c05a659a2e34f544b844a6
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/60885
Auto-Submit: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
1 year ago
|
|
|
const char *arg = argv[i];
|
|
|
|
const char *name = arg;
|
|
|
|
|
|
|
|
// -on-shim and -on-handshaker prefixes enable flags only on the shim or
|
|
|
|
// handshaker.
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
if (RemovePrefix(&name, "-on-shim")) {
|
|
|
|
if (!is_shim) {
|
|
|
|
skip = true;
|
|
|
|
}
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
} else if (RemovePrefix(&name, "-on-handshaker")) {
|
|
|
|
if (is_shim) {
|
|
|
|
skip = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// The following prefixes allow different configurations for each of the
|
|
|
|
// initial, resumption, and 0-RTT retry handshakes.
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
TestConfig *out = nullptr;
|
|
|
|
if (RemovePrefix(&name, "-on-initial")) {
|
|
|
|
out = out_initial;
|
|
|
|
} else if (RemovePrefix(&name, "-on-resume")) {
|
|
|
|
out = out_resume;
|
|
|
|
} else if (RemovePrefix(&name, "-on-retry")) {
|
|
|
|
out = out_retry;
|
|
|
|
}
|
|
|
|
|
|
|
|
const Flag *flag = FindFlag(name);
|
|
|
|
if (flag == nullptr) {
|
|
|
|
fprintf(stderr, "Unrecognized flag: %s\n", name);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *param = nullptr;
|
|
|
|
if (flag->has_param) {
|
|
|
|
if (i >= argc) {
|
|
|
|
fprintf(stderr, "Missing parameter for %s\n", name);
|
|
|
|
return false;
|
|
|
|
}
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
i++;
|
|
|
|
param = argv[i];
|
|
|
|
}
|
|
|
|
|
Pass IPv6 vs IPv4 down to the shim
The runner currently tries to listen on IPv6 and then falls back to IPv4
on error. The shim does the same. If they pick different ones, this
breaks down.
Normally, fallback happens because the system doesn't have IPv6, and
both sides will make the same decision. But if binding to IPv6 fails for
other reasons, they may mismatch. We're observing them fail due to what
seems to port exhaustion. When this happens, shim and runner don't
agree on the same address family.
Instead, just tell the shim which address to connect to. This doesn't
fix the underlying port exhaustion problem, but it does seem to fix the
flakes. Although given we are still exhausting ports and falling back to
IPv4, it doesn't truly fix it. Later CLs will address port exhaustion by
using a single server port.
This changes the runner <-> shim protocol, but hopefully in a fairly
obvious way that others using BoGo can easily follow. It shouldn't break
our cross-version tests because we keep runner and shim at the same
versio there.
To avoid needing to make an incompatible change to the shim <->
handshaker protocol, which would impact our cross-version tests, this
introduces a mechanism for the shim omit flags when talking to the
handshaker. The handshaker doesn't need to know how to connect to the
runner.
Also print the error string on Windows. Sadly this is a bit tedious.
Change-Id: Ic8bda9a854a115c206c05a659a2e34f544b844a6
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/60885
Auto-Submit: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
1 year ago
|
|
|
if (!flag->skip_handshaker) {
|
|
|
|
out_initial->handshaker_args.push_back(arg);
|
|
|
|
if (flag->has_param) {
|
|
|
|
out_initial->handshaker_args.push_back(param);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Rewrite bssl_shim command-line parser.
The command-line parser is slightly showing its age: first, it is hard
to add new integral types, such as uint16_t, which is getting in the way
of fixing some of the -Wformat-signedness errors. Second, the parameter
extraction logic and skipping logic is duplicated in every type.
While I'm here, use a binary search to look up the flag, since we have
rather a lot of them. With more C++ template tricks, we could avoid the
std::function, but that seemed more trouble than was worth it,
especially since, prior to C++17, it's a little hard to convince
template argument deduction to infer one of the parameters.
Change-Id: I208f89d46371b31fc8b44487725296bcd9d7c8e7
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50769
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
3 years ago
|
|
|
if (!skip) {
|
|
|
|
if (out != nullptr) {
|
|
|
|
if (!flag->set_param(out, param)) {
|
|
|
|
fprintf(stderr, "Invalid parameter for %s: %s\n", name, param);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Unprefixed flags apply to all three.
|
|
|
|
if (!flag->set_param(out_initial, param) ||
|
|
|
|
!flag->set_param(out_resume, param) ||
|
|
|
|
!flag->set_param(out_retry, param)) {
|
|
|
|
fprintf(stderr, "Invalid parameter for %s: %s\n", name, param);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Pass IPv6 vs IPv4 down to the shim
The runner currently tries to listen on IPv6 and then falls back to IPv4
on error. The shim does the same. If they pick different ones, this
breaks down.
Normally, fallback happens because the system doesn't have IPv6, and
both sides will make the same decision. But if binding to IPv6 fails for
other reasons, they may mismatch. We're observing them fail due to what
seems to port exhaustion. When this happens, shim and runner don't
agree on the same address family.
Instead, just tell the shim which address to connect to. This doesn't
fix the underlying port exhaustion problem, but it does seem to fix the
flakes. Although given we are still exhausting ports and falling back to
IPv4, it doesn't truly fix it. Later CLs will address port exhaustion by
using a single server port.
This changes the runner <-> shim protocol, but hopefully in a fairly
obvious way that others using BoGo can easily follow. It shouldn't break
our cross-version tests because we keep runner and shim at the same
versio there.
To avoid needing to make an incompatible change to the shim <->
handshaker protocol, which would impact our cross-version tests, this
introduces a mechanism for the shim omit flags when talking to the
handshaker. The handshaker doesn't need to know how to connect to the
runner.
Also print the error string on Windows. Sadly this is a bit tedious.
Change-Id: Ic8bda9a854a115c206c05a659a2e34f544b844a6
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/60885
Auto-Submit: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
1 year ago
|
|
|
out_resume->handshaker_args = out_initial->handshaker_args;
|
|
|
|
out_retry->handshaker_args = out_initial->handshaker_args;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static CRYPTO_BUFFER_POOL *BufferPool() {
|
|
|
|
static CRYPTO_BUFFER_POOL *pool = [&] {
|
|
|
|
OPENSSL_disable_malloc_failures_for_testing();
|
|
|
|
CRYPTO_BUFFER_POOL *ret = CRYPTO_BUFFER_POOL_new();
|
|
|
|
BSSL_CHECK(ret != nullptr);
|
|
|
|
OPENSSL_enable_malloc_failures_for_testing();
|
|
|
|
return ret;
|
|
|
|
}();
|
|
|
|
return pool;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int TestConfigExDataIndex() {
|
|
|
|
static int index = [&] {
|
|
|
|
OPENSSL_disable_malloc_failures_for_testing();
|
|
|
|
int ret = SSL_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
|
|
|
|
BSSL_CHECK(ret >= 0);
|
|
|
|
OPENSSL_enable_malloc_failures_for_testing();
|
|
|
|
return ret;
|
|
|
|
}();
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SetTestConfig(SSL *ssl, const TestConfig *config) {
|
|
|
|
return SSL_set_ex_data(ssl, TestConfigExDataIndex(), (void *)config) == 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
const TestConfig *GetTestConfig(const SSL *ssl) {
|
|
|
|
return static_cast<const TestConfig *>(
|
|
|
|
SSL_get_ex_data(ssl, TestConfigExDataIndex()));
|
|
|
|
}
|
|
|
|
|
|
|
|
static int LegacyOCSPCallback(SSL *ssl, void *arg) {
|
|
|
|
const TestConfig *config = GetTestConfig(ssl);
|
|
|
|
if (!SSL_is_server(ssl)) {
|
|
|
|
return !config->fail_ocsp_callback;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!config->ocsp_response.empty() && config->set_ocsp_in_callback &&
|
|
|
|
!SSL_set_ocsp_response(ssl, (const uint8_t *)config->ocsp_response.data(),
|
|
|
|
config->ocsp_response.size())) {
|
|
|
|
return SSL_TLSEXT_ERR_ALERT_FATAL;
|
|
|
|
}
|
|
|
|
if (config->fail_ocsp_callback) {
|
|
|
|
return SSL_TLSEXT_ERR_ALERT_FATAL;
|
|
|
|
}
|
|
|
|
if (config->decline_ocsp_callback) {
|
|
|
|
return SSL_TLSEXT_ERR_NOACK;
|
|
|
|
}
|
|
|
|
return SSL_TLSEXT_ERR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int ServerNameCallback(SSL *ssl, int *out_alert, void *arg) {
|
|
|
|
// SNI must be accessible from the SNI callback.
|
|
|
|
const TestConfig *config = GetTestConfig(ssl);
|
|
|
|
const char *server_name = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
|
|
|
|
if (server_name == nullptr ||
|
|
|
|
std::string(server_name) != config->expect_server_name) {
|
|
|
|
fprintf(stderr, "servername mismatch (got %s; want %s).\n", server_name,
|
|
|
|
config->expect_server_name.c_str());
|
|
|
|
return SSL_TLSEXT_ERR_ALERT_FATAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SSL_TLSEXT_ERR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int NextProtoSelectCallback(SSL *ssl, uint8_t **out, uint8_t *outlen,
|
|
|
|
const uint8_t *in, unsigned inlen,
|
|
|
|
void *arg) {
|
|
|
|
const TestConfig *config = GetTestConfig(ssl);
|
|
|
|
if (config->select_next_proto.empty()) {
|
|
|
|
return SSL_TLSEXT_ERR_NOACK;
|
|
|
|
}
|
|
|
|
|
|
|
|
*out = (uint8_t *)config->select_next_proto.data();
|
|
|
|
*outlen = config->select_next_proto.size();
|
|
|
|
return SSL_TLSEXT_ERR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int NextProtosAdvertisedCallback(SSL *ssl, const uint8_t **out,
|
|
|
|
unsigned int *out_len, void *arg) {
|
|
|
|
const TestConfig *config = GetTestConfig(ssl);
|
|
|
|
if (config->advertise_npn.empty()) {
|
|
|
|
return SSL_TLSEXT_ERR_NOACK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (config->advertise_npn.size() > UINT_MAX) {
|
|
|
|
fprintf(stderr, "NPN value too large.\n");
|
|
|
|
return SSL_TLSEXT_ERR_ALERT_FATAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
*out = reinterpret_cast<const uint8_t *>(config->advertise_npn.data());
|
|
|
|
*out_len = static_cast<unsigned>(config->advertise_npn.size());
|
|
|
|
return SSL_TLSEXT_ERR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void MessageCallback(int is_write, int version, int content_type,
|
|
|
|
const void *buf, size_t len, SSL *ssl, void *arg) {
|
|
|
|
const uint8_t *buf_u8 = reinterpret_cast<const uint8_t *>(buf);
|
|
|
|
const TestConfig *config = GetTestConfig(ssl);
|
|
|
|
TestState *state = GetTestState(ssl);
|
|
|
|
if (!state->msg_callback_ok) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (content_type == SSL3_RT_HEADER) {
|
Simplify MSVC warning configuration
We've been setting /Wall on MSVC for a while, but /Wall in MSVC is
really "all". I.e., it's -Weverything in Clang and GCC, and includes
many warnings that are simply diagnostics. MSVC's own headers do not
promise to be clean under /Wall.
Rather, the equivalent of Clang and GCC's -Wall is /W4, which MSVC does
promise to pass. Under /Wall, every new MSVC release we've had to update
an ever-growing list of warning exceptions, to disable the
off-by-default warnings that were off for a reason. Switch to MSVC's
recommendations and just enable /W4.
From there, I've trimmed the exception list, now that we don't need to
re-disable disabled warnings. A few non-disabled warnings also no longer
need exceptions.
This should fix the build with VS2022, which was failing due to C5264.
C5264 flags a couple of instances in the library, but tons and tons in
MSVC headers and googletest. (The instances in the library are a little
goofy and reflect things that should have been 'inline constexpr', but
we can't rely on C++17 yet. Though I may go add a compat macro for
that.)
Fixed: 552
Change-Id: I9031c0d5bd4c7a4df1dc3040b38af9cfbcffc06e
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/56045
Auto-Submit: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
2 years ago
|
|
|
size_t header_len =
|
|
|
|
config->is_dtls ? DTLS1_RT_HEADER_LENGTH : SSL3_RT_HEADER_LENGTH;
|
|
|
|
if (len != header_len) {
|
|
|
|
fprintf(stderr, "Incorrect length for record header: %zu.\n", len);
|
|
|
|
state->msg_callback_ok = false;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
state->msg_callback_text += is_write ? "write " : "read ";
|
|
|
|
switch (content_type) {
|
|
|
|
case 0:
|
|
|
|
if (version != SSL2_VERSION) {
|
|
|
|
fprintf(stderr, "Incorrect version for V2ClientHello: %x.\n",
|
|
|
|
static_cast<unsigned>(version));
|
|
|
|
state->msg_callback_ok = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
state->msg_callback_text += "v2clienthello\n";
|
|
|
|
return;
|
|
|
|
|
|
|
|
case SSL3_RT_CLIENT_HELLO_INNER:
|
|
|
|
case SSL3_RT_HANDSHAKE: {
|
|
|
|
CBS cbs;
|
|
|
|
CBS_init(&cbs, buf_u8, len);
|
|
|
|
uint8_t type;
|
|
|
|
uint32_t msg_len;
|
|
|
|
if (!CBS_get_u8(&cbs, &type) ||
|
|
|
|
// TODO(davidben): Reporting on entire messages would be more
|
|
|
|
// consistent than fragments.
|
|
|
|
(config->is_dtls &&
|
|
|
|
!CBS_skip(&cbs, 3 /* total */ + 2 /* seq */ + 3 /* frag_off */)) ||
|
|
|
|
!CBS_get_u24(&cbs, &msg_len) || !CBS_skip(&cbs, msg_len) ||
|
|
|
|
CBS_len(&cbs) != 0) {
|
|
|
|
fprintf(stderr, "Could not parse handshake message.\n");
|
|
|
|
state->msg_callback_ok = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
char text[16];
|
|
|
|
if (content_type == SSL3_RT_CLIENT_HELLO_INNER) {
|
|
|
|
if (type != SSL3_MT_CLIENT_HELLO) {
|
|
|
|
fprintf(stderr, "Invalid header for ClientHelloInner.\n");
|
|
|
|
state->msg_callback_ok = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
state->msg_callback_text += "clienthelloinner\n";
|
|
|
|
} else {
|
|
|
|
snprintf(text, sizeof(text), "hs %d\n", type);
|
|
|
|
state->msg_callback_text += text;
|
|
|
|
if (!is_write) {
|
|
|
|
state->last_message_received = type;
|
|
|
|
}
|
Check hs->early_session, not ssl->session, for the early data limit.
ServerHello/EncryptedExtensions/Finished is logically one atomic flight
that exits the early data state, we have process each message
sequentially. Until we've processed Finished, we are still in the early
data state and must support writing data. Individual messages *are*
processed atomically, so the interesting points are before ServerHello
(already tested), after ServerHello, and after EncryptedExtensions.
The TLS 1.3 handshake internally clears ssl->session when processing
ServerHello, so getting the early data information from ssl->session
does not work. Instead, use hs->early_session, which is what other
codepaths use.
I've tested this with runner rather than ssl_test, so we can test both
post-SH and post-EE states. ssl_test would be more self-contained, since
we can directly control the API calls, but it cannot test the post-EE
state. To reduce record overhead, our production implementation packs EE
and Finished into the same record, which means the handshake will
process the two atomically. Instead, I've tested this in runner, with a
flag to partially drive the handshake before reading early data.
I've also tweaked the logic to hopefully be a little clearer.
Bug: chromium:1208784
Change-Id: Ia4901042419c5324054f97743bd1aac59ebf8f24
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/47485
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
4 years ago
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
case SSL3_RT_CHANGE_CIPHER_SPEC:
|
|
|
|
if (len != 1 || buf_u8[0] != 1) {
|
|
|
|
fprintf(stderr, "Invalid ChangeCipherSpec.\n");
|
|
|
|
state->msg_callback_ok = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
state->msg_callback_text += "ccs\n";
|
|
|
|
return;
|
|
|
|
|
|
|
|
case SSL3_RT_ALERT:
|
|
|
|
if (len != 2) {
|
|
|
|
fprintf(stderr, "Invalid alert.\n");
|
|
|
|
state->msg_callback_ok = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
char text[16];
|
|
|
|
snprintf(text, sizeof(text), "alert %d %d\n", buf_u8[0], buf_u8[1]);
|
|
|
|
state->msg_callback_text += text;
|
|
|
|
return;
|
|
|
|
|
|
|
|
default:
|
|
|
|
fprintf(stderr, "Invalid content_type: %d.\n", content_type);
|
|
|
|
state->msg_callback_ok = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int TicketKeyCallback(SSL *ssl, uint8_t *key_name, uint8_t *iv,
|
|
|
|
EVP_CIPHER_CTX *ctx, HMAC_CTX *hmac_ctx,
|
|
|
|
int encrypt) {
|
|
|
|
if (!encrypt) {
|
|
|
|
if (GetTestState(ssl)->ticket_decrypt_done) {
|
|
|
|
fprintf(stderr, "TicketKeyCallback called after completion.\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
GetTestState(ssl)->ticket_decrypt_done = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// This is just test code, so use the all-zeros key.
|
|
|
|
static const uint8_t kZeros[16] = {0};
|
|
|
|
|
|
|
|
if (encrypt) {
|
|
|
|
OPENSSL_memcpy(key_name, kZeros, sizeof(kZeros));
|
|
|
|
RAND_bytes(iv, 16);
|
|
|
|
} else if (OPENSSL_memcmp(key_name, kZeros, 16) != 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!HMAC_Init_ex(hmac_ctx, kZeros, sizeof(kZeros), EVP_sha256(), NULL) ||
|
|
|
|
!EVP_CipherInit_ex(ctx, EVP_aes_128_cbc(), NULL, kZeros, iv, encrypt)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!encrypt) {
|
|
|
|
return GetTestConfig(ssl)->renew_ticket ? 2 : 1;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int NewSessionCallback(SSL *ssl, SSL_SESSION *session) {
|
|
|
|
// This callback is called as the handshake completes. |SSL_get_session|
|
|
|
|
// must continue to work and, historically, |SSL_in_init| returned false at
|
|
|
|
// this point.
|
|
|
|
if (SSL_in_init(ssl) || SSL_get_session(ssl) == nullptr) {
|
|
|
|
fprintf(stderr, "Invalid state for NewSessionCallback.\n");
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
|
|
|
GetTestState(ssl)->got_new_session = true;
|
|
|
|
GetTestState(ssl)->new_session.reset(session);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void InfoCallback(const SSL *ssl, int type, int val) {
|
|
|
|
if (type == SSL_CB_HANDSHAKE_DONE) {
|
|
|
|
if (GetTestConfig(ssl)->handshake_never_done) {
|
|
|
|
fprintf(stderr, "Handshake unexpectedly completed.\n");
|
|
|
|
// Abort before any expected error code is printed, to ensure the overall
|
|
|
|
// test fails.
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
// This callback is called when the handshake completes. |SSL_get_session|
|
|
|
|
// must continue to work and |SSL_in_init| must return false.
|
|
|
|
if (SSL_in_init(ssl) || SSL_get_session(ssl) == nullptr) {
|
|
|
|
fprintf(stderr, "Invalid state for SSL_CB_HANDSHAKE_DONE.\n");
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
GetTestState(ssl)->handshake_done = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static SSL_SESSION *GetSessionCallback(SSL *ssl, const uint8_t *data, int len,
|
|
|
|
int *copy) {
|
|
|
|
TestState *async_state = GetTestState(ssl);
|
|
|
|
if (async_state->session) {
|
|
|
|
*copy = 0;
|
|
|
|
return async_state->session.release();
|
|
|
|
} else if (async_state->pending_session) {
|
|
|
|
return SSL_magic_pending_session_ptr();
|
|
|
|
} else {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void CurrentTimeCallback(const SSL *ssl, timeval *out_clock) {
|
|
|
|
*out_clock = *GetClock();
|
|
|
|
}
|
|
|
|
|
|
|
|
static int AlpnSelectCallback(SSL *ssl, const uint8_t **out, uint8_t *outlen,
|
|
|
|
const uint8_t *in, unsigned inlen, void *arg) {
|
|
|
|
if (GetTestState(ssl)->alpn_select_done) {
|
|
|
|
fprintf(stderr, "AlpnSelectCallback called after completion.\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
GetTestState(ssl)->alpn_select_done = true;
|
|
|
|
|
|
|
|
const TestConfig *config = GetTestConfig(ssl);
|
|
|
|
if (config->decline_alpn) {
|
|
|
|
return SSL_TLSEXT_ERR_NOACK;
|
|
|
|
}
|
|
|
|
if (config->reject_alpn) {
|
|
|
|
return SSL_TLSEXT_ERR_ALERT_FATAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!config->expect_advertised_alpn.empty() &&
|
|
|
|
(config->expect_advertised_alpn.size() != inlen ||
|
|
|
|
OPENSSL_memcmp(config->expect_advertised_alpn.data(), in, inlen) !=
|
|
|
|
0)) {
|
|
|
|
fprintf(stderr, "bad ALPN select callback inputs.\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (config->defer_alps) {
|
|
|
|
for (const auto &pair : config->application_settings) {
|
|
|
|
if (!SSL_add_application_settings(
|
|
|
|
ssl, reinterpret_cast<const uint8_t *>(pair.first.data()),
|
|
|
|
pair.first.size(),
|
|
|
|
reinterpret_cast<const uint8_t *>(pair.second.data()),
|
|
|
|
pair.second.size())) {
|
|
|
|
fprintf(stderr, "error configuring ALPS.\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(config->select_alpn.empty() || !config->select_empty_alpn);
|
|
|
|
*out = (const uint8_t *)config->select_alpn.data();
|
|
|
|
*outlen = config->select_alpn.size();
|
|
|
|
return SSL_TLSEXT_ERR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool CheckVerifyCallback(SSL *ssl) {
|
|
|
|
const TestConfig *config = GetTestConfig(ssl);
|
|
|
|
if (!config->expect_ocsp_response.empty()) {
|
|
|
|
const uint8_t *data;
|
|
|
|
size_t len;
|
|
|
|
SSL_get0_ocsp_response(ssl, &data, &len);
|
|
|
|
if (len == 0) {
|
|
|
|
fprintf(stderr, "OCSP response not available in verify callback.\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Implement ClientHelloOuter handshakes.
If a client offers ECH, but the server rejects it, the client completes
the handshake with ClientHelloOuter in order to authenticate retry keys.
Implement this flow. This is largely allowing the existing handshake to
proceed, but with some changes:
- Certificate verification uses the other name. This CL routes this up to
the built-in verifier and adds SSL_get0_ech_name_override for the
callback.
- We need to disable False Start to pick up server Finished in TLS 1.2.
- Client certificates, notably in TLS 1.3 where they're encrypted,
should only be revealed to the true server. Fortunately, not sending
client certs is always an option, so do that.
Channel ID has a similar issue. I've just omitted the extension in
ClientHelloOuter because it's deprecated and is unlikely to be used
with ECH at this point. ALPS may be worth some pondering but, the way
it's currently used, is not sensitive.
(Possibly we should change the draft to terminate the handshake before
even sending that flight...)
- The session is never offered in ClientHelloOuter, but our internal
book-keeping doesn't quite notice.
I had to replace ech_accept with a tri-state ech_status to correctly
handle an edge case in SSL_get0_ech_name_override: when ECH + 0-RTT +
reverify_on_resume are all enabled, the first certificate verification
is for the 0-RTT session and should be against the true name, yet we
have selected_ech_config && !ech_accept. A tri-state tracks when ECH is
actually rejected. I've maintained this on the server as well, though
the server never actually cares.
Bug: 275
Change-Id: Ie55966ca3dc4ffcc8c381479f0fe9bcacd34d0f8
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/48135
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
3 years ago
|
|
|
const char *name_override;
|
|
|
|
size_t name_override_len;
|
|
|
|
SSL_get0_ech_name_override(ssl, &name_override, &name_override_len);
|
|
|
|
if (config->expect_no_ech_name_override && name_override_len != 0) {
|
|
|
|
fprintf(stderr, "Unexpected ECH name override.\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!config->expect_ech_name_override.empty() &&
|
|
|
|
config->expect_ech_name_override !=
|
|
|
|
std::string(name_override, name_override_len)) {
|
|
|
|
fprintf(stderr, "ECH name did not match expected value.\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (GetTestState(ssl)->cert_verified) {
|
|
|
|
fprintf(stderr, "Certificate verified twice.\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int CertVerifyCallback(X509_STORE_CTX *store_ctx, void *arg) {
|
|
|
|
SSL *ssl = (SSL *)X509_STORE_CTX_get_ex_data(
|
|
|
|
store_ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
|
|
|
|
const TestConfig *config = GetTestConfig(ssl);
|
|
|
|
if (!CheckVerifyCallback(ssl)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
GetTestState(ssl)->cert_verified = true;
|
|
|
|
if (config->verify_fail) {
|
|
|
|
X509_STORE_CTX_set_error(store_ctx, X509_V_ERR_APPLICATION_VERIFICATION);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool LoadCertificate(bssl::UniquePtr<X509> *out_x509,
|
|
|
|
bssl::UniquePtr<STACK_OF(X509)> *out_chain,
|
|
|
|
const std::string &file) {
|
|
|
|
bssl::UniquePtr<BIO> bio(BIO_new(BIO_s_file()));
|
|
|
|
if (!bio || !BIO_read_filename(bio.get(), file.c_str())) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
out_x509->reset(PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr));
|
|
|
|
if (!*out_x509) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
out_chain->reset(sk_X509_new_null());
|
|
|
|
if (!*out_chain) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Keep reading the certificate chain.
|
|
|
|
for (;;) {
|
|
|
|
bssl::UniquePtr<X509> cert(
|
|
|
|
PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr));
|
|
|
|
if (!cert) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!bssl::PushToStack(out_chain->get(), std::move(cert))) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t err = ERR_peek_last_error();
|
|
|
|
if (ERR_GET_LIB(err) != ERR_LIB_PEM ||
|
|
|
|
ERR_GET_REASON(err) != PEM_R_NO_START_LINE) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
ERR_clear_error();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bssl::UniquePtr<EVP_PKEY> LoadPrivateKey(const std::string &file) {
|
|
|
|
bssl::UniquePtr<BIO> bio(BIO_new(BIO_s_file()));
|
|
|
|
if (!bio || !BIO_read_filename(bio.get(), file.c_str())) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
return bssl::UniquePtr<EVP_PKEY>(
|
|
|
|
PEM_read_bio_PrivateKey(bio.get(), NULL, NULL, NULL));
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool GetCertificate(SSL *ssl, bssl::UniquePtr<X509> *out_x509,
|
|
|
|
bssl::UniquePtr<STACK_OF(X509)> *out_chain,
|
|
|
|
bssl::UniquePtr<EVP_PKEY> *out_pkey) {
|
|
|
|
const TestConfig *config = GetTestConfig(ssl);
|
|
|
|
|
|
|
|
if (!config->signing_prefs.empty()) {
|
|
|
|
if (!SSL_set_signing_algorithm_prefs(ssl, config->signing_prefs.data(),
|
|
|
|
config->signing_prefs.size())) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!config->key_file.empty()) {
|
|
|
|
*out_pkey = LoadPrivateKey(config->key_file.c_str());
|
|
|
|
if (!*out_pkey) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!config->cert_file.empty() &&
|
|
|
|
!LoadCertificate(out_x509, out_chain, config->cert_file.c_str())) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!config->ocsp_response.empty() && !config->set_ocsp_in_callback &&
|
|
|
|
!SSL_set_ocsp_response(ssl, (const uint8_t *)config->ocsp_response.data(),
|
|
|
|
config->ocsp_response.size())) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool HexDecode(std::string *out, const std::string &in) {
|
|
|
|
if ((in.size() & 1) != 0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto buf = std::make_unique<uint8_t[]>(in.size() / 2);
|
|
|
|
for (size_t i = 0; i < in.size() / 2; i++) {
|
|
|
|
uint8_t high, low;
|
|
|
|
if (!OPENSSL_fromxdigit(&high, in[i * 2]) ||
|
|
|
|
!OPENSSL_fromxdigit(&low, in[i * 2 + 1])) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
buf[i] = (high << 4) | low;
|
|
|
|
}
|
|
|
|
|
|
|
|
out->assign(reinterpret_cast<const char *>(buf.get()), in.size() / 2);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static std::vector<std::string> SplitParts(const std::string &in,
|
|
|
|
const char delim) {
|
|
|
|
std::vector<std::string> ret;
|
|
|
|
size_t start = 0;
|
|
|
|
|
|
|
|
for (size_t i = 0; i < in.size(); i++) {
|
|
|
|
if (in[i] == delim) {
|
|
|
|
ret.push_back(in.substr(start, i - start));
|
|
|
|
start = i + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ret.push_back(in.substr(start, std::string::npos));
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static std::vector<std::string> DecodeHexStrings(
|
|
|
|
const std::string &hex_strings) {
|
|
|
|
std::vector<std::string> ret;
|
|
|
|
const std::vector<std::string> parts = SplitParts(hex_strings, ',');
|
|
|
|
|
|
|
|
for (const auto &part : parts) {
|
|
|
|
std::string binary;
|
|
|
|
if (!HexDecode(&binary, part)) {
|
|
|
|
fprintf(stderr, "Bad hex string: %s.\n", part.c_str());
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret.push_back(binary);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bssl::UniquePtr<STACK_OF(X509_NAME)> DecodeHexX509Names(
|
|
|
|
const std::string &hex_names) {
|
|
|
|
const std::vector<std::string> der_names = DecodeHexStrings(hex_names);
|
|
|
|
bssl::UniquePtr<STACK_OF(X509_NAME)> ret(sk_X509_NAME_new_null());
|
|
|
|
if (!ret) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const auto &der_name : der_names) {
|
|
|
|
const uint8_t *const data =
|
|
|
|
reinterpret_cast<const uint8_t *>(der_name.data());
|
|
|
|
const uint8_t *derp = data;
|
|
|
|
bssl::UniquePtr<X509_NAME> name(
|
|
|
|
d2i_X509_NAME(nullptr, &derp, der_name.size()));
|
|
|
|
if (!name || derp != data + der_name.size()) {
|
|
|
|
fprintf(stderr, "Failed to parse X509_NAME.\n");
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!bssl::PushToStack(ret.get(), std::move(name))) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool CheckPeerVerifyPrefs(SSL *ssl) {
|
|
|
|
const TestConfig *config = GetTestConfig(ssl);
|
|
|
|
if (!config->expect_peer_verify_prefs.empty()) {
|
|
|
|
const uint16_t *peer_sigalgs;
|
|
|
|
size_t num_peer_sigalgs =
|
|
|
|
SSL_get0_peer_verify_algorithms(ssl, &peer_sigalgs);
|
|
|
|
if (config->expect_peer_verify_prefs.size() != num_peer_sigalgs) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"peer verify preferences length mismatch (got %zu, wanted %zu)\n",
|
|
|
|
num_peer_sigalgs, config->expect_peer_verify_prefs.size());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
for (size_t i = 0; i < num_peer_sigalgs; i++) {
|
|
|
|
if (peer_sigalgs[i] != config->expect_peer_verify_prefs[i]) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"peer verify preference %zu mismatch (got %04x, wanted %04x\n",
|
|
|
|
i, peer_sigalgs[i], config->expect_peer_verify_prefs[i]);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool CheckCertificateRequest(SSL *ssl) {
|
|
|
|
const TestConfig *config = GetTestConfig(ssl);
|
|
|
|
|
|
|
|
if (!CheckPeerVerifyPrefs(ssl)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!config->expect_certificate_types.empty()) {
|
|
|
|
const uint8_t *certificate_types;
|
|
|
|
size_t certificate_types_len =
|
|
|
|
SSL_get0_certificate_types(ssl, &certificate_types);
|
|
|
|
if (certificate_types_len != config->expect_certificate_types.size() ||
|
|
|
|
OPENSSL_memcmp(certificate_types,
|
|
|
|
config->expect_certificate_types.data(),
|
|
|
|
certificate_types_len) != 0) {
|
|
|
|
fprintf(stderr, "certificate types mismatch.\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!config->expect_client_ca_list.empty()) {
|
|
|
|
bssl::UniquePtr<STACK_OF(X509_NAME)> expected =
|
|
|
|
DecodeHexX509Names(config->expect_client_ca_list);
|
|
|
|
const size_t num_expected = sk_X509_NAME_num(expected.get());
|
|
|
|
|
|
|
|
const STACK_OF(X509_NAME) *received = SSL_get_client_CA_list(ssl);
|
|
|
|
const size_t num_received = sk_X509_NAME_num(received);
|
|
|
|
|
|
|
|
if (num_received != num_expected) {
|
Fix the easy -Wformat-signedness errors.
GCC has a warning that complains about even more type mismatches in
printf. Some of these are a bit messy and will be fixed in separate CLs.
This covers the easy ones.
The .*s stuff is unfortunate, but printf has no size_t-clean string
printer. ALPN protocol lengths are bound by uint8_t, so it doesn't
really matter.
The IPv6 printing one is obnoxious and arguably a false positive. It's
really a C language flaw: all types smaller than int get converted to
int when you do arithmetic. So something like this first doesn't
overflow the shift because it computes over int, but then the result
overall is stored as an int.
uint8_t a, b;
(a << 8) | b
On the one hand, this fixes a "missing" cast to uint16_t before the
shift. At the same time, the incorrect final type means passing it to
%x, which expects unsigned int. The compiler has forgotten this value
actually fits in uint16_t and flags a warning. Mitigate this by storing
in a uint16_t first.
The story doesn't quite end here. Arguments passed to variadic functions
go through integer promotion[0], so the argument is still passed to
snprintf as an int! But then va_arg allows for a signedness mismatch[1],
provided the value is representable in both types. The combination means
that %x, though actually paired with unsigned, also accept uint8_t and
uint16_t, because those are guaranteed to promote to an int that meets
[1]. GCC recognizes [1] applies here.
(There's also PRI16x, but that's a bit tedious to use and, in glibc, is
defined as plain "x" anyway.)
[0] https://en.cppreference.com/w/c/language/conversion#Default_argument_promotions
[1] https://en.cppreference.com/w/c/variadic/va_arg
Bug: 450
Change-Id: Ic1d41356755a18ab922956dd2e07b560470341f4
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50765
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
3 years ago
|
|
|
fprintf(stderr, "expected %zu names in CertificateRequest but got %zu.\n",
|
|
|
|
num_expected, num_received);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (size_t i = 0; i < num_received; i++) {
|
|
|
|
if (X509_NAME_cmp(sk_X509_NAME_value(received, i),
|
|
|
|
sk_X509_NAME_value(expected.get(), i)) != 0) {
|
Fix the easy -Wformat-signedness errors.
GCC has a warning that complains about even more type mismatches in
printf. Some of these are a bit messy and will be fixed in separate CLs.
This covers the easy ones.
The .*s stuff is unfortunate, but printf has no size_t-clean string
printer. ALPN protocol lengths are bound by uint8_t, so it doesn't
really matter.
The IPv6 printing one is obnoxious and arguably a false positive. It's
really a C language flaw: all types smaller than int get converted to
int when you do arithmetic. So something like this first doesn't
overflow the shift because it computes over int, but then the result
overall is stored as an int.
uint8_t a, b;
(a << 8) | b
On the one hand, this fixes a "missing" cast to uint16_t before the
shift. At the same time, the incorrect final type means passing it to
%x, which expects unsigned int. The compiler has forgotten this value
actually fits in uint16_t and flags a warning. Mitigate this by storing
in a uint16_t first.
The story doesn't quite end here. Arguments passed to variadic functions
go through integer promotion[0], so the argument is still passed to
snprintf as an int! But then va_arg allows for a signedness mismatch[1],
provided the value is representable in both types. The combination means
that %x, though actually paired with unsigned, also accept uint8_t and
uint16_t, because those are guaranteed to promote to an int that meets
[1]. GCC recognizes [1] applies here.
(There's also PRI16x, but that's a bit tedious to use and, in glibc, is
defined as plain "x" anyway.)
[0] https://en.cppreference.com/w/c/language/conversion#Default_argument_promotions
[1] https://en.cppreference.com/w/c/variadic/va_arg
Bug: 450
Change-Id: Ic1d41356755a18ab922956dd2e07b560470341f4
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50765
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
3 years ago
|
|
|
fprintf(stderr, "names in CertificateRequest differ at index #%zu.\n",
|
|
|
|
i);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const STACK_OF(CRYPTO_BUFFER) *buffers = SSL_get0_server_requested_CAs(ssl);
|
|
|
|
if (sk_CRYPTO_BUFFER_num(buffers) != num_received) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"Mismatch between SSL_get_server_requested_CAs and "
|
|
|
|
"SSL_get_client_CA_list.\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int ClientCertCallback(SSL *ssl, X509 **out_x509, EVP_PKEY **out_pkey) {
|
|
|
|
if (!CheckCertificateRequest(ssl)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (GetTestConfig(ssl)->async && !GetTestState(ssl)->cert_ready) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
bssl::UniquePtr<X509> x509;
|
|
|
|
bssl::UniquePtr<STACK_OF(X509)> chain;
|
|
|
|
bssl::UniquePtr<EVP_PKEY> pkey;
|
|
|
|
if (!GetCertificate(ssl, &x509, &chain, &pkey)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return zero for no certificate.
|
|
|
|
if (!x509) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Chains and asynchronous private keys are not supported with client_cert_cb.
|
|
|
|
*out_x509 = x509.release();
|
|
|
|
*out_pkey = pkey.release();
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssl_private_key_result_t AsyncPrivateKeyComplete(SSL *ssl, uint8_t *out,
|
|
|
|
size_t *out_len,
|
|
|
|
size_t max_out);
|
|
|
|
|
|
|
|
static ssl_private_key_result_t AsyncPrivateKeySign(
|
|
|
|
SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
|
|
|
|
uint16_t signature_algorithm, const uint8_t *in, size_t in_len) {
|
|
|
|
TestState *test_state = GetTestState(ssl);
|
|
|
|
test_state->used_private_key = true;
|
|
|
|
if (!test_state->private_key_result.empty()) {
|
|
|
|
fprintf(stderr, "AsyncPrivateKeySign called with operation pending.\n");
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (EVP_PKEY_id(test_state->private_key.get()) !=
|
|
|
|
SSL_get_signature_algorithm_key_type(signature_algorithm)) {
|
|
|
|
fprintf(stderr, "Key type does not match signature algorithm.\n");
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Determine the hash.
|
|
|
|
const EVP_MD *md = SSL_get_signature_algorithm_digest(signature_algorithm);
|
|
|
|
bssl::ScopedEVP_MD_CTX ctx;
|
|
|
|
EVP_PKEY_CTX *pctx;
|
|
|
|
if (!EVP_DigestSignInit(ctx.get(), &pctx, md, nullptr,
|
|
|
|
test_state->private_key.get())) {
|
|
|
|
return ssl_private_key_failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Configure additional signature parameters.
|
|
|
|
if (SSL_is_signature_algorithm_rsa_pss(signature_algorithm)) {
|
|
|
|
if (!EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) ||
|
|
|
|
!EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1 /* salt len = hash len */)) {
|
|
|
|
return ssl_private_key_failure;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Write the signature into |test_state|.
|
|
|
|
size_t len = 0;
|
|
|
|
if (!EVP_DigestSign(ctx.get(), nullptr, &len, in, in_len)) {
|
|
|
|
return ssl_private_key_failure;
|
|
|
|
}
|
|
|
|
test_state->private_key_result.resize(len);
|
|
|
|
if (!EVP_DigestSign(ctx.get(), test_state->private_key_result.data(), &len,
|
|
|
|
in, in_len)) {
|
|
|
|
return ssl_private_key_failure;
|
|
|
|
}
|
|
|
|
test_state->private_key_result.resize(len);
|
|
|
|
|
|
|
|
return AsyncPrivateKeyComplete(ssl, out, out_len, max_out);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssl_private_key_result_t AsyncPrivateKeyDecrypt(SSL *ssl, uint8_t *out,
|
|
|
|
size_t *out_len,
|
|
|
|
size_t max_out,
|
|
|
|
const uint8_t *in,
|
|
|
|
size_t in_len) {
|
|
|
|
TestState *test_state = GetTestState(ssl);
|
|
|
|
test_state->used_private_key = true;
|
|
|
|
if (!test_state->private_key_result.empty()) {
|
|
|
|
fprintf(stderr, "AsyncPrivateKeyDecrypt called with operation pending.\n");
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
|
|
|
RSA *rsa = EVP_PKEY_get0_RSA(test_state->private_key.get());
|
|
|
|
if (rsa == NULL) {
|
|
|
|
fprintf(stderr, "AsyncPrivateKeyDecrypt called with incorrect key type.\n");
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
test_state->private_key_result.resize(RSA_size(rsa));
|
|
|
|
if (!RSA_decrypt(rsa, out_len, test_state->private_key_result.data(),
|
|
|
|
RSA_size(rsa), in, in_len, RSA_NO_PADDING)) {
|
|
|
|
return ssl_private_key_failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
test_state->private_key_result.resize(*out_len);
|
|
|
|
|
|
|
|
return AsyncPrivateKeyComplete(ssl, out, out_len, max_out);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssl_private_key_result_t AsyncPrivateKeyComplete(SSL *ssl, uint8_t *out,
|
|
|
|
size_t *out_len,
|
|
|
|
size_t max_out) {
|
|
|
|
TestState *test_state = GetTestState(ssl);
|
|
|
|
if (test_state->private_key_result.empty()) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"AsyncPrivateKeyComplete called without operation pending.\n");
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (GetTestConfig(ssl)->async && test_state->private_key_retries < 2) {
|
|
|
|
// Only return the decryption on the second attempt, to test both incomplete
|
|
|
|
// |sign|/|decrypt| and |complete|.
|
|
|
|
return ssl_private_key_retry;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (max_out < test_state->private_key_result.size()) {
|
|
|
|
fprintf(stderr, "Output buffer too small.\n");
|
|
|
|
return ssl_private_key_failure;
|
|
|
|
}
|
|
|
|
OPENSSL_memcpy(out, test_state->private_key_result.data(),
|
|
|
|
test_state->private_key_result.size());
|
|
|
|
*out_len = test_state->private_key_result.size();
|
|
|
|
|
|
|
|
test_state->private_key_result.clear();
|
|
|
|
test_state->private_key_retries = 0;
|
|
|
|
return ssl_private_key_success;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const SSL_PRIVATE_KEY_METHOD g_async_private_key_method = {
|
|
|
|
AsyncPrivateKeySign,
|
|
|
|
AsyncPrivateKeyDecrypt,
|
|
|
|
AsyncPrivateKeyComplete,
|
|
|
|
};
|
|
|
|
|
|
|
|
static bool InstallCertificate(SSL *ssl) {
|
|
|
|
bssl::UniquePtr<X509> x509;
|
|
|
|
bssl::UniquePtr<STACK_OF(X509)> chain;
|
|
|
|
bssl::UniquePtr<EVP_PKEY> pkey;
|
|
|
|
if (!GetCertificate(ssl, &x509, &chain, &pkey)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pkey) {
|
|
|
|
TestState *test_state = GetTestState(ssl);
|
|
|
|
const TestConfig *config = GetTestConfig(ssl);
|
|
|
|
if (config->async || config->handshake_hints) {
|
|
|
|
// Install a custom private key if testing asynchronous callbacks, or if
|
|
|
|
// testing handshake hints. In the handshake hints case, we wish to check
|
|
|
|
// that hints only mismatch when allowed.
|
|
|
|
test_state->private_key = std::move(pkey);
|
|
|
|
SSL_set_private_key_method(ssl, &g_async_private_key_method);
|
|
|
|
} else if (!SSL_use_PrivateKey(ssl, pkey.get())) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (x509 && !SSL_use_certificate(ssl, x509.get())) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sk_X509_num(chain.get()) > 0 && !SSL_set1_chain(ssl, chain.get())) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static enum ssl_select_cert_result_t SelectCertificateCallback(
|
|
|
|
const SSL_CLIENT_HELLO *client_hello) {
|
|
|
|
SSL *ssl = client_hello->ssl;
|
|
|
|
const TestConfig *config = GetTestConfig(ssl);
|
|
|
|
TestState *test_state = GetTestState(ssl);
|
|
|
|
test_state->early_callback_called = true;
|
|
|
|
|
|
|
|
if (!config->expect_server_name.empty()) {
|
|
|
|
const char *server_name =
|
|
|
|
SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
|
|
|
|
if (server_name == nullptr ||
|
|
|
|
std::string(server_name) != config->expect_server_name) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"Server name mismatch in early callback (got %s; want %s).\n",
|
|
|
|
server_name, config->expect_server_name.c_str());
|
|
|
|
return ssl_select_cert_error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (config->fail_early_callback) {
|
|
|
|
return ssl_select_cert_error;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Simulate some asynchronous work in the early callback.
|
|
|
|
if ((config->use_early_callback || test_state->get_handshake_hints_cb) &&
|
|
|
|
config->async && !test_state->early_callback_ready) {
|
|
|
|
return ssl_select_cert_retry;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (test_state->get_handshake_hints_cb &&
|
|
|
|
!test_state->get_handshake_hints_cb(client_hello)) {
|
|
|
|
return ssl_select_cert_error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (config->use_early_callback && !InstallCertificate(ssl)) {
|
|
|
|
return ssl_select_cert_error;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ssl_select_cert_success;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int SetQuicReadSecret(SSL *ssl, enum ssl_encryption_level_t level,
|
|
|
|
const SSL_CIPHER *cipher, const uint8_t *secret,
|
|
|
|
size_t secret_len) {
|
|
|
|
MockQuicTransport *quic_transport = GetTestState(ssl)->quic_transport.get();
|
|
|
|
if (quic_transport == nullptr) {
|
|
|
|
fprintf(stderr, "No QUIC transport.\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return quic_transport->SetReadSecret(level, cipher, secret, secret_len);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int SetQuicWriteSecret(SSL *ssl, enum ssl_encryption_level_t level,
|
|
|
|
const SSL_CIPHER *cipher, const uint8_t *secret,
|
|
|
|
size_t secret_len) {
|
|
|
|
MockQuicTransport *quic_transport = GetTestState(ssl)->quic_transport.get();
|
|
|
|
if (quic_transport == nullptr) {
|
|
|
|
fprintf(stderr, "No QUIC transport.\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return quic_transport->SetWriteSecret(level, cipher, secret, secret_len);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int AddQuicHandshakeData(SSL *ssl, enum ssl_encryption_level_t level,
|
|
|
|
const uint8_t *data, size_t len) {
|
|
|
|
MockQuicTransport *quic_transport = GetTestState(ssl)->quic_transport.get();
|
|
|
|
if (quic_transport == nullptr) {
|
|
|
|
fprintf(stderr, "No QUIC transport.\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return quic_transport->WriteHandshakeData(level, data, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int FlushQuicFlight(SSL *ssl) {
|
|
|
|
MockQuicTransport *quic_transport = GetTestState(ssl)->quic_transport.get();
|
|
|
|
if (quic_transport == nullptr) {
|
|
|
|
fprintf(stderr, "No QUIC transport.\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return quic_transport->Flush();
|
|
|
|
}
|
|
|
|
|
|
|
|
static int SendQuicAlert(SSL *ssl, enum ssl_encryption_level_t level,
|
|
|
|
uint8_t alert) {
|
|
|
|
MockQuicTransport *quic_transport = GetTestState(ssl)->quic_transport.get();
|
|
|
|
if (quic_transport == nullptr) {
|
|
|
|
fprintf(stderr, "No QUIC transport.\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return quic_transport->SendAlert(level, alert);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const SSL_QUIC_METHOD g_quic_method = {
|
|
|
|
SetQuicReadSecret,
|
|
|
|
SetQuicWriteSecret,
|
|
|
|
AddQuicHandshakeData,
|
|
|
|
FlushQuicFlight,
|
|
|
|
SendQuicAlert,
|
|
|
|
};
|
|
|
|
|
|
|
|
static bool MaybeInstallCertCompressionAlg(
|
|
|
|
const TestConfig *config, SSL_CTX *ssl_ctx, uint16_t alg,
|
|
|
|
ssl_cert_compression_func_t compress,
|
|
|
|
ssl_cert_decompression_func_t decompress) {
|
|
|
|
if (!config->install_cert_compression_algs &&
|
|
|
|
config->install_one_cert_compression_alg != alg) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return SSL_CTX_add_cert_compression_alg(ssl_ctx, alg, compress, decompress);
|
|
|
|
}
|
|
|
|
|
|
|
|
bssl::UniquePtr<SSL_CTX> TestConfig::SetupCtx(SSL_CTX *old_ctx) const {
|
|
|
|
bssl::UniquePtr<SSL_CTX> ssl_ctx(
|
|
|
|
SSL_CTX_new(is_dtls ? DTLS_method() : TLS_method()));
|
|
|
|
if (!ssl_ctx) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
SSL_CTX_set0_buffer_pool(ssl_ctx.get(), BufferPool());
|
|
|
|
|
|
|
|
std::string cipher_list = "ALL:TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256";
|
|
|
|
if (!cipher.empty()) {
|
|
|
|
cipher_list = cipher;
|
|
|
|
SSL_CTX_set_options(ssl_ctx.get(), SSL_OP_CIPHER_SERVER_PREFERENCE);
|
|
|
|
}
|
|
|
|
if (!SSL_CTX_set_strict_cipher_list(ssl_ctx.get(), cipher_list.c_str())) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (async && is_server) {
|
|
|
|
// Disable the internal session cache. To test asynchronous session lookup,
|
|
|
|
// we use an external session cache.
|
|
|
|
SSL_CTX_set_session_cache_mode(
|
|
|
|
ssl_ctx.get(), SSL_SESS_CACHE_BOTH | SSL_SESS_CACHE_NO_INTERNAL);
|
|
|
|
SSL_CTX_sess_set_get_cb(ssl_ctx.get(), GetSessionCallback);
|
|
|
|
} else {
|
|
|
|
SSL_CTX_set_session_cache_mode(ssl_ctx.get(), SSL_SESS_CACHE_BOTH);
|
|
|
|
}
|
|
|
|
|
|
|
|
SSL_CTX_set_select_certificate_cb(ssl_ctx.get(), SelectCertificateCallback);
|
|
|
|
|
|
|
|
if (use_old_client_cert_callback) {
|
|
|
|
SSL_CTX_set_client_cert_cb(ssl_ctx.get(), ClientCertCallback);
|
|
|
|
}
|
|
|
|
|
|
|
|
SSL_CTX_set_next_protos_advertised_cb(ssl_ctx.get(),
|
|
|
|
NextProtosAdvertisedCallback, NULL);
|
|
|
|
if (!select_next_proto.empty()) {
|
|
|
|
SSL_CTX_set_next_proto_select_cb(ssl_ctx.get(), NextProtoSelectCallback,
|
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!select_alpn.empty() || decline_alpn || reject_alpn ||
|
|
|
|
select_empty_alpn) {
|
|
|
|
SSL_CTX_set_alpn_select_cb(ssl_ctx.get(), AlpnSelectCallback, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
SSL_CTX_set_current_time_cb(ssl_ctx.get(), CurrentTimeCallback);
|
|
|
|
|
|
|
|
SSL_CTX_set_info_callback(ssl_ctx.get(), InfoCallback);
|
|
|
|
SSL_CTX_sess_set_new_cb(ssl_ctx.get(), NewSessionCallback);
|
|
|
|
|
|
|
|
if (use_ticket_callback || handshake_hints) {
|
|
|
|
// If using handshake hints, always enable the ticket callback, so we can
|
|
|
|
// check that hints only mismatch when allowed. The ticket callback also
|
|
|
|
// uses a constant key, which simplifies the test.
|
|
|
|
SSL_CTX_set_tlsext_ticket_key_cb(ssl_ctx.get(), TicketKeyCallback);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!use_custom_verify_callback) {
|
|
|
|
SSL_CTX_set_cert_verify_callback(ssl_ctx.get(), CertVerifyCallback, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!signed_cert_timestamps.empty() &&
|
|
|
|
!SSL_CTX_set_signed_cert_timestamp_list(
|
|
|
|
ssl_ctx.get(), (const uint8_t *)signed_cert_timestamps.data(),
|
|
|
|
signed_cert_timestamps.size())) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!use_client_ca_list.empty()) {
|
|
|
|
if (use_client_ca_list == "<NULL>") {
|
|
|
|
SSL_CTX_set_client_CA_list(ssl_ctx.get(), nullptr);
|
|
|
|
} else if (use_client_ca_list == "<EMPTY>") {
|
|
|
|
bssl::UniquePtr<STACK_OF(X509_NAME)> names;
|
|
|
|
SSL_CTX_set_client_CA_list(ssl_ctx.get(), names.release());
|
|
|
|
} else {
|
|
|
|
bssl::UniquePtr<STACK_OF(X509_NAME)> names =
|
|
|
|
DecodeHexX509Names(use_client_ca_list);
|
|
|
|
SSL_CTX_set_client_CA_list(ssl_ctx.get(), names.release());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (enable_grease) {
|
|
|
|
SSL_CTX_set_grease_enabled(ssl_ctx.get(), 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (permute_extensions) {
|
|
|
|
SSL_CTX_set_permute_extensions(ssl_ctx.get(), 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!expect_server_name.empty()) {
|
|
|
|
SSL_CTX_set_tlsext_servername_callback(ssl_ctx.get(), ServerNameCallback);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (enable_early_data) {
|
|
|
|
SSL_CTX_set_early_data_enabled(ssl_ctx.get(), 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (allow_unknown_alpn_protos) {
|
|
|
|
SSL_CTX_set_allow_unknown_alpn_protos(ssl_ctx.get(), 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!verify_prefs.empty()) {
|
|
|
|
if (!SSL_CTX_set_verify_algorithm_prefs(ssl_ctx.get(), verify_prefs.data(),
|
|
|
|
verify_prefs.size())) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SSL_CTX_set_msg_callback(ssl_ctx.get(), MessageCallback);
|
|
|
|
|
|
|
|
if (allow_false_start_without_alpn) {
|
|
|
|
SSL_CTX_set_false_start_allowed_without_alpn(ssl_ctx.get(), 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (use_ocsp_callback) {
|
|
|
|
SSL_CTX_set_tlsext_status_cb(ssl_ctx.get(), LegacyOCSPCallback);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (old_ctx) {
|
|
|
|
uint8_t keys[48];
|
|
|
|
if (!SSL_CTX_get_tlsext_ticket_keys(old_ctx, &keys, sizeof(keys)) ||
|
|
|
|
!SSL_CTX_set_tlsext_ticket_keys(ssl_ctx.get(), keys, sizeof(keys))) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
CopySessions(ssl_ctx.get(), old_ctx);
|
|
|
|
} else if (!ticket_key.empty() &&
|
|
|
|
!SSL_CTX_set_tlsext_ticket_keys(ssl_ctx.get(), ticket_key.data(),
|
|
|
|
ticket_key.size())) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// These mock compression algorithms match the corresponding ones in
|
|
|
|
// |addCertCompressionTests|.
|
|
|
|
if (!MaybeInstallCertCompressionAlg(
|
|
|
|
this, ssl_ctx.get(), 0xff02,
|
|
|
|
[](SSL *ssl, CBB *out, const uint8_t *in, size_t in_len) -> int {
|
|
|
|
if (!CBB_add_u8(out, 1) || !CBB_add_u8(out, 2) ||
|
|
|
|
!CBB_add_u8(out, 3) || !CBB_add_u8(out, 4) ||
|
|
|
|
!CBB_add_bytes(out, in, in_len)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
},
|
|
|
|
[](SSL *ssl, CRYPTO_BUFFER **out, size_t uncompressed_len,
|
|
|
|
const uint8_t *in, size_t in_len) -> int {
|
|
|
|
if (in_len < 4 || in[0] != 1 || in[1] != 2 || in[2] != 3 ||
|
|
|
|
in[3] != 4 || uncompressed_len != in_len - 4) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
const bssl::Span<const uint8_t> uncompressed(in + 4, in_len - 4);
|
|
|
|
*out = CRYPTO_BUFFER_new(uncompressed.data(), uncompressed.size(),
|
|
|
|
nullptr);
|
|
|
|
return *out != nullptr;
|
|
|
|
}) ||
|
|
|
|
!MaybeInstallCertCompressionAlg(
|
|
|
|
this, ssl_ctx.get(), 0xff01,
|
|
|
|
[](SSL *ssl, CBB *out, const uint8_t *in, size_t in_len) -> int {
|
|
|
|
if (in_len < 2 || in[0] != 0 || in[1] != 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return CBB_add_bytes(out, in + 2, in_len - 2);
|
|
|
|
},
|
|
|
|
[](SSL *ssl, CRYPTO_BUFFER **out, size_t uncompressed_len,
|
|
|
|
const uint8_t *in, size_t in_len) -> int {
|
|
|
|
if (uncompressed_len != 2 + in_len) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
auto buf = std::make_unique<uint8_t[]>(2 + in_len);
|
|
|
|
buf[0] = 0;
|
|
|
|
buf[1] = 0;
|
|
|
|
OPENSSL_memcpy(&buf[2], in, in_len);
|
|
|
|
*out = CRYPTO_BUFFER_new(buf.get(), 2 + in_len, nullptr);
|
|
|
|
return *out != nullptr;
|
|
|
|
}) ||
|
|
|
|
!MaybeInstallCertCompressionAlg(
|
|
|
|
this, ssl_ctx.get(), 0xff03,
|
|
|
|
[](SSL *ssl, CBB *out, const uint8_t *in, size_t in_len) -> int {
|
|
|
|
uint8_t byte;
|
|
|
|
return RAND_bytes(&byte, 1) && //
|
|
|
|
CBB_add_u8(out, byte) && //
|
|
|
|
CBB_add_bytes(out, in, in_len);
|
|
|
|
},
|
|
|
|
[](SSL *ssl, CRYPTO_BUFFER **out, size_t uncompressed_len,
|
|
|
|
const uint8_t *in, size_t in_len) -> int {
|
|
|
|
if (uncompressed_len + 1 != in_len) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
*out = CRYPTO_BUFFER_new(in + 1, in_len - 1, nullptr);
|
|
|
|
return *out != nullptr;
|
|
|
|
})) {
|
|
|
|
fprintf(stderr, "SSL_CTX_add_cert_compression_alg failed.\n");
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (server_preference) {
|
|
|
|
SSL_CTX_set_options(ssl_ctx.get(), SSL_OP_CIPHER_SERVER_PREFERENCE);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_quic) {
|
|
|
|
SSL_CTX_set_quic_method(ssl_ctx.get(), &g_quic_method);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ssl_ctx;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int DDoSCallback(const SSL_CLIENT_HELLO *client_hello) {
|
|
|
|
const TestConfig *config = GetTestConfig(client_hello->ssl);
|
|
|
|
return config->fail_ddos_callback ? 0 : 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned PskClientCallback(SSL *ssl, const char *hint,
|
|
|
|
char *out_identity, unsigned max_identity_len,
|
|
|
|
uint8_t *out_psk, unsigned max_psk_len) {
|
|
|
|
const TestConfig *config = GetTestConfig(ssl);
|
|
|
|
|
|
|
|
if (config->psk_identity.empty()) {
|
|
|
|
if (hint != nullptr) {
|
|
|
|
fprintf(stderr, "Server PSK hint was non-null.\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else if (hint == nullptr ||
|
|
|
|
strcmp(hint, config->psk_identity.c_str()) != 0) {
|
|
|
|
fprintf(stderr, "Server PSK hint did not match.\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Account for the trailing '\0' for the identity.
|
|
|
|
if (config->psk_identity.size() >= max_identity_len ||
|
|
|
|
config->psk.size() > max_psk_len) {
|
|
|
|
fprintf(stderr, "PSK buffers too small.\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
OPENSSL_strlcpy(out_identity, config->psk_identity.c_str(), max_identity_len);
|
|
|
|
OPENSSL_memcpy(out_psk, config->psk.data(), config->psk.size());
|
|
|
|
return static_cast<unsigned>(config->psk.size());
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned PskServerCallback(SSL *ssl, const char *identity,
|
|
|
|
uint8_t *out_psk, unsigned max_psk_len) {
|
|
|
|
const TestConfig *config = GetTestConfig(ssl);
|
|
|
|
|
|
|
|
if (strcmp(identity, config->psk_identity.c_str()) != 0) {
|
|
|
|
fprintf(stderr, "Client PSK identity did not match.\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (config->psk.size() > max_psk_len) {
|
|
|
|
fprintf(stderr, "PSK buffers too small.\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
OPENSSL_memcpy(out_psk, config->psk.data(), config->psk.size());
|
|
|
|
return static_cast<unsigned>(config->psk.size());
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssl_verify_result_t CustomVerifyCallback(SSL *ssl, uint8_t *out_alert) {
|
|
|
|
const TestConfig *config = GetTestConfig(ssl);
|
|
|
|
if (!CheckVerifyCallback(ssl)) {
|
|
|
|
return ssl_verify_invalid;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (config->async && !GetTestState(ssl)->custom_verify_ready) {
|
|
|
|
return ssl_verify_retry;
|
|
|
|
}
|
|
|
|
|
|
|
|
GetTestState(ssl)->cert_verified = true;
|
|
|
|
if (config->verify_fail) {
|
|
|
|
return ssl_verify_invalid;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ssl_verify_ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int CertCallback(SSL *ssl, void *arg) {
|
|
|
|
const TestConfig *config = GetTestConfig(ssl);
|
|
|
|
|
|
|
|
// Check the peer certificate metadata is as expected.
|
|
|
|
if ((!SSL_is_server(ssl) && !CheckCertificateRequest(ssl)) ||
|
|
|
|
!CheckPeerVerifyPrefs(ssl)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (config->fail_cert_callback) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The certificate will be installed via other means.
|
|
|
|
if (!config->async || config->use_early_callback) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!GetTestState(ssl)->cert_ready) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (!InstallCertificate(ssl)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
bssl::UniquePtr<SSL> TestConfig::NewSSL(
|
|
|
|
SSL_CTX *ssl_ctx, SSL_SESSION *session,
|
|
|
|
std::unique_ptr<TestState> test_state) const {
|
|
|
|
bssl::UniquePtr<SSL> ssl(SSL_new(ssl_ctx));
|
|
|
|
if (!ssl) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!SetTestConfig(ssl.get(), this)) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
if (test_state != nullptr) {
|
|
|
|
if (!SetTestState(ssl.get(), std::move(test_state))) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fallback_scsv && !SSL_set_mode(ssl.get(), SSL_MODE_SEND_FALLBACK_SCSV)) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
// Install the certificate synchronously if nothing else will handle it.
|
|
|
|
if (!use_early_callback && !use_old_client_cert_callback && !async &&
|
|
|
|
!InstallCertificate(ssl.get())) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
if (!use_old_client_cert_callback) {
|
|
|
|
SSL_set_cert_cb(ssl.get(), CertCallback, nullptr);
|
|
|
|
}
|
|
|
|
int mode = SSL_VERIFY_NONE;
|
|
|
|
if (require_any_client_certificate) {
|
|
|
|
mode = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
|
|
|
|
}
|
|
|
|
if (verify_peer) {
|
|
|
|
mode = SSL_VERIFY_PEER;
|
|
|
|
}
|
|
|
|
if (verify_peer_if_no_obc) {
|
|
|
|
// Set SSL_VERIFY_FAIL_IF_NO_PEER_CERT so testing whether client
|
|
|
|
// certificates were requested is easy.
|
|
|
|
mode = SSL_VERIFY_PEER | SSL_VERIFY_PEER_IF_NO_OBC |
|
|
|
|
SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
|
|
|
|
}
|
|
|
|
if (use_custom_verify_callback) {
|
|
|
|
SSL_set_custom_verify(ssl.get(), mode, CustomVerifyCallback);
|
|
|
|
} else if (mode != SSL_VERIFY_NONE) {
|
|
|
|
SSL_set_verify(ssl.get(), mode, NULL);
|
|
|
|
}
|
|
|
|
if (false_start) {
|
|
|
|
SSL_set_mode(ssl.get(), SSL_MODE_ENABLE_FALSE_START);
|
|
|
|
}
|
|
|
|
if (cbc_record_splitting) {
|
|
|
|
SSL_set_mode(ssl.get(), SSL_MODE_CBC_RECORD_SPLITTING);
|
|
|
|
}
|
|
|
|
if (partial_write) {
|
|
|
|
SSL_set_mode(ssl.get(), SSL_MODE_ENABLE_PARTIAL_WRITE);
|
|
|
|
}
|
|
|
|
if (reverify_on_resume) {
|
|
|
|
SSL_CTX_set_reverify_on_resume(ssl_ctx, 1);
|
|
|
|
}
|
Default SSL_set_enforce_rsa_key_usage to enabled.
This relands
https://boringssl-review.googlesource.com/c/boringssl/+/54606, which was
temporarily reverted.
Update-Note: By default, clients will now require RSA server
certificates used in TLS 1.2 and earlier to include the keyEncipherment
or digitalSignature bit. keyEncipherment is required if using RSA key
exchange. digitalSignature is required if using ECDHE_RSA key exchange.
If unsure, TLS RSA server signatures should include both, but some
deployments may wish to include only one if separating keys, or simply
disabling RSA key exchange. The latter is useful to mitigate either the
Bleichenbacher attack (from 1998, most recently resurfaced in 2017 as
ROBOT), or to strengthen TLS 1.3 downgrade protections, which is
particularly important for enterprise environments using client
certificates (aka "mTLS") because, prior to TLS 1.3, the TLS client
certificate flow was insufficiently encrypted or authenticated. Without
reflecting an RSA key exchange disable into key usage, and then the
client checking it, an attacker can spoof a CertificateRequest as coming
from some server.
This aligns with standard security requirements for using X.509
certificates, specified in RFC 5280, section 4.2.1.3, and reiterated in
TLS as early as TLS 1.0, RFC 2246, section 7.4.2, published 24 years ago
on January 1999. Constraints on usage of keys are important to mitigate
cross-protocol attacks, a class of cryptographic attacks that is
well-studied in the literature.
We already checked this for each of ECDSA, TLS 1.3, and servers
verifying client certificates, so this just fills in the remaining hole.
As a result, this change is also important for avoiding some weird
behaviors when configuration changes transition a server in or out of
this hole. (We've seen connection failures get misattributed to TLS 1.3
when it was really a certificate misconfiguration.)
Chrome has also enforced this for some time with publicly-trusted
certificates. As a temporary measure for callers that need more time,
the SSL_set_enforce_rsa_key_usage API, added to BoringSSL in January
2019, still exists where we need to turn this off.
Fixed: 519
Change-Id: I91bf2cfb04c92aec7875e640f90ba6f837146dc1
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/58805
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Bob Beck <bbe@google.com>
2 years ago
|
|
|
if (ignore_rsa_key_usage) {
|
|
|
|
SSL_set_enforce_rsa_key_usage(ssl.get(), 0);
|
|
|
|
}
|
Check client certificate types in TLS <= 1.2
TLS <= 1.2 servers indicate supported client certificate key types with
a certificate_types field in the CertificateRequest. Historically, we've
just ignored this field, because we've always outsourced certificate
selection to the caller anyway. This meant that, if you configured an
RSA client certificate in response to a server that requested only ECDSA
certificates, we would happily send the certificate and leave it to the
server to decide if it was happy.
Strictly speaking, this was in violation of RFC 5246:
- The end-entity certificate provided by the client MUST contain a
key that is compatible with certificate_types. [...]
Although prior TLS versions didn't say anything useful about this either
way.
Once we move certificate selection into the library, we'll want to start
evaluating supported algorithms ourselves. A natural implementation of
it will, as a side effect, cause us to enforce this match, even when
only a single certificate is configured. Since this is unlikely to have
any real compatibility impact (every TLS server I've seen just hardcodes
this list), let's just try turning it on. On the off chance it does
break someone, I've left a flag, SSL_set_check_client_certificate_type,
for folks to turn this check off. The flag will most likely be
unnecessary, in which case we can retire it after a few months.
If this does cause a problem, we can opt to turn it off for the default
certificate, or only enable it when multiple certificates are
configured, or lean on the sigalgs list (doesn't work for 1.0/1.1), but
these all result in some slightly suboptimal behavior, so I think we
should treat them as contingency plans.
Update-Note: A TLS 1.2 (or below) client, using client certificates,
connecting to a TLS server which doesn't support its certificate type
will now fail the connection slightly earlier, rather than sending the
certificate and waiting for the server to reject it. The connection
should fail either way, but now it will fail earlier with
SSL_R_UNKNOWN_CERTIFICATE_TYPE. If the server was buggy and did not
correctly advertise its own capabilities (very very unlikely), this may
cause a connection to fail despite previously succeeding. We have
included a temporary API, SSL_set_check_client_certificate_type, to
disable this behavior in the unlikely event this has any impact, but
please contact the BoringSSL team if you need it, as it will interfere
with improvements down the line.
This change does not affect servers requesting client certificates, only
clients sending them.
Bug: 249
Change-Id: I159bc444c4ee79fbe5c476d4253b48d58d2538be
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/66687
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Bob Beck <bbe@google.com>
9 months ago
|
|
|
if (no_check_client_certificate_type) {
|
|
|
|
SSL_set_check_client_certificate_type(ssl.get(), 0);
|
|
|
|
}
|
|
|
|
if (no_tls13) {
|
|
|
|
SSL_set_options(ssl.get(), SSL_OP_NO_TLSv1_3);
|
|
|
|
}
|
|
|
|
if (no_tls12) {
|
|
|
|
SSL_set_options(ssl.get(), SSL_OP_NO_TLSv1_2);
|
|
|
|
}
|
|
|
|
if (no_tls11) {
|
|
|
|
SSL_set_options(ssl.get(), SSL_OP_NO_TLSv1_1);
|
|
|
|
}
|
|
|
|
if (no_tls1) {
|
|
|
|
SSL_set_options(ssl.get(), SSL_OP_NO_TLSv1);
|
|
|
|
}
|
|
|
|
if (no_ticket) {
|
|
|
|
SSL_set_options(ssl.get(), SSL_OP_NO_TICKET);
|
|
|
|
}
|
|
|
|
if (!expect_channel_id.empty() || enable_channel_id) {
|
|
|
|
SSL_set_tls_channel_id_enabled(ssl.get(), 1);
|
|
|
|
}
|
|
|
|
if (enable_ech_grease) {
|
|
|
|
SSL_set_enable_ech_grease(ssl.get(), 1);
|
|
|
|
}
|
|
|
|
if (static_cast<int>(fips_202205) + static_cast<int>(wpa_202304) > 1) {
|
|
|
|
fprintf(stderr, "Multiple policy options given\n");
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
if (fips_202205 && !SSL_set_compliance_policy(
|
|
|
|
ssl.get(), ssl_compliance_policy_fips_202205)) {
|
|
|
|
fprintf(stderr, "SSL_set_compliance_policy failed\n");
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
if (wpa_202304 && !SSL_set_compliance_policy(
|
|
|
|
ssl.get(), ssl_compliance_policy_wpa3_192_202304)) {
|
|
|
|
fprintf(stderr, "SSL_set_compliance_policy failed\n");
|
|
|
|
return nullptr;
|
|
|
|
}
|
Add most of an ECH client implementation.
Based on an initial implementation by Dan McArdle at
https://boringssl-review.googlesource.com/c/boringssl/+/46784
This CL contains most of a client implementation for
draft-ietf-tls-esni-10. The pieces missing so far, which will be done in
follow-up CLs are:
1. While the ClientHelloInner is padded, the server Certificate message
is not. I'll add that once we resolve the spec discussions on how to
do that. (We were originally going to use TLS record-level padding,
but that doesn't work well with QUIC.)
2. The client should check the public name is a valid DNS name before
copying it into ClientHelloOuter.server_name.
3. The ClientHelloOuter handshake flow is not yet implemented. This CL
can detect when the server selects ClientHelloOuter, but for now the
handshake immediately fails. A follow-up CL will remove that logic
and instead add the APIs and extra checks needed.
Otherwise, this should be complete, including padding and compression.
The main interesting point design-wise is that we run through
ClientHello construction multiple times. We need to construct
ClientHelloInner and ClientHelloOuter. Then each of those has slight
variants: EncodedClientHelloInner is the compressed form, and
ClientHelloOuterAAD just has the ECH extension erased to avoid a
circular dependency.
I've computed ClientHelloInner and EncodedClientHelloInner concurrently
because the compression scheme requires shifting the extensions around
to be contiguous. However, I've computed ClientHelloOuterAAD and
ClientHelloOuter by running through the logic twice. This probably can
be done better, but the next draft revises the construction anyway, so
I'm thinking I'll rework it then. (In the next draft, we use a
placeholder payload of the same length, so we can construct the
ClientHello once and fill in the payload.)
Additionally, now that we have a client available in ssl_test, this adds
a threading test to confirm that SSL_CTX_set1_ech_keys is properly
synchronized. (Confirmed that, if I drop the lock in
SSL_CTX_set1_ech_keys, TSan notices.)
Change-Id: Icaff68b595035bdcc73c468ff638e67c84239ef4
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/48004
Reviewed-by: Adam Langley <agl@google.com>
4 years ago
|
|
|
if (!ech_config_list.empty() &&
|
|
|
|
!SSL_set1_ech_config_list(
|
|
|
|
ssl.get(), reinterpret_cast<const uint8_t *>(ech_config_list.data()),
|
|
|
|
ech_config_list.size())) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
if (ech_server_configs.size() != ech_server_keys.size() ||
|
|
|
|
ech_server_configs.size() != ech_is_retry_config.size()) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"-ech-server-config, -ech-server-key, and -ech-is-retry-config "
|
|
|
|
"flags must match.\n");
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
if (!ech_server_configs.empty()) {
|
|
|
|
bssl::UniquePtr<SSL_ECH_KEYS> keys(SSL_ECH_KEYS_new());
|
|
|
|
if (!keys) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
for (size_t i = 0; i < ech_server_configs.size(); i++) {
|
|
|
|
const std::string &ech_config = ech_server_configs[i];
|
|
|
|
const std::string &ech_private_key = ech_server_keys[i];
|
|
|
|
const int is_retry_config = ech_is_retry_config[i];
|
|
|
|
bssl::ScopedEVP_HPKE_KEY key;
|
|
|
|
if (!EVP_HPKE_KEY_init(
|
|
|
|
key.get(), EVP_hpke_x25519_hkdf_sha256(),
|
|
|
|
reinterpret_cast<const uint8_t *>(ech_private_key.data()),
|
|
|
|
ech_private_key.size()) ||
|
|
|
|
!SSL_ECH_KEYS_add(
|
|
|
|
keys.get(), is_retry_config,
|
|
|
|
reinterpret_cast<const uint8_t *>(ech_config.data()),
|
|
|
|
ech_config.size(), key.get())) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!SSL_CTX_set1_ech_keys(ssl_ctx, keys.get())) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!send_channel_id.empty()) {
|
|
|
|
bssl::UniquePtr<EVP_PKEY> pkey = LoadPrivateKey(send_channel_id);
|
|
|
|
if (!pkey || !SSL_set1_tls_channel_id(ssl.get(), pkey.get())) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!host_name.empty() &&
|
|
|
|
!SSL_set_tlsext_host_name(ssl.get(), host_name.c_str())) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
if (!advertise_alpn.empty() &&
|
|
|
|
SSL_set_alpn_protos(
|
|
|
|
ssl.get(), reinterpret_cast<const uint8_t *>(advertise_alpn.data()),
|
|
|
|
advertise_alpn.size()) != 0) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
if (!defer_alps) {
|
|
|
|
for (const auto &pair : application_settings) {
|
|
|
|
if (!SSL_add_application_settings(
|
|
|
|
ssl.get(), reinterpret_cast<const uint8_t *>(pair.first.data()),
|
|
|
|
pair.first.size(),
|
|
|
|
reinterpret_cast<const uint8_t *>(pair.second.data()),
|
|
|
|
pair.second.size())) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!psk.empty()) {
|
|
|
|
SSL_set_psk_client_callback(ssl.get(), PskClientCallback);
|
|
|
|
SSL_set_psk_server_callback(ssl.get(), PskServerCallback);
|
|
|
|
}
|
|
|
|
if (!psk_identity.empty() &&
|
|
|
|
!SSL_use_psk_identity_hint(ssl.get(), psk_identity.c_str())) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
if (!srtp_profiles.empty() &&
|
|
|
|
!SSL_set_srtp_profiles(ssl.get(), srtp_profiles.c_str())) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
if (enable_ocsp_stapling) {
|
|
|
|
SSL_enable_ocsp_stapling(ssl.get());
|
|
|
|
}
|
|
|
|
if (enable_signed_cert_timestamps) {
|
|
|
|
SSL_enable_signed_cert_timestamps(ssl.get());
|
|
|
|
}
|
|
|
|
if (min_version != 0 &&
|
|
|
|
!SSL_set_min_proto_version(ssl.get(), min_version)) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
if (max_version != 0 &&
|
|
|
|
!SSL_set_max_proto_version(ssl.get(), max_version)) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
if (mtu != 0) {
|
|
|
|
SSL_set_options(ssl.get(), SSL_OP_NO_QUERY_MTU);
|
|
|
|
SSL_set_mtu(ssl.get(), mtu);
|
|
|
|
}
|
|
|
|
if (install_ddos_callback) {
|
|
|
|
SSL_CTX_set_dos_protection_cb(ssl_ctx, DDoSCallback);
|
|
|
|
}
|
|
|
|
SSL_set_shed_handshake_config(ssl.get(), true);
|
|
|
|
if (renegotiate_once) {
|
|
|
|
SSL_set_renegotiate_mode(ssl.get(), ssl_renegotiate_once);
|
|
|
|
}
|
|
|
|
if (renegotiate_freely || forbid_renegotiation_after_handshake) {
|
|
|
|
// |forbid_renegotiation_after_handshake| will disable renegotiation later.
|
|
|
|
SSL_set_renegotiate_mode(ssl.get(), ssl_renegotiate_freely);
|
|
|
|
}
|
|
|
|
if (renegotiate_ignore) {
|
|
|
|
SSL_set_renegotiate_mode(ssl.get(), ssl_renegotiate_ignore);
|
|
|
|
}
|
|
|
|
if (renegotiate_explicit) {
|
|
|
|
SSL_set_renegotiate_mode(ssl.get(), ssl_renegotiate_explicit);
|
|
|
|
}
|
|
|
|
if (!check_close_notify) {
|
|
|
|
SSL_set_quiet_shutdown(ssl.get(), 1);
|
|
|
|
}
|
Align NIDs vs group IDs in TLS group APIs
Right now we use NIDs to configure the group list, but group IDs (the
TLS codepoints) to return the negotiated group. The NIDs come from
OpenSSL, while the group ID was original our API. OpenSSL has since
added SSL_get_negotiated_group, but we don't implement it.
To add Kyber to QUIC, we'll need to add an API for configuring groups to
QUICHE. Carrying over our inconsistency into QUICHE's public API would
be unfortunate, so let's use this as the time to align things.
We could either align with OpenSSL and say NIDs are now the group
representation at the public API, or we could add a parallel group ID
API. (Or we could make a whole new SSL_NAMED_GROUP object to pattern
after SSL_CIPHER, which isn't wrong, but is even more new APIs.)
Aligning with OpenSSL would be fewer APIs, but NIDs aren't a great
representation. The numbers are ad-hoc and even diverge a bit between
OpenSSL and BoringSSL. The TLS codepoints are better to export out to
callers. Also QUICHE has exported the negotiated group using the
codepoints, so the natural solution would be to use codepoints on input
too.
Thus, this CL adds SSL_CTX_set1_group_ids and SSL_set1_group_ids. It
also rearranges the API docs slightly to put the group ID ones first,
and leaves a little note about the NID representation before introducing
those.
While I'm here, I've added SSL_get_negotiated_group. NGINX seems to use
it when available, so we may as well fill in that unnecessary
compatibility hole.
Bug: chromium:1442377
Change-Id: I47ca8ae52c274133f28da9893aed7fc70f942bf8
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/60208
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
1 year ago
|
|
|
if (!curves.empty() &&
|
|
|
|
!SSL_set1_group_ids(ssl.get(), curves.data(), curves.size())) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
if (initial_timeout_duration_ms > 0) {
|
|
|
|
DTLSv1_set_initial_timeout_duration(ssl.get(), initial_timeout_duration_ms);
|
|
|
|
}
|
|
|
|
if (max_cert_list > 0) {
|
|
|
|
SSL_set_max_cert_list(ssl.get(), max_cert_list);
|
|
|
|
}
|
|
|
|
if (retain_only_sha256_client_cert) {
|
|
|
|
SSL_set_retain_only_sha256_of_client_certs(ssl.get(), 1);
|
|
|
|
}
|
|
|
|
if (max_send_fragment > 0) {
|
|
|
|
SSL_set_max_send_fragment(ssl.get(), max_send_fragment);
|
|
|
|
}
|
|
|
|
if (alps_use_new_codepoint) {
|
|
|
|
SSL_set_alps_use_new_codepoint(ssl.get(), 1);
|
|
|
|
}
|
|
|
|
if (quic_use_legacy_codepoint != -1) {
|
|
|
|
SSL_set_quic_use_legacy_codepoint(ssl.get(), quic_use_legacy_codepoint);
|
|
|
|
}
|
|
|
|
if (!quic_transport_params.empty()) {
|
|
|
|
if (!SSL_set_quic_transport_params(
|
|
|
|
ssl.get(),
|
|
|
|
reinterpret_cast<const uint8_t *>(quic_transport_params.data()),
|
|
|
|
quic_transport_params.size())) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (jdk11_workaround) {
|
|
|
|
SSL_set_jdk11_workaround(ssl.get(), 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (session != NULL) {
|
|
|
|
if (!is_server) {
|
|
|
|
if (SSL_set_session(ssl.get(), session) != 1) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
} else if (async) {
|
|
|
|
// The internal session cache is disabled, so install the session
|
|
|
|
// manually.
|
|
|
|
SSL_SESSION_up_ref(session);
|
|
|
|
GetTestState(ssl.get())->pending_session.reset(session);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!delegated_credential.empty()) {
|
|
|
|
std::string::size_type comma = delegated_credential.find(',');
|
|
|
|
if (comma == std::string::npos) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"failed to find comma in delegated credential argument.\n");
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
const std::string dc_hex = delegated_credential.substr(0, comma);
|
|
|
|
const std::string pkcs8_hex = delegated_credential.substr(comma + 1);
|
|
|
|
std::string dc, pkcs8;
|
|
|
|
if (!HexDecode(&dc, dc_hex) || !HexDecode(&pkcs8, pkcs8_hex)) {
|
|
|
|
fprintf(stderr, "failed to hex decode delegated credential argument.\n");
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
CBS dc_cbs(bssl::Span<const uint8_t>(
|
|
|
|
reinterpret_cast<const uint8_t *>(dc.data()), dc.size()));
|
|
|
|
CBS pkcs8_cbs(bssl::Span<const uint8_t>(
|
|
|
|
reinterpret_cast<const uint8_t *>(pkcs8.data()), pkcs8.size()));
|
|
|
|
|
|
|
|
bssl::UniquePtr<EVP_PKEY> priv(EVP_parse_private_key(&pkcs8_cbs));
|
|
|
|
if (!priv) {
|
|
|
|
fprintf(stderr, "failed to parse delegated credential private key.\n");
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
bssl::UniquePtr<CRYPTO_BUFFER> dc_buf(
|
|
|
|
CRYPTO_BUFFER_new_from_CBS(&dc_cbs, nullptr));
|
|
|
|
if (!SSL_set1_delegated_credential(ssl.get(), dc_buf.get(),
|
|
|
|
priv.get(), nullptr)) {
|
|
|
|
fprintf(stderr, "SSL_set1_delegated_credential failed.\n");
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!quic_early_data_context.empty() &&
|
|
|
|
!SSL_set_quic_early_data_context(
|
|
|
|
ssl.get(),
|
|
|
|
reinterpret_cast<const uint8_t *>(quic_early_data_context.data()),
|
|
|
|
quic_early_data_context.size())) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ssl;
|
|
|
|
}
|