Merge pull request #12024 from yihuazhang/tsi_test_lib

Add transport security test library
pull/12390/head
Mark D. Roth 7 years ago committed by GitHub
commit 17f21b44a3
  1. 72
      CMakeLists.txt
  2. 78
      Makefile
  3. 39
      build.yaml
  4. 8
      src/core/tsi/test_creds/BUILD
  5. 52
      test/core/tsi/BUILD
  6. 148
      test/core/tsi/fake_transport_security_test.c
  7. 558
      test/core/tsi/ssl_transport_security_test.c
  8. 550
      test/core/tsi/transport_security_test_lib.c
  9. 165
      test/core/tsi/transport_security_test_lib.h
  10. 51
      tools/run_tests/generated/sources_and_headers.json
  11. 40
      tools/run_tests/generated/tests.json
  12. 1
      tools/ubsan_suppressions.txt

@ -421,6 +421,9 @@ add_dependencies(buildtests_c ev_epollsig_linux_test)
endif()
add_dependencies(buildtests_c fake_resolver_test)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_c fake_transport_security_test)
endif()
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_c fd_conservation_posix_test)
endif()
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
@ -530,6 +533,9 @@ add_dependencies(buildtests_c sockaddr_utils_test)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_c socket_utils_test)
endif()
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_c ssl_transport_security_test)
endif()
add_dependencies(buildtests_c status_conversion_test)
add_dependencies(buildtests_c stream_compression_test)
add_dependencies(buildtests_c stream_owned_slice_test)
@ -5966,6 +5972,39 @@ endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_executable(fake_transport_security_test
test/core/tsi/fake_transport_security_test.c
test/core/tsi/transport_security_test_lib.c
)
target_include_directories(fake_transport_security_test
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src
PRIVATE ${BENCHMARK_ROOT_DIR}/include
PRIVATE ${ZLIB_ROOT_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
PRIVATE ${CARES_BUILD_INCLUDE_DIR}
PRIVATE ${CARES_INCLUDE_DIR}
PRIVATE ${CARES_PLATFORM_INCLUDE_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
)
target_link_libraries(fake_transport_security_test
${_gRPC_ALLTARGETS_LIBRARIES}
gpr_test_util
gpr
grpc
)
endif()
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_executable(fd_conservation_posix_test
test/core/iomgr/fd_conservation_posix_test.c
)
@ -8708,6 +8747,39 @@ target_link_libraries(socket_utils_test
gpr
)
endif()
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_executable(ssl_transport_security_test
test/core/tsi/ssl_transport_security_test.c
test/core/tsi/transport_security_test_lib.c
)
target_include_directories(ssl_transport_security_test
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${BORINGSSL_ROOT_DIR}/include
PRIVATE ${PROTOBUF_ROOT_DIR}/src
PRIVATE ${BENCHMARK_ROOT_DIR}/include
PRIVATE ${ZLIB_ROOT_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
PRIVATE ${CARES_BUILD_INCLUDE_DIR}
PRIVATE ${CARES_INCLUDE_DIR}
PRIVATE ${CARES_PLATFORM_INCLUDE_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
)
target_link_libraries(ssl_transport_security_test
${_gRPC_ALLTARGETS_LIBRARIES}
gpr_test_util
gpr
grpc
)
endif()
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)

@ -976,6 +976,7 @@ endpoint_pair_test: $(BINDIR)/$(CONFIG)/endpoint_pair_test
error_test: $(BINDIR)/$(CONFIG)/error_test
ev_epollsig_linux_test: $(BINDIR)/$(CONFIG)/ev_epollsig_linux_test
fake_resolver_test: $(BINDIR)/$(CONFIG)/fake_resolver_test
fake_transport_security_test: $(BINDIR)/$(CONFIG)/fake_transport_security_test
fd_conservation_posix_test: $(BINDIR)/$(CONFIG)/fd_conservation_posix_test
fd_posix_test: $(BINDIR)/$(CONFIG)/fd_posix_test
fling_client: $(BINDIR)/$(CONFIG)/fling_client
@ -1075,6 +1076,7 @@ sockaddr_resolver_test: $(BINDIR)/$(CONFIG)/sockaddr_resolver_test
sockaddr_utils_test: $(BINDIR)/$(CONFIG)/sockaddr_utils_test
socket_utils_test: $(BINDIR)/$(CONFIG)/socket_utils_test
ssl_server_fuzzer: $(BINDIR)/$(CONFIG)/ssl_server_fuzzer
ssl_transport_security_test: $(BINDIR)/$(CONFIG)/ssl_transport_security_test
status_conversion_test: $(BINDIR)/$(CONFIG)/status_conversion_test
stream_compression_test: $(BINDIR)/$(CONFIG)/stream_compression_test
stream_owned_slice_test: $(BINDIR)/$(CONFIG)/stream_owned_slice_test
@ -1366,6 +1368,7 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/error_test \
$(BINDIR)/$(CONFIG)/ev_epollsig_linux_test \
$(BINDIR)/$(CONFIG)/fake_resolver_test \
$(BINDIR)/$(CONFIG)/fake_transport_security_test \
$(BINDIR)/$(CONFIG)/fd_conservation_posix_test \
$(BINDIR)/$(CONFIG)/fd_posix_test \
$(BINDIR)/$(CONFIG)/fling_client \
@ -1448,6 +1451,7 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/sockaddr_resolver_test \
$(BINDIR)/$(CONFIG)/sockaddr_utils_test \
$(BINDIR)/$(CONFIG)/socket_utils_test \
$(BINDIR)/$(CONFIG)/ssl_transport_security_test \
$(BINDIR)/$(CONFIG)/status_conversion_test \
$(BINDIR)/$(CONFIG)/stream_compression_test \
$(BINDIR)/$(CONFIG)/stream_owned_slice_test \
@ -1788,6 +1792,8 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/ev_epollsig_linux_test || ( echo test ev_epollsig_linux_test failed ; exit 1 )
$(E) "[RUN] Testing fake_resolver_test"
$(Q) $(BINDIR)/$(CONFIG)/fake_resolver_test || ( echo test fake_resolver_test failed ; exit 1 )
$(E) "[RUN] Testing fake_transport_security_test"
$(Q) $(BINDIR)/$(CONFIG)/fake_transport_security_test || ( echo test fake_transport_security_test failed ; exit 1 )
$(E) "[RUN] Testing fd_conservation_posix_test"
$(Q) $(BINDIR)/$(CONFIG)/fd_conservation_posix_test || ( echo test fd_conservation_posix_test failed ; exit 1 )
$(E) "[RUN] Testing fd_posix_test"
@ -1936,6 +1942,8 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/sockaddr_utils_test || ( echo test sockaddr_utils_test failed ; exit 1 )
$(E) "[RUN] Testing socket_utils_test"
$(Q) $(BINDIR)/$(CONFIG)/socket_utils_test || ( echo test socket_utils_test failed ; exit 1 )
$(E) "[RUN] Testing ssl_transport_security_test"
$(Q) $(BINDIR)/$(CONFIG)/ssl_transport_security_test || ( echo test ssl_transport_security_test failed ; exit 1 )
$(E) "[RUN] Testing status_conversion_test"
$(Q) $(BINDIR)/$(CONFIG)/status_conversion_test || ( echo test status_conversion_test failed ; exit 1 )
$(E) "[RUN] Testing stream_compression_test"
@ -9602,6 +9610,41 @@ endif
endif
FAKE_TRANSPORT_SECURITY_TEST_SRC = \
test/core/tsi/fake_transport_security_test.c \
test/core/tsi/transport_security_test_lib.c \
FAKE_TRANSPORT_SECURITY_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(FAKE_TRANSPORT_SECURITY_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/fake_transport_security_test: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/fake_transport_security_test: $(FAKE_TRANSPORT_SECURITY_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(FAKE_TRANSPORT_SECURITY_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/fake_transport_security_test
endif
$(OBJDIR)/$(CONFIG)/test/core/tsi/fake_transport_security_test.o: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc.a
$(OBJDIR)/$(CONFIG)/test/core/tsi/transport_security_test_lib.o: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc.a
deps_fake_transport_security_test: $(FAKE_TRANSPORT_SECURITY_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(FAKE_TRANSPORT_SECURITY_TEST_OBJS:.o=.dep)
endif
endif
FD_CONSERVATION_POSIX_TEST_SRC = \
test/core/iomgr/fd_conservation_posix_test.c \
@ -12770,6 +12813,41 @@ endif
endif
SSL_TRANSPORT_SECURITY_TEST_SRC = \
test/core/tsi/ssl_transport_security_test.c \
test/core/tsi/transport_security_test_lib.c \
SSL_TRANSPORT_SECURITY_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SSL_TRANSPORT_SECURITY_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/ssl_transport_security_test: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/ssl_transport_security_test: $(SSL_TRANSPORT_SECURITY_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(SSL_TRANSPORT_SECURITY_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/ssl_transport_security_test
endif
$(OBJDIR)/$(CONFIG)/test/core/tsi/ssl_transport_security_test.o: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc.a
$(OBJDIR)/$(CONFIG)/test/core/tsi/transport_security_test_lib.o: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc.a
deps_ssl_transport_security_test: $(SSL_TRANSPORT_SECURITY_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(SSL_TRANSPORT_SECURITY_TEST_OBJS:.o=.dep)
endif
endif
STATUS_CONVERSION_TEST_SRC = \
test/core/transport/status_conversion_test.c \

@ -750,6 +750,7 @@ filegroups:
- test/core/util/trickle_endpoint.c
deps:
- gpr_test_util
- gpr
uses:
- grpc_base
- grpc_client_channel
@ -924,6 +925,14 @@ filegroups:
- third_party/nanopb/pb_common.h
- third_party/nanopb/pb_decode.h
- third_party/nanopb/pb_encode.h
- name: transport_security_test_lib
build: test
headers:
- test/core/tsi/transport_security_test_lib.h
src:
- test/core/tsi/transport_security_test_lib.c
deps:
- grpc
- name: tsi
headers:
- src/core/tsi/fake_transport_security.h
@ -2034,6 +2043,21 @@ targets:
- grpc
- gpr_test_util
- gpr
- name: fake_transport_security_test
build: test
language: c
src:
- test/core/tsi/fake_transport_security_test.c
deps:
- gpr_test_util
- gpr
- grpc
filegroups:
- transport_security_test_lib
platforms:
- linux
- posix
- mac
- name: fd_conservation_posix_test
build: test
language: c
@ -3105,6 +3129,21 @@ targets:
corpus_dirs:
- test/core/security/corpus/ssl_server_corpus
maxlen: 2048
- name: ssl_transport_security_test
build: test
language: c
src:
- test/core/tsi/ssl_transport_security_test.c
deps:
- gpr_test_util
- gpr
- grpc
filegroups:
- transport_security_test_lib
platforms:
- linux
- posix
- mac
- name: status_conversion_test
build: test
language: c

@ -18,4 +18,12 @@ exports_files([
"ca.pem",
"server1.key",
"server1.pem",
"server0.key",
"server0.pem",
"client.key",
"client.pem",
"badserver.key",
"badserver.pem",
"badclient.key",
"badclient.pem",
])

@ -18,13 +18,63 @@ licenses(["notice"]) # Apache v2
grpc_package(name = "test/core/tsi")
grpc_cc_library(
name = "transport_security_test_lib",
srcs = ["transport_security_test_lib.c"],
hdrs = ["transport_security_test_lib.h"],
deps = [
"//:grpc",
"//:tsi",
],
)
grpc_cc_test(
name = "fake_transport_security_test",
srcs = ["fake_transport_security_test.c"],
language = "C",
deps = [
":transport_security_test_lib",
"//:grpc",
"//:gpr",
"//:tsi",
"//test/core/util:gpr_test_util",
],
)
grpc_cc_test(
name = "ssl_transport_security_test",
srcs = ["ssl_transport_security_test.c"],
data = [
"//src/core/tsi/test_creds:badclient.key",
"//src/core/tsi/test_creds:badclient.pem",
"//src/core/tsi/test_creds:badserver.key",
"//src/core/tsi/test_creds:badserver.pem",
"//src/core/tsi/test_creds:ca.pem",
"//src/core/tsi/test_creds:client.key",
"//src/core/tsi/test_creds:client.pem",
"//src/core/tsi/test_creds:server0.key",
"//src/core/tsi/test_creds:server0.pem",
"//src/core/tsi/test_creds:server1.key",
"//src/core/tsi/test_creds:server1.pem",
],
language = "C",
deps = [
":transport_security_test_lib",
"//:grpc",
"//:gpr",
"//:tsi",
"//test/core/util:gpr_test_util",
],
)
grpc_cc_test(
name = "transport_security_test",
srcs = ["transport_security_test.c"],
language = "C",
deps = [
"//:gpr",
"//:grpc",
"//:gpr",
"//test/core/util:gpr_test_util",
"//test/core/util:grpc_test_util",
],

@ -0,0 +1,148 @@
/*
*
* Copyright 2017 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "src/core/lib/security/transport/security_connector.h"
#include "src/core/tsi/fake_transport_security.h"
#include "test/core/tsi/transport_security_test_lib.h"
#include "test/core/util/test_config.h"
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
typedef struct fake_tsi_test_fixture {
tsi_test_fixture base;
} fake_tsi_test_fixture;
static void fake_test_setup_handshakers(tsi_test_fixture *fixture) {
fixture->client_handshaker =
tsi_create_fake_handshaker(true /* is_client. */);
fixture->server_handshaker =
tsi_create_fake_handshaker(false /* is_client. */);
}
static void validate_handshaker_peers(tsi_handshaker_result *result) {
GPR_ASSERT(result != NULL);
tsi_peer peer;
GPR_ASSERT(tsi_handshaker_result_extract_peer(result, &peer) == TSI_OK);
const tsi_peer_property *property =
tsi_peer_get_property_by_name(&peer, TSI_CERTIFICATE_TYPE_PEER_PROPERTY);
GPR_ASSERT(property != NULL);
GPR_ASSERT(memcmp(property->value.data, TSI_FAKE_CERTIFICATE_TYPE,
property->value.length) == 0);
tsi_peer_destruct(&peer);
}
static void fake_test_check_handshaker_peers(tsi_test_fixture *fixture) {
validate_handshaker_peers(fixture->client_result);
validate_handshaker_peers(fixture->server_result);
}
static void fake_test_destruct(tsi_test_fixture *fixture) {}
static const struct tsi_test_fixture_vtable vtable = {
fake_test_setup_handshakers, fake_test_check_handshaker_peers,
fake_test_destruct};
static tsi_test_fixture *fake_tsi_test_fixture_create() {
fake_tsi_test_fixture *fake_fixture = gpr_zalloc(sizeof(*fake_fixture));
tsi_test_fixture_init(&fake_fixture->base);
fake_fixture->base.vtable = &vtable;
return &fake_fixture->base;
}
void fake_tsi_test_do_handshake_tiny_handshake_buffer() {
tsi_test_fixture *fixture = fake_tsi_test_fixture_create();
fixture->handshake_buffer_size = TSI_TEST_TINY_HANDSHAKE_BUFFER_SIZE;
tsi_test_do_handshake(fixture);
tsi_test_fixture_destroy(fixture);
}
void fake_tsi_test_do_handshake_small_handshake_buffer() {
tsi_test_fixture *fixture = fake_tsi_test_fixture_create();
fixture->handshake_buffer_size = TSI_TEST_SMALL_HANDSHAKE_BUFFER_SIZE;
tsi_test_do_handshake(fixture);
tsi_test_fixture_destroy(fixture);
}
void fake_tsi_test_do_handshake() {
tsi_test_fixture *fixture = fake_tsi_test_fixture_create();
tsi_test_do_handshake(fixture);
tsi_test_fixture_destroy(fixture);
}
void fake_tsi_test_do_round_trip_for_all_configs() {
unsigned int *bit_array =
gpr_zalloc(sizeof(unsigned int) * TSI_TEST_NUM_OF_ARGUMENTS);
const unsigned int mask = 1U << (TSI_TEST_NUM_OF_ARGUMENTS - 1);
for (unsigned int val = 0; val < TSI_TEST_NUM_OF_COMBINATIONS; val++) {
unsigned int v = val;
for (unsigned int ind = 0; ind < TSI_TEST_NUM_OF_ARGUMENTS; ind++) {
bit_array[ind] = (v & mask) ? 1 : 0;
v <<= 1;
}
tsi_test_fixture *fixture = fake_tsi_test_fixture_create();
fake_tsi_test_fixture *fake_fixture = (fake_tsi_test_fixture *)fixture;
tsi_test_frame_protector_config_destroy(fake_fixture->base.config);
fake_fixture->base.config = tsi_test_frame_protector_config_create(
bit_array[0], bit_array[1], bit_array[2], bit_array[3], bit_array[4],
bit_array[5], bit_array[6], bit_array[7]);
tsi_test_do_round_trip(&fake_fixture->base);
tsi_test_fixture_destroy(fixture);
}
gpr_free(bit_array);
}
void fake_tsi_test_do_round_trip_odd_buffer_size() {
const size_t odd_sizes[] = {1025, 2051, 4103, 8207, 16409};
const size_t size = sizeof(odd_sizes) / sizeof(size_t);
for (size_t ind1 = 0; ind1 < size; ind1++) {
for (size_t ind2 = 0; ind2 < size; ind2++) {
for (size_t ind3 = 0; ind3 < size; ind3++) {
for (size_t ind4 = 0; ind4 < size; ind4++) {
for (size_t ind5 = 0; ind5 < size; ind5++) {
tsi_test_fixture *fixture = fake_tsi_test_fixture_create();
fake_tsi_test_fixture *fake_fixture =
(fake_tsi_test_fixture *)fixture;
tsi_test_frame_protector_config_set_buffer_size(
fake_fixture->base.config, odd_sizes[ind1], odd_sizes[ind2],
odd_sizes[ind3], odd_sizes[ind4], odd_sizes[ind5]);
tsi_test_do_round_trip(&fake_fixture->base);
tsi_test_fixture_destroy(fixture);
}
}
}
}
}
}
int main(int argc, char **argv) {
grpc_test_init(argc, argv);
grpc_init();
fake_tsi_test_do_handshake_tiny_handshake_buffer();
fake_tsi_test_do_handshake_small_handshake_buffer();
fake_tsi_test_do_handshake();
fake_tsi_test_do_round_trip_for_all_configs();
fake_tsi_test_do_round_trip_odd_buffer_size();
grpc_shutdown();
return 0;
}

@ -0,0 +1,558 @@
/*
*
* Copyright 2017 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "src/core/lib/iomgr/load_file.h"
#include "src/core/lib/security/transport/security_connector.h"
#include "src/core/tsi/ssl_transport_security.h"
#include "src/core/tsi/transport_security_adapter.h"
#include "test/core/tsi/transport_security_test_lib.h"
#include "test/core/util/test_config.h"
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#define SSL_TSI_TEST_ALPN1 "foo"
#define SSL_TSI_TEST_ALPN2 "toto"
#define SSL_TSI_TEST_ALPN3 "baz"
#define SSL_TSI_TEST_ALPN_NUM 2
#define SSL_TSI_TEST_SERVER_KEY_CERT_PAIRS_NUM 2
#define SSL_TSI_TEST_BAD_SERVER_KEY_CERT_PAIRS_NUM 1
#define SSL_TSI_TEST_CREDENTIALS_DIR "src/core/tsi/test_creds/"
typedef enum AlpnMode {
NO_ALPN,
ALPN_CLIENT_NO_SERVER,
ALPN_SERVER_NO_CLIENT,
ALPN_CLIENT_SERVER_OK,
ALPN_CLIENT_SERVER_MISMATCH
} AlpnMode;
typedef struct ssl_alpn_lib {
AlpnMode alpn_mode;
char **server_alpn_protocols;
char **client_alpn_protocols;
uint16_t num_server_alpn_protocols;
uint16_t num_client_alpn_protocols;
} ssl_alpn_lib;
typedef struct ssl_key_cert_lib {
bool use_bad_server_cert;
bool use_bad_client_cert;
char *root_cert;
tsi_ssl_pem_key_cert_pair *server_pem_key_cert_pairs;
tsi_ssl_pem_key_cert_pair *bad_server_pem_key_cert_pairs;
tsi_ssl_pem_key_cert_pair client_pem_key_cert_pair;
tsi_ssl_pem_key_cert_pair bad_client_pem_key_cert_pair;
uint16_t server_num_key_cert_pairs;
uint16_t bad_server_num_key_cert_pairs;
} ssl_key_cert_lib;
typedef struct ssl_tsi_test_fixture {
tsi_test_fixture base;
ssl_key_cert_lib *key_cert_lib;
ssl_alpn_lib *alpn_lib;
bool force_client_auth;
char *server_name_indication;
tsi_ssl_server_handshaker_factory *server_handshaker_factory;
tsi_ssl_client_handshaker_factory *client_handshaker_factory;
} ssl_tsi_test_fixture;
static void ssl_test_setup_handshakers(tsi_test_fixture *fixture) {
ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture;
GPR_ASSERT(ssl_fixture != NULL);
GPR_ASSERT(ssl_fixture->key_cert_lib != NULL);
GPR_ASSERT(ssl_fixture->alpn_lib != NULL);
ssl_key_cert_lib *key_cert_lib = ssl_fixture->key_cert_lib;
ssl_alpn_lib *alpn_lib = ssl_fixture->alpn_lib;
/* Create client handshaker factory. */
tsi_ssl_pem_key_cert_pair *client_key_cert_pair = NULL;
if (ssl_fixture->force_client_auth) {
client_key_cert_pair = key_cert_lib->use_bad_client_cert
? &key_cert_lib->bad_client_pem_key_cert_pair
: &key_cert_lib->client_pem_key_cert_pair;
}
char **client_alpn_protocols = NULL;
uint16_t num_client_alpn_protocols = 0;
if (alpn_lib->alpn_mode == ALPN_CLIENT_NO_SERVER ||
alpn_lib->alpn_mode == ALPN_CLIENT_SERVER_OK ||
alpn_lib->alpn_mode == ALPN_CLIENT_SERVER_MISMATCH) {
client_alpn_protocols = alpn_lib->client_alpn_protocols;
num_client_alpn_protocols = alpn_lib->num_client_alpn_protocols;
}
GPR_ASSERT(tsi_create_ssl_client_handshaker_factory(
client_key_cert_pair, key_cert_lib->root_cert, NULL,
(const char **)client_alpn_protocols,
num_client_alpn_protocols,
&ssl_fixture->client_handshaker_factory) == TSI_OK);
/* Create server handshaker factory. */
char **server_alpn_protocols = NULL;
uint16_t num_server_alpn_protocols = 0;
if (alpn_lib->alpn_mode == ALPN_SERVER_NO_CLIENT ||
alpn_lib->alpn_mode == ALPN_CLIENT_SERVER_OK ||
alpn_lib->alpn_mode == ALPN_CLIENT_SERVER_MISMATCH) {
server_alpn_protocols = alpn_lib->server_alpn_protocols;
num_server_alpn_protocols = alpn_lib->num_server_alpn_protocols;
if (alpn_lib->alpn_mode == ALPN_CLIENT_SERVER_MISMATCH) {
num_server_alpn_protocols--;
}
}
GPR_ASSERT(tsi_create_ssl_server_handshaker_factory(
key_cert_lib->use_bad_server_cert
? key_cert_lib->bad_server_pem_key_cert_pairs
: key_cert_lib->server_pem_key_cert_pairs,
key_cert_lib->use_bad_server_cert
? key_cert_lib->bad_server_num_key_cert_pairs
: key_cert_lib->server_num_key_cert_pairs,
key_cert_lib->root_cert, ssl_fixture->force_client_auth, NULL,
(const char **)server_alpn_protocols,
num_server_alpn_protocols,
&ssl_fixture->server_handshaker_factory) == TSI_OK);
/* Create server and client handshakers. */
tsi_handshaker *client_handshaker = NULL;
GPR_ASSERT(tsi_ssl_client_handshaker_factory_create_handshaker(
ssl_fixture->client_handshaker_factory,
ssl_fixture->server_name_indication,
&client_handshaker) == TSI_OK);
ssl_fixture->base.client_handshaker =
tsi_create_adapter_handshaker(client_handshaker);
tsi_handshaker *server_handshaker = NULL;
GPR_ASSERT(tsi_ssl_server_handshaker_factory_create_handshaker(
ssl_fixture->server_handshaker_factory, &server_handshaker) ==
TSI_OK);
ssl_fixture->base.server_handshaker =
tsi_create_adapter_handshaker(server_handshaker);
}
static void check_alpn(ssl_tsi_test_fixture *ssl_fixture,
const tsi_peer *peer) {
GPR_ASSERT(ssl_fixture != NULL);
GPR_ASSERT(ssl_fixture->alpn_lib != NULL);
ssl_alpn_lib *alpn_lib = ssl_fixture->alpn_lib;
const tsi_peer_property *alpn_property =
tsi_peer_get_property_by_name(peer, TSI_SSL_ALPN_SELECTED_PROTOCOL);
if (alpn_lib->alpn_mode != ALPN_CLIENT_SERVER_OK) {
GPR_ASSERT(alpn_property == NULL);
} else {
GPR_ASSERT(alpn_property != NULL);
const char *expected_match = "baz";
GPR_ASSERT(memcmp(alpn_property->value.data, expected_match,
alpn_property->value.length) == 0);
}
}
static const tsi_peer_property *
check_basic_authenticated_peer_and_get_common_name(const tsi_peer *peer) {
const tsi_peer_property *cert_type_property =
tsi_peer_get_property_by_name(peer, TSI_CERTIFICATE_TYPE_PEER_PROPERTY);
GPR_ASSERT(cert_type_property != NULL);
GPR_ASSERT(memcmp(cert_type_property->value.data, TSI_X509_CERTIFICATE_TYPE,
cert_type_property->value.length) == 0);
const tsi_peer_property *property = tsi_peer_get_property_by_name(
peer, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY);
GPR_ASSERT(property != NULL);
return property;
}
void check_server0_peer(tsi_peer *peer) {
const tsi_peer_property *property =
check_basic_authenticated_peer_and_get_common_name(peer);
const char *expected_match = "*.test.google.com.au";
GPR_ASSERT(memcmp(property->value.data, expected_match,
property->value.length) == 0);
GPR_ASSERT(tsi_peer_get_property_by_name(
peer, TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) ==
NULL);
GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "foo.test.google.com.au") == 1);
GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "bar.test.google.com.au") == 1);
GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "bar.test.google.blah") == 0);
GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "foo.bar.test.google.com.au") ==
0);
GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "test.google.com.au") == 0);
tsi_peer_destruct(peer);
}
static bool check_subject_alt_name(tsi_peer *peer, const char *name) {
for (size_t i = 0; i < peer->property_count; i++) {
const tsi_peer_property *prop = &peer->properties[i];
if (strcmp(prop->name, TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) ==
0) {
if (memcmp(prop->value.data, name, prop->value.length) == 0) {
return true;
}
}
}
return false;
}
void check_server1_peer(tsi_peer *peer) {
const tsi_peer_property *property =
check_basic_authenticated_peer_and_get_common_name(peer);
const char *expected_match = "*.test.google.com";
GPR_ASSERT(memcmp(property->value.data, expected_match,
property->value.length) == 0);
GPR_ASSERT(check_subject_alt_name(peer, "*.test.google.fr") == 1);
GPR_ASSERT(check_subject_alt_name(peer, "waterzooi.test.google.be") == 1);
GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "foo.test.google.fr") == 1);
GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "bar.test.google.fr") == 1);
GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "waterzooi.test.google.be") == 1);
GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "foo.test.youtube.com") == 1);
GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "bar.foo.test.google.com") == 0);
GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "test.google.fr") == 0);
GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "tartines.test.google.be") == 0);
GPR_ASSERT(tsi_ssl_peer_matches_name(peer, "tartines.youtube.com") == 0);
tsi_peer_destruct(peer);
}
static void check_client_peer(ssl_tsi_test_fixture *ssl_fixture,
tsi_peer *peer) {
GPR_ASSERT(ssl_fixture != NULL);
GPR_ASSERT(ssl_fixture->alpn_lib != NULL);
ssl_alpn_lib *alpn_lib = ssl_fixture->alpn_lib;
if (!ssl_fixture->force_client_auth) {
GPR_ASSERT(peer->property_count ==
(alpn_lib->alpn_mode == ALPN_CLIENT_SERVER_OK ? 1 : 0));
} else {
const tsi_peer_property *property =
check_basic_authenticated_peer_and_get_common_name(peer);
const char *expected_match = "testclient";
GPR_ASSERT(memcmp(property->value.data, expected_match,
property->value.length) == 0);
}
tsi_peer_destruct(peer);
}
static void ssl_test_check_handshaker_peers(tsi_test_fixture *fixture) {
ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture;
GPR_ASSERT(ssl_fixture != NULL);
GPR_ASSERT(ssl_fixture->key_cert_lib != NULL);
ssl_key_cert_lib *key_cert_lib = ssl_fixture->key_cert_lib;
tsi_peer peer;
bool expect_success =
!(key_cert_lib->use_bad_server_cert ||
(key_cert_lib->use_bad_client_cert && ssl_fixture->force_client_auth));
if (expect_success) {
GPR_ASSERT(tsi_handshaker_result_extract_peer(
ssl_fixture->base.client_result, &peer) == TSI_OK);
check_alpn(ssl_fixture, &peer);
if (ssl_fixture->server_name_indication != NULL) {
check_server1_peer(&peer);
} else {
check_server0_peer(&peer);
}
} else {
GPR_ASSERT(ssl_fixture->base.client_result == NULL);
}
if (expect_success) {
GPR_ASSERT(tsi_handshaker_result_extract_peer(
ssl_fixture->base.server_result, &peer) == TSI_OK);
check_alpn(ssl_fixture, &peer);
check_client_peer(ssl_fixture, &peer);
} else {
GPR_ASSERT(ssl_fixture->base.server_result == NULL);
}
}
static void ssl_test_pem_key_cert_pair_destroy(tsi_ssl_pem_key_cert_pair kp) {
gpr_free((void *)kp.private_key);
gpr_free((void *)kp.cert_chain);
}
static void ssl_test_destruct(tsi_test_fixture *fixture) {
ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture;
if (ssl_fixture == NULL) {
return;
}
/* Destroy ssl_alpn_lib. */
ssl_alpn_lib *alpn_lib = ssl_fixture->alpn_lib;
for (size_t i = 0; i < alpn_lib->num_server_alpn_protocols; i++) {
gpr_free(alpn_lib->server_alpn_protocols[i]);
}
gpr_free(alpn_lib->server_alpn_protocols);
for (size_t i = 0; i < alpn_lib->num_client_alpn_protocols; i++) {
gpr_free(alpn_lib->client_alpn_protocols[i]);
}
gpr_free(alpn_lib->client_alpn_protocols);
gpr_free(alpn_lib);
/* Destroy ssl_key_cert_lib. */
ssl_key_cert_lib *key_cert_lib = ssl_fixture->key_cert_lib;
for (size_t i = 0; i < key_cert_lib->server_num_key_cert_pairs; i++) {
ssl_test_pem_key_cert_pair_destroy(
key_cert_lib->server_pem_key_cert_pairs[i]);
}
gpr_free(key_cert_lib->server_pem_key_cert_pairs);
for (size_t i = 0; i < key_cert_lib->bad_server_num_key_cert_pairs; i++) {
ssl_test_pem_key_cert_pair_destroy(
key_cert_lib->bad_server_pem_key_cert_pairs[i]);
}
gpr_free(key_cert_lib->bad_server_pem_key_cert_pairs);
ssl_test_pem_key_cert_pair_destroy(key_cert_lib->client_pem_key_cert_pair);
ssl_test_pem_key_cert_pair_destroy(
key_cert_lib->bad_client_pem_key_cert_pair);
gpr_free(key_cert_lib->root_cert);
gpr_free(key_cert_lib);
/* Destroy others. */
tsi_ssl_server_handshaker_factory_destroy(
ssl_fixture->server_handshaker_factory);
tsi_ssl_client_handshaker_factory_destroy(
ssl_fixture->client_handshaker_factory);
}
static const struct tsi_test_fixture_vtable vtable = {
ssl_test_setup_handshakers, ssl_test_check_handshaker_peers,
ssl_test_destruct};
static char *load_file(const char *dir_path, const char *file_name) {
char *file_path =
gpr_zalloc(sizeof(char) * (strlen(dir_path) + strlen(file_name) + 1));
memcpy(file_path, dir_path, strlen(dir_path));
memcpy(file_path + strlen(dir_path), file_name, strlen(file_name));
grpc_slice slice;
GPR_ASSERT(grpc_load_file(file_path, 1, &slice) == GRPC_ERROR_NONE);
char *data = grpc_slice_to_c_string(slice);
grpc_slice_unref(slice);
gpr_free(file_path);
return data;
}
static tsi_test_fixture *ssl_tsi_test_fixture_create() {
ssl_tsi_test_fixture *ssl_fixture = gpr_zalloc(sizeof(*ssl_fixture));
tsi_test_fixture_init(&ssl_fixture->base);
ssl_fixture->base.test_unused_bytes = false;
ssl_fixture->base.vtable = &vtable;
/* Create ssl_key_cert_lib. */
ssl_key_cert_lib *key_cert_lib = gpr_zalloc(sizeof(*key_cert_lib));
key_cert_lib->use_bad_server_cert = false;
key_cert_lib->use_bad_client_cert = false;
key_cert_lib->server_num_key_cert_pairs =
SSL_TSI_TEST_SERVER_KEY_CERT_PAIRS_NUM;
key_cert_lib->bad_server_num_key_cert_pairs =
SSL_TSI_TEST_BAD_SERVER_KEY_CERT_PAIRS_NUM;
key_cert_lib->server_pem_key_cert_pairs =
gpr_malloc(sizeof(tsi_ssl_pem_key_cert_pair) *
key_cert_lib->server_num_key_cert_pairs);
key_cert_lib->bad_server_pem_key_cert_pairs =
gpr_malloc(sizeof(tsi_ssl_pem_key_cert_pair) *
key_cert_lib->bad_server_num_key_cert_pairs);
key_cert_lib->server_pem_key_cert_pairs[0].private_key =
load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "server0.key");
key_cert_lib->server_pem_key_cert_pairs[0].cert_chain =
load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "server0.pem");
key_cert_lib->server_pem_key_cert_pairs[1].private_key =
load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "server1.key");
key_cert_lib->server_pem_key_cert_pairs[1].cert_chain =
load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "server1.pem");
key_cert_lib->bad_server_pem_key_cert_pairs[0].private_key =
load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "badserver.key");
key_cert_lib->bad_server_pem_key_cert_pairs[0].cert_chain =
load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "badserver.pem");
key_cert_lib->client_pem_key_cert_pair.private_key =
load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "client.key");
key_cert_lib->client_pem_key_cert_pair.cert_chain =
load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "client.pem");
key_cert_lib->bad_client_pem_key_cert_pair.private_key =
load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "badclient.key");
key_cert_lib->bad_client_pem_key_cert_pair.cert_chain =
load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "badclient.pem");
key_cert_lib->root_cert = load_file(SSL_TSI_TEST_CREDENTIALS_DIR, "ca.pem");
ssl_fixture->key_cert_lib = key_cert_lib;
/* Create ssl_alpn_lib. */
ssl_alpn_lib *alpn_lib = gpr_zalloc(sizeof(*alpn_lib));
alpn_lib->server_alpn_protocols =
gpr_zalloc(sizeof(char *) * SSL_TSI_TEST_ALPN_NUM);
alpn_lib->client_alpn_protocols =
gpr_zalloc(sizeof(char *) * SSL_TSI_TEST_ALPN_NUM);
alpn_lib->server_alpn_protocols[0] = gpr_strdup(SSL_TSI_TEST_ALPN1);
alpn_lib->server_alpn_protocols[1] = gpr_strdup(SSL_TSI_TEST_ALPN3);
alpn_lib->client_alpn_protocols[0] = gpr_strdup(SSL_TSI_TEST_ALPN2);
alpn_lib->client_alpn_protocols[1] = gpr_strdup(SSL_TSI_TEST_ALPN3);
alpn_lib->num_server_alpn_protocols = SSL_TSI_TEST_ALPN_NUM;
alpn_lib->num_client_alpn_protocols = SSL_TSI_TEST_ALPN_NUM;
alpn_lib->alpn_mode = NO_ALPN;
ssl_fixture->alpn_lib = alpn_lib;
ssl_fixture->base.vtable = &vtable;
ssl_fixture->server_name_indication = NULL;
ssl_fixture->force_client_auth = false;
return &ssl_fixture->base;
}
void ssl_tsi_test_do_handshake_tiny_handshake_buffer() {
tsi_test_fixture *fixture = ssl_tsi_test_fixture_create();
fixture->handshake_buffer_size = TSI_TEST_TINY_HANDSHAKE_BUFFER_SIZE;
tsi_test_do_handshake(fixture);
tsi_test_fixture_destroy(fixture);
}
void ssl_tsi_test_do_handshake_small_handshake_buffer() {
tsi_test_fixture *fixture = ssl_tsi_test_fixture_create();
fixture->handshake_buffer_size = TSI_TEST_SMALL_HANDSHAKE_BUFFER_SIZE;
tsi_test_do_handshake(fixture);
tsi_test_fixture_destroy(fixture);
}
void ssl_tsi_test_do_handshake() {
tsi_test_fixture *fixture = ssl_tsi_test_fixture_create();
tsi_test_do_handshake(fixture);
tsi_test_fixture_destroy(fixture);
}
void ssl_tsi_test_do_handshake_with_client_authentication() {
tsi_test_fixture *fixture = ssl_tsi_test_fixture_create();
ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture;
ssl_fixture->force_client_auth = true;
tsi_test_do_handshake(fixture);
tsi_test_fixture_destroy(fixture);
}
void ssl_tsi_test_do_handshake_with_server_name_indication_exact_domain() {
/* server1 cert contains "waterzooi.test.google.be" in SAN. */
tsi_test_fixture *fixture = ssl_tsi_test_fixture_create();
ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture;
ssl_fixture->server_name_indication = "waterzooi.test.google.be";
tsi_test_do_handshake(fixture);
tsi_test_fixture_destroy(fixture);
}
void ssl_tsi_test_do_handshake_with_server_name_indication_wild_star_domain() {
/* server1 cert contains "*.test.google.fr" in SAN. */
tsi_test_fixture *fixture = ssl_tsi_test_fixture_create();
ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture;
ssl_fixture->server_name_indication = "juju.test.google.fr";
tsi_test_do_handshake(fixture);
tsi_test_fixture_destroy(fixture);
}
void ssl_tsi_test_do_handshake_with_bad_server_cert() {
tsi_test_fixture *fixture = ssl_tsi_test_fixture_create();
ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture;
ssl_fixture->key_cert_lib->use_bad_server_cert = true;
tsi_test_do_handshake(fixture);
tsi_test_fixture_destroy(fixture);
}
void ssl_tsi_test_do_handshake_with_bad_client_cert() {
tsi_test_fixture *fixture = ssl_tsi_test_fixture_create();
ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture;
ssl_fixture->key_cert_lib->use_bad_client_cert = true;
ssl_fixture->force_client_auth = true;
tsi_test_do_handshake(fixture);
tsi_test_fixture_destroy(fixture);
}
void ssl_tsi_test_do_handshake_alpn_client_no_server() {
tsi_test_fixture *fixture = ssl_tsi_test_fixture_create();
ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture;
ssl_fixture->alpn_lib->alpn_mode = ALPN_CLIENT_NO_SERVER;
tsi_test_do_handshake(fixture);
tsi_test_fixture_destroy(fixture);
}
void ssl_tsi_test_do_handshake_alpn_server_no_client() {
tsi_test_fixture *fixture = ssl_tsi_test_fixture_create();
ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture;
ssl_fixture->alpn_lib->alpn_mode = ALPN_SERVER_NO_CLIENT;
tsi_test_do_handshake(fixture);
tsi_test_fixture_destroy(fixture);
}
void ssl_tsi_test_do_handshake_alpn_client_server_mismatch() {
tsi_test_fixture *fixture = ssl_tsi_test_fixture_create();
ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture;
ssl_fixture->alpn_lib->alpn_mode = ALPN_CLIENT_SERVER_MISMATCH;
tsi_test_do_handshake(fixture);
tsi_test_fixture_destroy(fixture);
}
void ssl_tsi_test_do_handshake_alpn_client_server_ok() {
tsi_test_fixture *fixture = ssl_tsi_test_fixture_create();
ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture;
ssl_fixture->alpn_lib->alpn_mode = ALPN_CLIENT_SERVER_OK;
tsi_test_do_handshake(fixture);
tsi_test_fixture_destroy(fixture);
}
void ssl_tsi_test_do_round_trip_for_all_configs() {
unsigned int *bit_array =
gpr_zalloc(sizeof(unsigned int) * TSI_TEST_NUM_OF_ARGUMENTS);
const unsigned int mask = 1U << (TSI_TEST_NUM_OF_ARGUMENTS - 1);
for (unsigned int val = 0; val < TSI_TEST_NUM_OF_COMBINATIONS; val++) {
unsigned int v = val;
for (unsigned int ind = 0; ind < TSI_TEST_NUM_OF_ARGUMENTS; ind++) {
bit_array[ind] = (v & mask) ? 1 : 0;
v <<= 1;
}
tsi_test_fixture *fixture = ssl_tsi_test_fixture_create();
ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture;
tsi_test_frame_protector_config_destroy(ssl_fixture->base.config);
ssl_fixture->base.config = tsi_test_frame_protector_config_create(
bit_array[0], bit_array[1], bit_array[2], bit_array[3], bit_array[4],
bit_array[5], bit_array[6], bit_array[7]);
tsi_test_do_round_trip(&ssl_fixture->base);
tsi_test_fixture_destroy(fixture);
}
gpr_free(bit_array);
}
void ssl_tsi_test_do_round_trip_odd_buffer_size() {
const size_t odd_sizes[] = {1025, 2051, 4103, 8207, 16409};
const size_t size = sizeof(odd_sizes) / sizeof(size_t);
for (size_t ind1 = 0; ind1 < size; ind1++) {
for (size_t ind2 = 0; ind2 < size; ind2++) {
for (size_t ind3 = 0; ind3 < size; ind3++) {
for (size_t ind4 = 0; ind4 < size; ind4++) {
for (size_t ind5 = 0; ind5 < size; ind5++) {
tsi_test_fixture *fixture = ssl_tsi_test_fixture_create();
ssl_tsi_test_fixture *ssl_fixture = (ssl_tsi_test_fixture *)fixture;
tsi_test_frame_protector_config_set_buffer_size(
ssl_fixture->base.config, odd_sizes[ind1], odd_sizes[ind2],
odd_sizes[ind3], odd_sizes[ind4], odd_sizes[ind5]);
tsi_test_do_round_trip(&ssl_fixture->base);
tsi_test_fixture_destroy(fixture);
}
}
}
}
}
}
int main(int argc, char **argv) {
grpc_test_init(argc, argv);
grpc_init();
ssl_tsi_test_do_handshake_tiny_handshake_buffer();
ssl_tsi_test_do_handshake_small_handshake_buffer();
ssl_tsi_test_do_handshake();
ssl_tsi_test_do_handshake_with_client_authentication();
ssl_tsi_test_do_handshake_with_server_name_indication_exact_domain();
ssl_tsi_test_do_handshake_with_server_name_indication_wild_star_domain();
ssl_tsi_test_do_handshake_with_bad_server_cert();
ssl_tsi_test_do_handshake_with_bad_client_cert();
ssl_tsi_test_do_handshake_alpn_client_no_server();
ssl_tsi_test_do_handshake_alpn_server_no_client();
ssl_tsi_test_do_handshake_alpn_client_server_mismatch();
ssl_tsi_test_do_handshake_alpn_client_server_ok();
ssl_tsi_test_do_round_trip_for_all_configs();
ssl_tsi_test_do_round_trip_odd_buffer_size();
grpc_shutdown();
return 0;
}

