crl_ssl_transport_security_test.cc
Go to the documentation of this file.
1 // Copyright 2021 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <stdbool.h>
16 #include <stdio.h>
17 #include <string.h>
18 
19 #include <gmock/gmock.h>
20 #include <gtest/gtest.h>
21 
22 #include <grpc/grpc.h>
23 #include <grpc/support/alloc.h>
24 #include <grpc/support/log.h>
26 
34 
35 extern "C" {
36 #include <openssl/crypto.h>
37 #include <openssl/pem.h>
38 }
39 
40 namespace {
41 
42 const int kSslTsiTestRevokedKeyCertPairsNum = 1;
43 const int kSslTsiTestValidKeyCertPairsNum = 1;
44 const char* kSslTsiTestCrlSupportedCredentialsDir =
45  "test/core/tsi/test_creds/crl_data/";
46 const char* kSslTsiTestFaultyCrlsDir = "bad_path/";
47 
48 class CrlSslTransportSecurityTest
49  : public testing::TestWithParam<tsi_tls_version> {
50  protected:
51  // A tsi_test_fixture implementation.
52  class SslTsiTestFixture {
53  public:
54  // When use_faulty_crl_directory is set, the crl_directory of the
55  // client is set to a non-existant path.
56  static SslTsiTestFixture* Create(bool use_revoked_server_cert,
57  bool use_revoked_client_cert,
58  bool use_faulty_crl_directory) {
59  return new SslTsiTestFixture(use_revoked_server_cert,
60  use_revoked_client_cert,
61  use_faulty_crl_directory);
62  }
63 
64  void Run() {
65  tsi_test_do_handshake(&base_);
67  }
68 
69  private:
70  SslTsiTestFixture(bool use_revoked_server_cert,
71  bool use_revoked_client_cert,
72  bool use_faulty_crl_directory)
73  : use_revoked_server_cert_(use_revoked_server_cert),
74  use_revoked_client_cert_(use_revoked_client_cert),
75  use_faulty_crl_directory_(use_faulty_crl_directory) {
76  tsi_test_fixture_init(&base_);
77  base_.test_unused_bytes = true;
78  base_.vtable = &kVtable;
79  // Load cert data.
80  revoked_pem_key_cert_pairs_ = static_cast<tsi_ssl_pem_key_cert_pair*>(
82  kSslTsiTestRevokedKeyCertPairsNum));
83  revoked_pem_key_cert_pairs_[0].private_key = LoadFile(
84  absl::StrCat(kSslTsiTestCrlSupportedCredentialsDir, "revoked.key"));
85  revoked_pem_key_cert_pairs_[0].cert_chain = LoadFile(
86  absl::StrCat(kSslTsiTestCrlSupportedCredentialsDir, "revoked.pem"));
87  valid_pem_key_cert_pairs_ = static_cast<tsi_ssl_pem_key_cert_pair*>(
89  kSslTsiTestValidKeyCertPairsNum));
90  valid_pem_key_cert_pairs_[0].private_key = LoadFile(
91  absl::StrCat(kSslTsiTestCrlSupportedCredentialsDir, "valid.key"));
92  valid_pem_key_cert_pairs_[0].cert_chain = LoadFile(
93  absl::StrCat(kSslTsiTestCrlSupportedCredentialsDir, "valid.pem"));
94  root_cert_ = LoadFile(
95  absl::StrCat(kSslTsiTestCrlSupportedCredentialsDir, "ca.pem"));
97  GPR_ASSERT(root_store_ != nullptr);
98  }
99 
100  ~SslTsiTestFixture() {
101  for (size_t i = 0; i < kSslTsiTestValidKeyCertPairsNum; i++) {
102  PemKeyCertPairDestroy(valid_pem_key_cert_pairs_[i]);
103  }
104  gpr_free(valid_pem_key_cert_pairs_);
105  for (size_t i = 0; i < kSslTsiTestRevokedKeyCertPairsNum; i++) {
106  PemKeyCertPairDestroy(revoked_pem_key_cert_pairs_[i]);
107  }
108  gpr_free(revoked_pem_key_cert_pairs_);
111  tsi_ssl_server_handshaker_factory_unref(server_handshaker_factory_);
112  tsi_ssl_client_handshaker_factory_unref(client_handshaker_factory_);
113  }
114 
115  static void SetupHandshakers(tsi_test_fixture* fixture) {
116  GPR_ASSERT(fixture != nullptr);
117  auto* self = reinterpret_cast<SslTsiTestFixture*>(fixture);
118  self->SetupHandshakers();
119  }
120 
121  void SetupHandshakers() {
122  // Create client handshaker factory.
123  tsi_ssl_client_handshaker_options client_options;
124  client_options.pem_root_certs = root_cert_;
125  if (use_revoked_client_cert_) {
126  client_options.pem_key_cert_pair = revoked_pem_key_cert_pairs_;
127  } else {
128  client_options.pem_key_cert_pair = valid_pem_key_cert_pairs_;
129  }
130  if (use_faulty_crl_directory_) {
131  client_options.crl_directory = kSslTsiTestFaultyCrlsDir;
132  } else {
133  client_options.crl_directory = kSslTsiTestCrlSupportedCredentialsDir;
134  }
135  client_options.root_store = root_store_;
136  client_options.min_tls_version = GetParam();
137  client_options.max_tls_version = GetParam();
139  &client_options, &client_handshaker_factory_),
140  TSI_OK);
141  // Create server handshaker factory.
143  if (use_revoked_server_cert_) {
144  server_options.pem_key_cert_pairs = revoked_pem_key_cert_pairs_;
145  server_options.num_key_cert_pairs = kSslTsiTestRevokedKeyCertPairsNum;
146  } else {
147  server_options.pem_key_cert_pairs = valid_pem_key_cert_pairs_;
148  server_options.num_key_cert_pairs = kSslTsiTestValidKeyCertPairsNum;
149  }
150  server_options.pem_client_root_certs = root_cert_;
151  server_options.crl_directory = kSslTsiTestCrlSupportedCredentialsDir;
152  server_options.client_certificate_request =
154  server_options.session_ticket_key = nullptr;
155  server_options.session_ticket_key_size = 0;
156  server_options.min_tls_version = GetParam();
157  server_options.max_tls_version = GetParam();
159  &server_options, &server_handshaker_factory_),
160  TSI_OK);
161  // Create server and client handshakers.
163  client_handshaker_factory_, nullptr, 0, 0,
164  &base_.client_handshaker),
165  TSI_OK);
167  server_handshaker_factory_, 0, 0, &base_.server_handshaker),
168  TSI_OK);
169  }
170 
171  static void CheckHandshakerPeers(tsi_test_fixture* fixture) {
172  GPR_ASSERT(fixture != nullptr);
173  auto* self = reinterpret_cast<SslTsiTestFixture*>(fixture);
174  self->CheckHandshakerPeers();
175  }
176 
177  void CheckHandshakerPeers() {
178  // In TLS 1.3, the client-side handshake succeeds even if the client
179  // sends a revoked certificate. In such a case, the server would fail
180  // the TLS handshake and send an alert to the client as the first
181  // application data message. In TLS 1.2, the client-side handshake will
182  // fail if the client sends a revoked certificate.
183  //
184  // For OpenSSL versions < 1.1, TLS 1.3 is not supported, so the
185  // client-side handshake should succeed precisely when the server-side
186  // handshake succeeds.
187  bool expect_server_success =
188  !(use_revoked_server_cert_ || use_revoked_client_cert_);
189 #if OPENSSL_VERSION_NUMBER >= 0x10100000
190  bool expect_client_success = GetParam() == tsi_tls_version::TSI_TLS1_2
191  ? expect_server_success
192  : !use_revoked_server_cert_;
193 #else
194  // If using OpenSSL version < 1.1, the CRL revocation won't be enabled
195  // anyways, so we always expect the connection to be successful.
196  expect_server_success = true;
197  bool expect_client_success = expect_server_success;
198 #endif
199  tsi_peer peer;
200  if (expect_client_success) {
201  EXPECT_EQ(
202  tsi_handshaker_result_extract_peer(base_.client_result, &peer),
203  TSI_OK);
204  tsi_peer_destruct(&peer);
205  } else {
206  EXPECT_EQ(base_.client_result, nullptr);
207  }
208  if (expect_server_success) {
209  EXPECT_EQ(
210  tsi_handshaker_result_extract_peer(base_.server_result, &peer),
211  TSI_OK);
212  tsi_peer_destruct(&peer);
213  } else {
214  EXPECT_EQ(base_.server_result, nullptr);
215  }
216  }
217 
218  static void PemKeyCertPairDestroy(tsi_ssl_pem_key_cert_pair kp) {
219  gpr_free(const_cast<char*>(kp.private_key));
220  gpr_free(const_cast<char*>(kp.cert_chain));
221  }
222 
223  static void Destruct(tsi_test_fixture* fixture) {
224  auto* self = reinterpret_cast<SslTsiTestFixture*>(fixture);
225  delete self;
226  }
227 
228  static char* LoadFile(absl::string_view file_path) {
230  GPR_ASSERT(grpc_load_file(file_path.data(), 1, &slice) ==
234  return data;
235  }
236 
237  static struct tsi_test_fixture_vtable kVtable;
238 
239  tsi_test_fixture base_;
240  bool use_revoked_server_cert_;
241  bool use_revoked_client_cert_;
242  bool use_faulty_crl_directory_;
243  char* root_cert_;
244  tsi_ssl_root_certs_store* root_store_;
245  tsi_ssl_pem_key_cert_pair* revoked_pem_key_cert_pairs_;
246  tsi_ssl_pem_key_cert_pair* valid_pem_key_cert_pairs_;
247  tsi_ssl_server_handshaker_factory* server_handshaker_factory_;
248  tsi_ssl_client_handshaker_factory* client_handshaker_factory_;
249  };
250 };
251 
253  CrlSslTransportSecurityTest::SslTsiTestFixture::kVtable = {
254  &CrlSslTransportSecurityTest::SslTsiTestFixture::SetupHandshakers,
255  &CrlSslTransportSecurityTest::SslTsiTestFixture::CheckHandshakerPeers,
257 
258 TEST_P(CrlSslTransportSecurityTest, RevokedServerCert) {
259  auto* fixture = SslTsiTestFixture::Create(/*use_revoked_server_cert=*/true,
260  /*use_revoked_client_cert=*/false,
261  /*use_faulty_crl_directory=*/false);
262  fixture->Run();
263 }
264 
265 TEST_P(CrlSslTransportSecurityTest, RevokedClientCert) {
266  auto* fixture = SslTsiTestFixture::Create(/*use_revoked_server_cert=*/false,
267  /*use_revoked_client_cert=*/true,
268  /*use_faulty_crl_directory=*/false);
269  fixture->Run();
270 }
271 
272 TEST_P(CrlSslTransportSecurityTest, ValidCerts) {
273  auto* fixture = SslTsiTestFixture::Create(/*use_revoked_server_cert=*/false,
274  /*use_revoked_client_cert=*/false,
275  /*use_faulty_crl_directory=*/false);
276  fixture->Run();
277 }
278 
279 TEST_P(CrlSslTransportSecurityTest, UseFaultyCrlDirectory) {
280  auto* fixture = SslTsiTestFixture::Create(/*use_revoked_server_cert=*/false,
281  /*use_revoked_client_cert=*/false,
282  /*use_faulty_crl_directory=*/true);
283  fixture->Run();
284 }
285 
286 std::string TestNameSuffix(
287  const ::testing::TestParamInfo<tsi_tls_version>& version) {
288  if (version.param == tsi_tls_version::TSI_TLS1_2) return "TLS_1_2";
290  return "TLS_1_3";
291 }
292 
293 INSTANTIATE_TEST_SUITE_P(TLSVersionsTest, CrlSslTransportSecurityTest,
296  &TestNameSuffix);
297 
298 } // namespace
299 
300 int main(int argc, char** argv) {
301  grpc::testing::TestEnvironment env(&argc, argv);
302  ::testing::InitGoogleTest(&argc, argv);
303  return RUN_ALL_TESTS();
304 }
grpc_slice_unref
GPRAPI void grpc_slice_unref(grpc_slice s)
Definition: slice_api.cc:32
main
int main(int argc, char **argv)
Definition: crl_ssl_transport_security_test.cc:300
tsi_ssl_client_handshaker_options::pem_root_certs
const char * pem_root_certs
Definition: ssl_transport_security.h:144
tsi_create_ssl_server_handshaker_factory_with_options
tsi_result tsi_create_ssl_server_handshaker_factory_with_options(const tsi_ssl_server_handshaker_options *options, tsi_ssl_server_handshaker_factory **factory)
Definition: ssl_transport_security.cc:2179
GRPC_ERROR_NONE
#define GRPC_ERROR_NONE
Definition: error.h:234
log.h
TSI_TLS1_3
@ TSI_TLS1_3
Definition: transport_security_interface.h:91
grpc_load_file
grpc_error_handle grpc_load_file(const char *filename, int add_null_terminator, grpc_slice *output)
Definition: load_file.cc:33
generate.env
env
Definition: generate.py:37
absl::StrCat
std::string StrCat(const AlphaNum &a, const AlphaNum &b)
Definition: abseil-cpp/absl/strings/str_cat.cc:98
tsi_create_ssl_client_handshaker_factory_with_options
tsi_result tsi_create_ssl_client_handshaker_factory_with_options(const tsi_ssl_client_handshaker_options *options, tsi_ssl_client_handshaker_factory **factory)
Definition: ssl_transport_security.cc:2007
load_file.h
tsi_test_fixture_vtable
Definition: transport_security_test_lib.h:67
tsi_ssl_pem_key_cert_pair
Definition: ssl_transport_security.h:101
tsi_ssl_client_handshaker_factory_unref
void tsi_ssl_client_handshaker_factory_unref(tsi_ssl_client_handshaker_factory *factory)
Definition: ssl_transport_security.cc:1783
string.h
absl::string_view
Definition: abseil-cpp/absl/strings/string_view.h:167
tsi_ssl_client_handshaker_factory
Definition: ssl_transport_security.cc:93
gpr_free
GPRAPI void gpr_free(void *ptr)
Definition: alloc.cc:51
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
tsi_test_fixture_init
void tsi_test_fixture_init(tsi_test_fixture *fixture)
Definition: transport_security_test_lib.cc:607
gpr_malloc
GPRAPI void * gpr_malloc(size_t size)
Definition: alloc.cc:29
tsi_test_fixture_destroy
void tsi_test_fixture_destroy(tsi_test_fixture *fixture)
Definition: transport_security_test_lib.cc:620
TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY
@ TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY
Definition: transport_security_interface.h:66
pem.h
tsi_ssl_pem_key_cert_pair::cert_chain
const char * cert_chain
Definition: ssl_transport_security.h:108
version
Definition: version.py:1
transport_security_test_lib.h
tsi_ssl_client_handshaker_options::pem_key_cert_pair
const tsi_ssl_pem_key_cert_pair * pem_key_cert_pair
Definition: ssl_transport_security.h:141
ssl_transport_security.h
tsi_ssl_client_handshaker_options::max_tls_version
tsi_tls_version max_tls_version
Definition: ssl_transport_security.h:174
testing::TestWithParam
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:1883
tsi_ssl_server_handshaker_options
Definition: ssl_transport_security.h:279
EXPECT_EQ
#define EXPECT_EQ(a, b)
Definition: iomgr/time_averaged_stats_test.cc:27
TSI_OK
@ TSI_OK
Definition: transport_security_interface.h:32
string_util.h
root_cert_
std::string root_cert_
Definition: xds_end2end_test.cc:415
GPR_ASSERT
#define GPR_ASSERT(x)
Definition: include/grpc/impl/codegen/log.h:94
fixture
static const char fixture[]
Definition: test-fs-copyfile.c:36
TEST_P
#define TEST_P(test_suite_name, test_name)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest-param-test.h:414
TSI_TLS1_2
@ TSI_TLS1_2
Definition: transport_security_interface.h:90
slice
grpc_slice slice
Definition: src/core/lib/surface/server.cc:467
grpc.h
security_connector.h
crypto.h
grpc_slice
Definition: include/grpc/impl/codegen/slice.h:65
tsi_ssl_server_handshaker_factory_create_handshaker
tsi_result tsi_ssl_server_handshaker_factory_create_handshaker(tsi_ssl_server_handshaker_factory *factory, size_t network_bio_buf_size, size_t ssl_bio_buf_size, tsi_handshaker **handshaker)
Definition: ssl_transport_security.cc:1813
data
char data[kBufferLength]
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1006
RUN_ALL_TESTS
int RUN_ALL_TESTS() GTEST_MUST_USE_RESULT_
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:2471
tsi_test_do_handshake
void tsi_test_do_handshake(tsi_test_fixture *fixture)
Definition: transport_security_test_lib.cc:386
transport_security_interface.h
tsi_handshaker_result_extract_peer
tsi_result tsi_handshaker_result_extract_peer(const tsi_handshaker_result *self, tsi_peer *peer)
Definition: transport_security.cc:244
test_config.h
tsi_ssl_server_handshaker_factory
Definition: ssl_transport_security.cc:102
grpc_slice_to_c_string
GPRAPI char * grpc_slice_to_c_string(grpc_slice s)
Definition: slice/slice.cc:35
grpc.beta.implementations.server_options
def server_options(multi_method_implementation=None, request_deserializers=None, response_serializers=None, thread_pool=None, thread_pool_size=None, default_timeout=None, maximum_timeout=None)
Definition: implementations.py:258
tsi_ssl_pem_key_cert_pair::private_key
const char * private_key
Definition: ssl_transport_security.h:104
tsi_peer
Definition: transport_security_interface.h:238
grpc_core::Destruct
void Destruct(T *p)
Definition: construct_destruct.h:27
transport_security.h
testing::InitGoogleTest
GTEST_API_ void InitGoogleTest(int *argc, char **argv)
Definition: bloaty/third_party/googletest/googletest/src/gtest.cc:6106
testing::Values
internal::ValueArray< T... > Values(T... v)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest-param-test.h:335
tsi_ssl_server_handshaker_factory_unref
void tsi_ssl_server_handshaker_factory_unref(tsi_ssl_server_handshaker_factory *factory)
Definition: ssl_transport_security.cc:1824
tsi_ssl_root_certs_store
Definition: ssl_transport_security.cc:84
alloc.h
tsi_test_fixture
Definition: transport_security_test_lib.h:73
grpc::testing::TestEnvironment
Definition: test/core/util/test_config.h:54
tsi_ssl_client_handshaker_options
Definition: ssl_transport_security.h:137
tsi_ssl_root_certs_store_create
tsi_ssl_root_certs_store * tsi_ssl_root_certs_store_create(const char *pem_roots)
Definition: ssl_transport_security.cc:1000
tsi_ssl_root_certs_store_destroy
void tsi_ssl_root_certs_store_destroy(tsi_ssl_root_certs_store *self)
Definition: ssl_transport_security.cc:1029
googletest-break-on-failure-unittest.Run
def Run(command)
Definition: bloaty/third_party/googletest/googletest/test/googletest-break-on-failure-unittest.py:76
tsi_ssl_client_handshaker_options::min_tls_version
tsi_tls_version min_tls_version
Definition: ssl_transport_security.h:173
absl::string_view::data
constexpr const_pointer data() const noexcept
Definition: abseil-cpp/absl/strings/string_view.h:336
tsi_peer_destruct
void tsi_peer_destruct(tsi_peer *self)
Definition: transport_security.cc:320
tsi_ssl_client_handshaker_options::crl_directory
const char * crl_directory
Definition: ssl_transport_security.h:180
tsi_ssl_client_handshaker_factory_create_handshaker
tsi_result tsi_ssl_client_handshaker_factory_create_handshaker(tsi_ssl_client_handshaker_factory *factory, const char *server_name_indication, size_t network_bio_buf_size, size_t ssl_bio_buf_size, tsi_handshaker **handshaker)
Definition: ssl_transport_security.cc:1774
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
INSTANTIATE_TEST_SUITE_P
#define INSTANTIATE_TEST_SUITE_P(prefix, test_suite_name,...)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest-param-test.h:460
tsi_ssl_client_handshaker_options::root_store
const tsi_ssl_root_certs_store * root_store
Definition: ssl_transport_security.h:149


grpc
Author(s):
autogenerated on Fri May 16 2025 02:58:06