@ -0,0 +1,550 @@
/*
*
* Copyright 2017 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "src/core/lib/security/transport/tsi_error.h"
#include "test/core/tsi/transport_security_test_lib.h"
typedef struct handshaker_args {
tsi_test_fixture *fixture;
unsigned char *handshake_buffer;
size_t handshake_buffer_size;
bool is_client;
bool transferred_data;
bool appended_unused_bytes;
grpc_error *error;
} handshaker_args;
static handshaker_args *handshaker_args_create(tsi_test_fixture *fixture,
bool is_client) {
GPR_ASSERT(fixture != NULL);
GPR_ASSERT(fixture->config != NULL);
handshaker_args *args = gpr_zalloc(sizeof(*args));
args->fixture = fixture;
args->handshake_buffer_size = fixture->handshake_buffer_size;
args->handshake_buffer = gpr_zalloc(args->handshake_buffer_size);
args->is_client = is_client;
args->error = GRPC_ERROR_NONE;
return args;
}
static void handshaker_args_destroy(handshaker_args *args) {
gpr_free(args->handshake_buffer);
GRPC_ERROR_UNREF(args->error);
gpr_free(args);
}
static void do_handshaker_next(handshaker_args *args);
static void setup_handshakers(tsi_test_fixture *fixture) {
GPR_ASSERT(fixture != NULL);
GPR_ASSERT(fixture->vtable != NULL);
GPR_ASSERT(fixture->vtable->setup_handshakers != NULL);
fixture->vtable->setup_handshakers(fixture);
}
static void check_unused_bytes(tsi_test_fixture *fixture) {
tsi_handshaker_result *result_with_unused_bytes =
fixture->has_client_finished_first ? fixture->server_result
: fixture->client_result;
tsi_handshaker_result *result_without_unused_bytes =
fixture->has_client_finished_first ? fixture->client_result
: fixture->server_result;
const unsigned char *bytes = NULL;
size_t bytes_size = 0;
GPR_ASSERT(tsi_handshaker_result_get_unused_bytes(
result_with_unused_bytes, &bytes, &bytes_size) == TSI_OK);
GPR_ASSERT(bytes_size == strlen(TSI_TEST_UNUSED_BYTES));
GPR_ASSERT(memcmp(bytes, TSI_TEST_UNUSED_BYTES, bytes_size) == 0);
GPR_ASSERT(tsi_handshaker_result_get_unused_bytes(
result_without_unused_bytes, &bytes, &bytes_size) == TSI_OK);
GPR_ASSERT(bytes_size == 0);
GPR_ASSERT(bytes == NULL);
}
static void check_handshake_results(tsi_test_fixture *fixture) {
GPR_ASSERT(fixture != NULL);
GPR_ASSERT(fixture->vtable != NULL);
GPR_ASSERT(fixture->vtable->check_handshaker_peers != NULL);
/* Check handshaker peers. */
fixture->vtable->check_handshaker_peers(fixture);
/* Check unused bytes. */
if (fixture->test_unused_bytes) {
if (fixture->server_result != NULL && fixture->client_result != NULL) {
check_unused_bytes(fixture);
}
fixture->bytes_written_to_server_channel = 0;
fixture->bytes_written_to_client_channel = 0;
fixture->bytes_read_from_client_channel = 0;
fixture->bytes_read_from_server_channel = 0;
}
}
static void send_bytes_to_peer(tsi_test_fixture *fixture,
const unsigned char *buf, size_t buf_size,
bool is_client) {
GPR_ASSERT(fixture != NULL);
GPR_ASSERT(buf != NULL);
uint8_t *channel =
is_client ? fixture->server_channel : fixture->client_channel;
GPR_ASSERT(channel != NULL);
size_t *bytes_written = is_client ? &fixture->bytes_written_to_server_channel
: &fixture->bytes_written_to_client_channel;
GPR_ASSERT(bytes_written != NULL);
GPR_ASSERT(*bytes_written + buf_size <= TSI_TEST_DEFAULT_CHANNEL_SIZE);
/* Write data to channel. */
memcpy(channel + *bytes_written, buf, buf_size);
*bytes_written += buf_size;
}
static void maybe_append_unused_bytes(handshaker_args *args) {
GPR_ASSERT(args != NULL);
GPR_ASSERT(args->fixture != NULL);
tsi_test_fixture *fixture = args->fixture;
if (fixture->test_unused_bytes && !args->appended_unused_bytes) {
args->appended_unused_bytes = true;
send_bytes_to_peer(fixture, (const unsigned char *)TSI_TEST_UNUSED_BYTES,
strlen(TSI_TEST_UNUSED_BYTES), args->is_client);
if (fixture->client_result != NULL && fixture->server_result == NULL) {
fixture->has_client_finished_first = true;
}
}
}
static void receive_bytes_from_peer(tsi_test_fixture *fixture,
unsigned char **buf, size_t *buf_size,
bool is_client) {
GPR_ASSERT(fixture != NULL);
GPR_ASSERT(*buf != NULL);
GPR_ASSERT(buf_size != NULL);
uint8_t *channel =
is_client ? fixture->client_channel : fixture->server_channel;
GPR_ASSERT(channel != NULL);
size_t *bytes_read = is_client ? &fixture->bytes_read_from_client_channel
: &fixture->bytes_read_from_server_channel;
size_t *bytes_written = is_client ? &fixture->bytes_written_to_client_channel
: &fixture->bytes_written_to_server_channel;
GPR_ASSERT(bytes_read != NULL);
GPR_ASSERT(bytes_written != NULL);
size_t to_read = *buf_size < *bytes_written - *bytes_read
? *buf_size
: *bytes_written - *bytes_read;
/* Read data from channel. */
memcpy(*buf, channel + *bytes_read, to_read);
*buf_size = to_read;
*bytes_read += to_read;
}
static void send_message_to_peer(tsi_test_fixture *fixture,
tsi_frame_protector *protector,
bool is_client) {
/* Initialization. */
GPR_ASSERT(fixture != NULL);
GPR_ASSERT(fixture->config != NULL);
GPR_ASSERT(protector != NULL);
tsi_test_frame_protector_config *config = fixture->config;
unsigned char *protected_buffer = gpr_zalloc(config->protected_buffer_size);
size_t message_size =
is_client ? config->client_message_size : config->server_message_size;
uint8_t *message =
is_client ? config->client_message : config->server_message;
GPR_ASSERT(message != NULL);
const unsigned char *message_bytes = (const unsigned char *)message;
tsi_result result = TSI_OK;
/* Do protect and send protected data to peer. */
while (message_size > 0 && result == TSI_OK) {
size_t protected_buffer_size_to_send = config->protected_buffer_size;
size_t processed_message_size = message_size;
/* Do protect. */
result = tsi_frame_protector_protect(
protector, message_bytes, &processed_message_size, protected_buffer,
&protected_buffer_size_to_send);
GPR_ASSERT(result == TSI_OK);
/* Send protected data to peer. */
send_bytes_to_peer(fixture, protected_buffer, protected_buffer_size_to_send,
is_client);
message_bytes += processed_message_size;
message_size -= processed_message_size;
/* Flush if we're done. */
if (message_size == 0) {
size_t still_pending_size;
do {
protected_buffer_size_to_send = config->protected_buffer_size;
result = tsi_frame_protector_protect_flush(
protector, protected_buffer, &protected_buffer_size_to_send,
&still_pending_size);
GPR_ASSERT(result == TSI_OK);
send_bytes_to_peer(fixture, protected_buffer,
protected_buffer_size_to_send, is_client);
} while (still_pending_size > 0 && result == TSI_OK);
GPR_ASSERT(result == TSI_OK);
}
}
GPR_ASSERT(result == TSI_OK);
gpr_free(protected_buffer);
}
static void receive_message_from_peer(tsi_test_fixture *fixture,
tsi_frame_protector *protector,
unsigned char *message,
size_t *bytes_received, bool is_client) {
/* Initialization. */
GPR_ASSERT(fixture != NULL);
GPR_ASSERT(protector != NULL);
GPR_ASSERT(message != NULL);
GPR_ASSERT(bytes_received != NULL);
GPR_ASSERT(fixture->config != NULL);
tsi_test_frame_protector_config *config = fixture->config;
size_t read_offset = 0;
size_t message_offset = 0;
size_t read_from_peer_size = 0;
tsi_result result = TSI_OK;
bool done = false;
unsigned char *read_buffer = gpr_zalloc(config->read_buffer_allocated_size);
unsigned char *message_buffer =
gpr_zalloc(config->message_buffer_allocated_size);
/* Do unprotect on data received from peer. */
while (!done && result == TSI_OK) {
/* Receive data from peer. */
if (read_from_peer_size == 0) {
read_from_peer_size = config->read_buffer_allocated_size;
receive_bytes_from_peer(fixture, &read_buffer, &read_from_peer_size,
is_client);
read_offset = 0;
}
if (read_from_peer_size == 0) {
done = true;
}
/* Do unprotect. */
size_t message_buffer_size;
do {
message_buffer_size = config->message_buffer_allocated_size;
size_t processed_size = read_from_peer_size;
result = tsi_frame_protector_unprotect(
protector, read_buffer + read_offset, &processed_size, message_buffer,
&message_buffer_size);
GPR_ASSERT(result == TSI_OK);
if (message_buffer_size > 0) {
memcpy(message + message_offset, message_buffer, message_buffer_size);
message_offset += message_buffer_size;
}
read_offset += processed_size;
read_from_peer_size -= processed_size;
} while ((read_from_peer_size > 0 || message_buffer_size > 0) &&
result == TSI_OK);
GPR_ASSERT(result == TSI_OK);
}
GPR_ASSERT(result == TSI_OK);
*bytes_received = message_offset;
gpr_free(read_buffer);
gpr_free(message_buffer);
}
grpc_error *on_handshake_next_done(tsi_result result, void *user_data,
const unsigned char *bytes_to_send,
size_t bytes_to_send_size,
tsi_handshaker_result *handshaker_result) {
handshaker_args *args = (handshaker_args *)user_data;
GPR_ASSERT(args != NULL);
GPR_ASSERT(args->fixture != NULL);
tsi_test_fixture *fixture = args->fixture;
grpc_error *error = GRPC_ERROR_NONE;
/* Read more data if we need to. */
if (result == TSI_INCOMPLETE_DATA) {
GPR_ASSERT(bytes_to_send_size == 0);
return error;
}
if (result != TSI_OK) {
return grpc_set_tsi_error_result(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Handshake failed"), result);
}
/* Update handshaker result. */
if (handshaker_result != NULL) {
tsi_handshaker_result **result_to_write =
args->is_client ? &fixture->client_result : &fixture->server_result;
GPR_ASSERT(*result_to_write == NULL);
*result_to_write = handshaker_result;
}
/* Send data to peer, if needed. */
if (bytes_to_send_size > 0) {
send_bytes_to_peer(args->fixture, bytes_to_send, bytes_to_send_size,
args->is_client);
args->transferred_data = true;
}
if (handshaker_result != NULL) {
maybe_append_unused_bytes(args);
}
return error;
}
static void on_handshake_next_done_wrapper(
tsi_result result, void *user_data, const unsigned char *bytes_to_send,
size_t bytes_to_send_size, tsi_handshaker_result *handshaker_result) {
handshaker_args *args = (handshaker_args *)user_data;
args->error = on_handshake_next_done(result, user_data, bytes_to_send,
bytes_to_send_size, handshaker_result);
}
static bool is_handshake_finished_properly(handshaker_args *args) {
GPR_ASSERT(args != NULL);
GPR_ASSERT(args->fixture != NULL);
tsi_test_fixture *fixture = args->fixture;
if ((args->is_client && fixture->client_result != NULL) ||
(!args->is_client && fixture->server_result != NULL)) {
return true;
}
return false;
}
static void do_handshaker_next(handshaker_args *args) {
/* Initialization. */
GPR_ASSERT(args != NULL);
GPR_ASSERT(args->fixture != NULL);
tsi_test_fixture *fixture = args->fixture;
tsi_handshaker *handshaker =
args->is_client ? fixture->client_handshaker : fixture->server_handshaker;
if (is_handshake_finished_properly(args)) {
return;
}
tsi_handshaker_result *handshaker_result = NULL;
unsigned char *bytes_to_send = NULL;
size_t bytes_to_send_size = 0;
/* Receive data from peer, if available. */
size_t buf_size = args->handshake_buffer_size;
receive_bytes_from_peer(args->fixture, &args->handshake_buffer, &buf_size,
args->is_client);
if (buf_size > 0) {
args->transferred_data = true;
}
/* Peform handshaker next. */
tsi_result result = tsi_handshaker_next(
handshaker, args->handshake_buffer, buf_size,
(const unsigned char **)&bytes_to_send, &bytes_to_send_size,
&handshaker_result, &on_handshake_next_done_wrapper, args);
if (result != TSI_ASYNC) {
args->error = on_handshake_next_done(result, args, bytes_to_send,
bytes_to_send_size, handshaker_result);
}
}
void tsi_test_do_handshake(tsi_test_fixture *fixture) {
/* Initializaiton. */
setup_handshakers(fixture);
handshaker_args *client_args =
handshaker_args_create(fixture, true /* is_client */);
handshaker_args *server_args =
handshaker_args_create(fixture, false /* is_client */);
/* Do handshake. */
do {
client_args->transferred_data = false;
server_args->transferred_data = false;
do_handshaker_next(client_args);
if (client_args->error != GRPC_ERROR_NONE) {
break;
}
do_handshaker_next(server_args);
if (server_args->error != GRPC_ERROR_NONE) {
break;
}
GPR_ASSERT(client_args->transferred_data || server_args->transferred_data);
} while (fixture->client_result == NULL || fixture->server_result == NULL);
/* Verify handshake results. */
check_handshake_results(fixture);
/* Cleanup. */
handshaker_args_destroy(client_args);
handshaker_args_destroy(server_args);
}
void tsi_test_do_round_trip(tsi_test_fixture *fixture) {
/* Initialization. */
GPR_ASSERT(fixture != NULL);
GPR_ASSERT(fixture->config != NULL);
tsi_test_frame_protector_config *config = fixture->config;
tsi_frame_protector *client_frame_protector = NULL;
tsi_frame_protector *server_frame_protector = NULL;
/* Perform handshake. */
tsi_test_do_handshake(fixture);
/* Create frame protectors.*/
size_t client_max_output_protected_frame_size =
config->client_max_output_protected_frame_size;
GPR_ASSERT(tsi_handshaker_result_create_frame_protector(
fixture->client_result,
client_max_output_protected_frame_size == 0
? NULL
: &client_max_output_protected_frame_size,
&client_frame_protector) == TSI_OK);
size_t server_max_output_protected_frame_size =
config->server_max_output_protected_frame_size;
GPR_ASSERT(tsi_handshaker_result_create_frame_protector(
fixture->server_result,
server_max_output_protected_frame_size == 0
? NULL
: &server_max_output_protected_frame_size,
&server_frame_protector) == TSI_OK);
/* Client sends a message to server. */
send_message_to_peer(fixture, client_frame_protector, true /* is_client */);
unsigned char *server_received_message =
gpr_zalloc(TSI_TEST_DEFAULT_CHANNEL_SIZE);
size_t server_received_message_size = 0;
receive_message_from_peer(
fixture, server_frame_protector, server_received_message,
&server_received_message_size, false /* is_client */);
GPR_ASSERT(config->client_message_size == server_received_message_size);
GPR_ASSERT(memcmp(config->client_message, server_received_message,
server_received_message_size) == 0);
/* Server sends a message to client. */
send_message_to_peer(fixture, server_frame_protector, false /* is_client */);
unsigned char *client_received_message =
gpr_zalloc(TSI_TEST_DEFAULT_CHANNEL_SIZE);
size_t client_received_message_size = 0;
receive_message_from_peer(
fixture, client_frame_protector, client_received_message,
&client_received_message_size, true /* is_client */);
GPR_ASSERT(config->server_message_size == client_received_message_size);
GPR_ASSERT(memcmp(config->server_message, client_received_message,
client_received_message_size) == 0);
/* Destroy server and client frame protectors. */
tsi_frame_protector_destroy(client_frame_protector);
tsi_frame_protector_destroy(server_frame_protector);
gpr_free(server_received_message);
gpr_free(client_received_message);
}
static unsigned char *generate_random_message(size_t size) {
size_t i;
unsigned char chars[] = "abcdefghijklmnopqrstuvwxyz1234567890";
unsigned char *output = gpr_zalloc(sizeof(unsigned char) * size);
for (i = 0; i < size - 1; ++i) {
output[i] = chars[rand() % (int)(sizeof(chars) - 1)];
}
return output;
}
tsi_test_frame_protector_config *tsi_test_frame_protector_config_create(
bool use_default_read_buffer_allocated_size,
bool use_default_message_buffer_allocated_size,
bool use_default_protected_buffer_size, bool use_default_client_message,
bool use_default_server_message,
bool use_default_client_max_output_protected_frame_size,
bool use_default_server_max_output_protected_frame_size,
bool use_default_handshake_buffer_size) {
tsi_test_frame_protector_config *config = gpr_zalloc(sizeof(*config));
/* Set the value for read_buffer_allocated_size. */
config->read_buffer_allocated_size =
use_default_read_buffer_allocated_size
? TSI_TEST_DEFAULT_BUFFER_SIZE
: TSI_TEST_SMALL_READ_BUFFER_ALLOCATED_SIZE;
/* Set the value for message_buffer_allocated_size. */
config->message_buffer_allocated_size =
use_default_message_buffer_allocated_size
? TSI_TEST_DEFAULT_BUFFER_SIZE
: TSI_TEST_SMALL_MESSAGE_BUFFER_ALLOCATED_SIZE;
/* Set the value for protected_buffer_size. */
config->protected_buffer_size = use_default_protected_buffer_size
? TSI_TEST_DEFAULT_PROTECTED_BUFFER_SIZE
: TSI_TEST_SMALL_PROTECTED_BUFFER_SIZE;
/* Set the value for client message. */
config->client_message_size = use_default_client_message
? TSI_TEST_BIG_MESSAGE_SIZE
: TSI_TEST_SMALL_MESSAGE_SIZE;
config->client_message =
use_default_client_message
? generate_random_message(TSI_TEST_BIG_MESSAGE_SIZE)
: generate_random_message(TSI_TEST_SMALL_MESSAGE_SIZE);
/* Set the value for server message. */
config->server_message_size = use_default_server_message
? TSI_TEST_BIG_MESSAGE_SIZE
: TSI_TEST_SMALL_MESSAGE_SIZE;
config->server_message =
use_default_server_message
? generate_random_message(TSI_TEST_BIG_MESSAGE_SIZE)
: generate_random_message(TSI_TEST_SMALL_MESSAGE_SIZE);
/* Set the value for client max_output_protected_frame_size.
If it is 0, we pass NULL to tsi_handshaker_result_create_frame_protector(),
which then uses default protected frame size for it. */
config->client_max_output_protected_frame_size =
use_default_client_max_output_protected_frame_size
? 0
: TSI_TEST_SMALL_CLIENT_MAX_OUTPUT_PROTECTED_FRAME_SIZE;
/* Set the value for server max_output_protected_frame_size.
If it is 0, we pass NULL to tsi_handshaker_result_create_frame_protector(),
which then uses default protected frame size for it. */
config->server_max_output_protected_frame_size =
use_default_server_max_output_protected_frame_size
? 0
: TSI_TEST_SMALL_SERVER_MAX_OUTPUT_PROTECTED_FRAME_SIZE;
return config;
}
void tsi_test_frame_protector_config_set_buffer_size(
tsi_test_frame_protector_config *config, size_t read_buffer_allocated_size,
size_t message_buffer_allocated_size, size_t protected_buffer_size,
size_t client_max_output_protected_frame_size,
size_t server_max_output_protected_frame_size) {
GPR_ASSERT(config != NULL);
config->read_buffer_allocated_size = read_buffer_allocated_size;
config->message_buffer_allocated_size = message_buffer_allocated_size;
config->protected_buffer_size = protected_buffer_size;
config->client_max_output_protected_frame_size =
client_max_output_protected_frame_size;
config->server_max_output_protected_frame_size =
server_max_output_protected_frame_size;
}
void tsi_test_frame_protector_config_destroy(
tsi_test_frame_protector_config *config) {
GPR_ASSERT(config != NULL);
gpr_free(config->client_message);
gpr_free(config->server_message);
gpr_free(config);
}
void tsi_test_fixture_init(tsi_test_fixture *fixture) {
fixture->config = tsi_test_frame_protector_config_create(
true, true, true, true, true, true, true, true);
fixture->handshake_buffer_size = TSI_TEST_DEFAULT_BUFFER_SIZE;
fixture->client_channel = gpr_zalloc(TSI_TEST_DEFAULT_CHANNEL_SIZE);
fixture->server_channel = gpr_zalloc(TSI_TEST_DEFAULT_CHANNEL_SIZE);
fixture->bytes_written_to_client_channel = 0;
fixture->bytes_written_to_server_channel = 0;
fixture->bytes_read_from_client_channel = 0;
fixture->bytes_read_from_server_channel = 0;
fixture->test_unused_bytes = true;
fixture->has_client_finished_first = false;
}
void tsi_test_fixture_destroy(tsi_test_fixture *fixture) {
GPR_ASSERT(fixture != NULL);
tsi_test_frame_protector_config_destroy(fixture->config);
tsi_handshaker_destroy(fixture->client_handshaker);
tsi_handshaker_destroy(fixture->server_handshaker);
tsi_handshaker_result_destroy(fixture->client_result);
tsi_handshaker_result_destroy(fixture->server_result);
gpr_free(fixture->client_channel);
gpr_free(fixture->server_channel);
GPR_ASSERT(fixture->vtable != NULL);
GPR_ASSERT(fixture->vtable->destruct != NULL);
fixture->vtable->destruct(fixture);
gpr_free(fixture);
}

@ -0,0 +1,165 @@
/*
*
* Copyright 2017 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef GRPC_TEST_CORE_TSI_TRANSPORT_SECURITY_TEST_LIB_H_
#define GRPC_TEST_CORE_TSI_TRANSPORT_SECURITY_TEST_LIB_H_
#include "src/core/tsi/transport_security_interface.h"
#define TSI_TEST_TINY_HANDSHAKE_BUFFER_SIZE 32
#define TSI_TEST_SMALL_HANDSHAKE_BUFFER_SIZE 128
#define TSI_TEST_SMALL_READ_BUFFER_ALLOCATED_SIZE 41
#define TSI_TEST_SMALL_PROTECTED_BUFFER_SIZE 37
#define TSI_TEST_SMALL_MESSAGE_BUFFER_ALLOCATED_SIZE 42
#define TSI_TEST_SMALL_CLIENT_MAX_OUTPUT_PROTECTED_FRAME_SIZE 39
#define TSI_TEST_SMALL_SERVER_MAX_OUTPUT_PROTECTED_FRAME_SIZE 43
#define TSI_TEST_DEFAULT_BUFFER_SIZE 4096
#define TSI_TEST_DEFAULT_PROTECTED_BUFFER_SIZE 16384
#define TSI_TEST_DEFAULT_CHANNEL_SIZE 32768
#define TSI_TEST_BIG_MESSAGE_SIZE 17000
#define TSI_TEST_SMALL_MESSAGE_SIZE 10
#define TSI_TEST_NUM_OF_ARGUMENTS 8
#define TSI_TEST_NUM_OF_COMBINATIONS 256
#define TSI_TEST_UNUSED_BYTES "HELLO GOOGLE"
/* --- tsi_test_fixture object ---
The tests for specific TSI implementations should create their own
custom "subclass" of this fixture, which wraps all information
that will be used to test correctness of TSI handshakes and frame
protect/unprotect operations with respect to TSI implementations. */
typedef struct tsi_test_fixture tsi_test_fixture;
/* --- tsi_test_frame_protector_config object ---
This object is used to configure different parameters of TSI frame protector
APIs. */
typedef struct tsi_test_frame_protector_config tsi_test_frame_protector_config;
/* V-table for tsi_test_fixture operations that are implemented differently in
different TSI implementations. */
typedef struct tsi_test_fixture_vtable {
void (*setup_handshakers)(tsi_test_fixture *fixture);
void (*check_handshaker_peers)(tsi_test_fixture *fixture);
void (*destruct)(tsi_test_fixture *fixture);
} tranport_security_test_vtable;
struct tsi_test_fixture {
const struct tsi_test_fixture_vtable *vtable;
/* client/server TSI handshaker used to perform TSI handshakes, and will get
instantiated during the call to setup_handshakers. */
tsi_handshaker *client_handshaker;
tsi_handshaker *server_handshaker;
/* client/server TSI handshaker results used to store the result of TSI
handshake. If the handshake fails, the result will store NULL upon
finishing the handshake. */
tsi_handshaker_result *client_result;
tsi_handshaker_result *server_result;
/* size of buffer used to store data received from the peer. */
size_t handshake_buffer_size;
/* simulated channels between client and server. If the server (client)
wants to send data to the client (server), he will write data to
client_channel (server_channel), which will be read by client (server). */
uint8_t *client_channel;
uint8_t *server_channel;
/* size of data written to the client/server channel. */
size_t bytes_written_to_client_channel;
size_t bytes_written_to_server_channel;
/* size of data read from the client/server channel */
size_t bytes_read_from_client_channel;
size_t bytes_read_from_server_channel;
/* tsi_test_frame_protector_config instance */
tsi_test_frame_protector_config *config;
/* a flag indicating if client has finished TSI handshake first (i.e., before
server).
The flag should be referred if and only if TSI handshake finishes
successfully. */
bool has_client_finished_first;
/* a flag indicating whether to test tsi_handshaker_result_get_unused_bytes()
for TSI implementation. This field is true by default, and false
for SSL TSI implementation due to grpc issue #12164
(https://github.com/grpc/grpc/issues/12164).
*/
bool test_unused_bytes;
};
struct tsi_test_frame_protector_config {
/* size of buffer used to store protected frames to be unprotected. */
size_t read_buffer_allocated_size;
/* size of buffer used to store bytes resulted from unprotect operations. */
size_t message_buffer_allocated_size;
/* size of buffer used to store frames resulted from protect operations. */
size_t protected_buffer_size;
/* size of client/server maximum frame size. */
size_t client_max_output_protected_frame_size;
size_t server_max_output_protected_frame_size;
/* pointer that points to client/server message to be protected. */
uint8_t *client_message;
uint8_t *server_message;
/* size of client/server message. */
size_t client_message_size;
size_t server_message_size;
};
/* This method creates a tsi_test_frame_protector_config instance. Each
parameter of this function is a boolean value indicating whether to set the
corresponding parameter with a default value or not. If it's false, it will
be set with a specific value which is usually much smaller than the default.
Both values are defined with #define directive. */
tsi_test_frame_protector_config *tsi_test_frame_protector_config_create(
bool use_default_read_buffer_allocated_size,
bool use_default_message_buffer_allocated_size,
bool use_default_protected_buffer_size, bool use_default_client_message,
bool use_default_server_message,
bool use_default_client_max_output_protected_frame_size,
bool use_default_server_max_output_protected_frame_size,
bool use_default_handshake_buffer_size);
/* This method sets different buffer and frame sizes of a
tsi_test_frame_protector_config instance with user provided values. */
void tsi_test_frame_protector_config_set_buffer_size(
tsi_test_frame_protector_config *config, size_t read_buffer_allocated_size,
size_t message_buffer_allocated_size, size_t protected_buffer_size,
size_t client_max_output_protected_frame_size,
size_t server_max_output_protected_frame_size);
/* This method destroys a tsi_test_frame_protector_config instance. */
void tsi_test_frame_protector_config_destroy(
tsi_test_frame_protector_config *config);
/* This method initializes members of tsi_test_fixture instance.
Note that the struct instance should be allocated before making
this call. */
void tsi_test_fixture_init(tsi_test_fixture *fixture);
/* This method destroys a tsi_test_fixture instance. Note that the
fixture intance must be dynamically allocated and will be freed by
this function. */
void tsi_test_fixture_destroy(tsi_test_fixture *fixture);
/* This method performs a full TSI handshake between a client and a server.
Note that the test library will implement the new TSI handshaker API to
perform handshakes. */
void tsi_test_do_handshake(tsi_test_fixture *fixture);
/* This method performs a round trip test between the client and the server.
That is, the client sends a protected message to a server who receives the
message, and unprotects it. The same operation is triggered again with
the client and server switching its role. */
void tsi_test_do_round_trip(tsi_test_fixture *fixture);
#endif // GRPC_TEST_CORE_TSI_TRANSPORT_SECURITY_TEST_LIB_H_

@ -536,6 +536,23 @@
"third_party": false,
"type": "target"
},
{
"deps": [
"gpr",
"gpr_test_util",
"grpc",
"transport_security_test_lib"
],
"headers": [],
"is_filegroup": false,
"language": "c",
"name": "fake_transport_security_test",
"src": [
"test/core/tsi/fake_transport_security_test.c"
],
"third_party": false,
"type": "target"
},
{
"deps": [
"gpr",
@ -2163,6 +2180,23 @@
"third_party": false,
"type": "target"
},
{
"deps": [
"gpr",
"gpr_test_util",
"grpc",
"transport_security_test_lib"
],
"headers": [],
"is_filegroup": false,
"language": "c",
"name": "ssl_transport_security_test",
"src": [
"test/core/tsi/ssl_transport_security_test.c"
],
"third_party": false,
"type": "target"
},
{
"deps": [
"gpr",
@ -9106,6 +9140,23 @@
"third_party": false,
"type": "filegroup"
},
{
"deps": [
"grpc"
],
"headers": [
"test/core/tsi/transport_security_test_lib.h"
],
"is_filegroup": true,
"language": "c",
"name": "transport_security_test_lib",
"src": [
"test/core/tsi/transport_security_test_lib.c",
"test/core/tsi/transport_security_test_lib.h"
],
"third_party": false,
"type": "filegroup"
},
{
"deps": [
"gpr",

@ -643,6 +643,26 @@
"windows"
]
},
{
"args": [],
"ci_platforms": [
"linux",
"mac",
"posix"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
"gtest": false,
"language": "c",
"name": "fake_transport_security_test",
"platforms": [
"linux",
"mac",
"posix"
]
},
{
"args": [],
"ci_platforms": [
@ -2273,6 +2293,26 @@
"posix"
]
},
{
"args": [],
"ci_platforms": [
"linux",
"mac",
"posix"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
"gtest": false,
"language": "c",
"name": "ssl_transport_security_test",
"platforms": [
"linux",
"mac",
"posix"
]
},
{
"args": [],
"ci_platforms": [

@ -5,6 +5,7 @@ nonnull-attribute:rsa_blinding_get
nonnull-attribute:ssl_copy_key_material
alignment:CRYPTO_cbc128_encrypt
alignment:CRYPTO_gcm128_encrypt
alignment:poly1305_block_copy
nonnull-attribute:google::protobuf::*
alignment:google::protobuf::*
nonnull-attribute:_tr_stored_block

Loading…
Cancel
Save