Add ALTS code to grpc/core

pull/14638/head
Yihua Zhang 7 years ago
parent a5935917c5
commit 04fb58efbd
  1. 112
      BUILD
  2. 1081
      CMakeLists.txt
  3. 1329
      Makefile
  4. 9
      bazel/grpc_build_system.bzl
  5. 247
      build.yaml
  6. 62
      config.m4
  7. 63
      config.w32
  8. 41
      gRPC-C++.podspec
  9. 144
      gRPC-Core.podspec
  10. 106
      grpc.gemspec
  11. 74
      grpc.gyp
  12. 106
      package.xml
  13. 3
      setup.py
  14. 119
      src/core/lib/security/credentials/alts/alts_credentials.cc
  15. 102
      src/core/lib/security/credentials/alts/alts_credentials.h
  16. 72
      src/core/lib/security/credentials/alts/check_gcp_environment.cc
  17. 57
      src/core/lib/security/credentials/alts/check_gcp_environment.h
  18. 67
      src/core/lib/security/credentials/alts/check_gcp_environment_linux.cc
  19. 33
      src/core/lib/security/credentials/alts/check_gcp_environment_no_op.cc
  20. 114
      src/core/lib/security/credentials/alts/check_gcp_environment_windows.cc
  21. 126
      src/core/lib/security/credentials/alts/grpc_alts_credentials_client_options.cc
  22. 46
      src/core/lib/security/credentials/alts/grpc_alts_credentials_options.cc
  23. 112
      src/core/lib/security/credentials/alts/grpc_alts_credentials_options.h
  24. 58
      src/core/lib/security/credentials/alts/grpc_alts_credentials_server_options.cc
  25. 287
      src/core/lib/security/security_connector/alts_security_connector.cc
  26. 69
      src/core/lib/security/security_connector/alts_security_connector.h
  27. 8
      src/core/plugin_registry/grpc_plugin_registry.cc
  28. 687
      src/core/tsi/alts/crypt/aes_gcm.cc
  29. 189
      src/core/tsi/alts/crypt/gsec.cc
  30. 454
      src/core/tsi/alts/crypt/gsec.h
  31. 118
      src/core/tsi/alts/frame_protector/alts_counter.cc
  32. 98
      src/core/tsi/alts/frame_protector/alts_counter.h
  33. 66
      src/core/tsi/alts/frame_protector/alts_crypter.cc
  34. 255
      src/core/tsi/alts/frame_protector/alts_crypter.h
  35. 407
      src/core/tsi/alts/frame_protector/alts_frame_protector.cc
  36. 55
      src/core/tsi/alts/frame_protector/alts_frame_protector.h
  37. 114
      src/core/tsi/alts/frame_protector/alts_record_protocol_crypter_common.cc
  38. 114
      src/core/tsi/alts/frame_protector/alts_record_protocol_crypter_common.h
  39. 105
      src/core/tsi/alts/frame_protector/alts_seal_privacy_integrity_crypter.cc
  40. 103
      src/core/tsi/alts/frame_protector/alts_unseal_privacy_integrity_crypter.cc
  41. 218
      src/core/tsi/alts/frame_protector/frame_handler.cc
  42. 236
      src/core/tsi/alts/frame_protector/frame_handler.h
  43. 316
      src/core/tsi/alts/handshaker/alts_handshaker_client.cc
  44. 137
      src/core/tsi/alts/handshaker/alts_handshaker_client.h
  45. 520
      src/core/tsi/alts/handshaker/alts_handshaker_service_api.cc
  46. 323
      src/core/tsi/alts/handshaker/alts_handshaker_service_api.h
  47. 143
      src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.cc
  48. 149
      src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.h
  49. 73
      src/core/tsi/alts/handshaker/alts_tsi_event.cc
  50. 93
      src/core/tsi/alts/handshaker/alts_tsi_event.h
  51. 483
      src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc
  52. 83
      src/core/tsi/alts/handshaker/alts_tsi_handshaker.h
  53. 52
      src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h
  54. 58
      src/core/tsi/alts/handshaker/alts_tsi_utils.cc
  55. 52
      src/core/tsi/alts/handshaker/alts_tsi_utils.h
  56. 48
      src/core/tsi/alts/handshaker/altscontext.pb.c
  57. 64
      src/core/tsi/alts/handshaker/altscontext.pb.h
  58. 123
      src/core/tsi/alts/handshaker/handshaker.pb.c
  59. 255
      src/core/tsi/alts/handshaker/handshaker.pb.h
  60. 41
      src/core/tsi/alts/handshaker/proto/altscontext.proto
  61. 2
      src/core/tsi/alts/handshaker/proto/handshaker.options
  62. 220
      src/core/tsi/alts/handshaker/proto/handshaker.proto
  63. 40
      src/core/tsi/alts/handshaker/proto/transport_security_common.proto
  64. 50
      src/core/tsi/alts/handshaker/transport_security_common.pb.c
  65. 78
      src/core/tsi/alts/handshaker/transport_security_common.pb.h
  66. 196
      src/core/tsi/alts/handshaker/transport_security_common_api.cc
  67. 163
      src/core/tsi/alts/handshaker/transport_security_common_api.h
  68. 180
      src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.cc
  69. 52
      src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.h
  70. 144
      src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.cc
  71. 49
      src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.h
  72. 91
      src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol.h
  73. 173
      src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.cc
  74. 100
      src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.h
  75. 476
      src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.cc
  76. 199
      src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.h
  77. 295
      src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.cc
  78. 52
      src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.h
  79. 57
      src/python/grpcio/grpc_core_dependencies.py
  80. 2
      templates/CMakeLists.txt.template
  81. 2
      templates/Makefile.template
  82. 2
      templates/gRPC-Core.podspec.template
  83. 6
      templates/grpc.gyp.template
  84. 49
      test/core/security/BUILD
  85. 166
      test/core/security/alts_security_connector_test.cc
  86. 83
      test/core/security/check_gcp_environment_linux_test.cc
  87. 71
      test/core/security/check_gcp_environment_windows_test.cc
  88. 118
      test/core/security/grpc_alts_credentials_options_test.cc
  89. 2
      test/core/tsi/BUILD
  90. 42
      test/core/tsi/alts/crypt/BUILD
  91. 2105
      test/core/tsi/alts/crypt/aes_gcm_test.cc
  92. 89
      test/core/tsi/alts/crypt/gsec_test_util.cc
  93. 89
      test/core/tsi/alts/crypt/gsec_test_util.h
  94. 71
      test/core/tsi/alts/frame_protector/BUILD
  95. 180
      test/core/tsi/alts/frame_protector/alts_counter_test.cc
  96. 493
      test/core/tsi/alts/frame_protector/alts_crypter_test.cc
  97. 394
      test/core/tsi/alts/frame_protector/alts_frame_protector_test.cc
  98. 244
      test/core/tsi/alts/frame_protector/frame_handler_test.cc
  99. 86
      test/core/tsi/alts/handshaker/BUILD
  100. 412
      test/core/tsi/alts/handshaker/alts_handshaker_client_test.cc
  101. Some files were not shown because too many files have changed in this diff Show More

112
BUILD

@ -1326,6 +1326,8 @@ grpc_cc_library(
"src/core/lib/security/credentials/oauth2/oauth2_credentials.cc",
"src/core/lib/security/credentials/plugin/plugin_credentials.cc",
"src/core/lib/security/credentials/ssl/ssl_credentials.cc",
"src/core/lib/security/credentials/alts/alts_credentials.cc",
"src/core/lib/security/security_connector/alts_security_connector.cc",
"src/core/lib/security/security_connector/security_connector.cc",
"src/core/lib/security/transport/client_auth_filter.cc",
"src/core/lib/security/transport/secure_endpoint.cc",
@ -1349,6 +1351,8 @@ grpc_cc_library(
"src/core/lib/security/credentials/oauth2/oauth2_credentials.h",
"src/core/lib/security/credentials/plugin/plugin_credentials.h",
"src/core/lib/security/credentials/ssl/ssl_credentials.h",
"src/core/lib/security/credentials/alts/alts_credentials.h",
"src/core/lib/security/security_connector/alts_security_connector.h",
"src/core/lib/security/security_connector/security_connector.h",
"src/core/lib/security/transport/auth_filters.h",
"src/core/lib/security/transport/secure_endpoint.h",
@ -1360,6 +1364,7 @@ grpc_cc_library(
language = "c++",
public_hdrs = GRPC_SECURE_PUBLIC_HDRS,
deps = [
"alts_util",
"grpc_base",
"grpc_transport_chttp2_alpn",
"tsi",
@ -1582,16 +1587,119 @@ grpc_cc_library(
],
)
grpc_cc_library(
name = "alts_frame_protector",
srcs = [
"src/core/tsi/alts/crypt/aes_gcm.cc",
"src/core/tsi/alts/crypt/gsec.cc",
"src/core/tsi/alts/frame_protector/alts_counter.cc",
"src/core/tsi/alts/frame_protector/alts_crypter.cc",
"src/core/tsi/alts/frame_protector/alts_frame_protector.cc",
"src/core/tsi/alts/frame_protector/alts_record_protocol_crypter_common.cc",
"src/core/tsi/alts/frame_protector/alts_seal_privacy_integrity_crypter.cc",
"src/core/tsi/alts/frame_protector/alts_unseal_privacy_integrity_crypter.cc",
"src/core/tsi/alts/frame_protector/frame_handler.cc",
"src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.cc",
"src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.cc",
"src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.cc",
"src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.cc",
"src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.cc",
],
hdrs = [
"src/core/tsi/alts/crypt/gsec.h",
"src/core/tsi/alts/frame_protector/alts_counter.h",
"src/core/tsi/alts/frame_protector/alts_crypter.h",
"src/core/tsi/alts/frame_protector/alts_frame_protector.h",
"src/core/tsi/alts/frame_protector/alts_record_protocol_crypter_common.h",
"src/core/tsi/alts/frame_protector/frame_handler.h",
"src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.h",
"src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.h",
"src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.h",
"src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol.h",
"src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.h",
"src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.h",
"src/core/tsi/transport_security_grpc.h",
],
external_deps = [
"libssl",
],
language = "c++",
deps = [
"gpr",
"grpc_base",
"tsi_interface",
],
)
grpc_cc_library(
name = "alts_proto",
srcs = [
"src/core/tsi/alts/handshaker/altscontext.pb.c",
"src/core/tsi/alts/handshaker/handshaker.pb.c",
"src/core/tsi/alts/handshaker/transport_security_common.pb.c",
],
hdrs = [
"src/core/tsi/alts/handshaker/altscontext.pb.h",
"src/core/tsi/alts/handshaker/handshaker.pb.h",
"src/core/tsi/alts/handshaker/transport_security_common.pb.h",
],
external_deps = [
"nanopb",
],
language = "c++",
)
grpc_cc_library(
name = "alts_util",
srcs = [
"src/core/lib/security/credentials/alts/check_gcp_environment.cc",
"src/core/lib/security/credentials/alts/check_gcp_environment_linux.cc",
"src/core/lib/security/credentials/alts/check_gcp_environment_no_op.cc",
"src/core/lib/security/credentials/alts/check_gcp_environment_windows.cc",
"src/core/lib/security/credentials/alts/grpc_alts_credentials_client_options.cc",
"src/core/lib/security/credentials/alts/grpc_alts_credentials_options.cc",
"src/core/lib/security/credentials/alts/grpc_alts_credentials_server_options.cc",
"src/core/tsi/alts/handshaker/alts_handshaker_service_api.cc",
"src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.cc",
"src/core/tsi/alts/handshaker/transport_security_common_api.cc",
],
hdrs = [
"src/core/lib/security/credentials/alts/check_gcp_environment.h",
"src/core/lib/security/credentials/alts/grpc_alts_credentials_options.h",
"src/core/tsi/alts/handshaker/alts_handshaker_service_api.h",
"src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.h",
"src/core/tsi/alts/handshaker/transport_security_common_api.h",
],
external_deps = [
"nanopb",
],
language = "c++",
deps = [
"alts_proto",
"gpr",
"grpc_base",
],
)
grpc_cc_library(
name = "tsi",
srcs = [
"src/core/tsi/alts_transport_security.cc",
"src/core/tsi/alts/handshaker/alts_handshaker_client.cc",
"src/core/tsi/alts/handshaker/alts_tsi_event.cc",
"src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc",
"src/core/tsi/alts/handshaker/alts_tsi_utils.cc",
"src/core/tsi/fake_transport_security.cc",
"src/core/tsi/ssl_transport_security.cc",
"src/core/tsi/transport_security_grpc.cc",
],
hdrs = [
"src/core/tsi/alts_transport_security.h",
"src/core/tsi/alts/handshaker/alts_handshaker_client.h",
"src/core/tsi/alts/handshaker/alts_tsi_event.h",
"src/core/tsi/alts/handshaker/alts_tsi_handshaker.h",
"src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h",
"src/core/tsi/alts/handshaker/alts_tsi_utils.h",
"src/core/tsi/fake_transport_security.h",
"src/core/tsi/ssl_transport_security.h",
"src/core/tsi/ssl_types.h",
@ -1602,7 +1710,11 @@ grpc_cc_library(
],
language = "c++",
deps = [
"alts_frame_protector",
"alts_util",
"gpr",
"grpc_base",
"grpc_transport_chttp2_client_insecure",
"tsi_interface",
],
)

File diff suppressed because it is too large Load Diff

1329
Makefile

File diff suppressed because it is too large Load Diff

@ -57,6 +57,12 @@ def _maybe_update_cc_library_hdrs(hdrs):
ret.append(h)
return ret
def _maybe_update_cc_library_defines(name):
ret = []
if name == "alts_proto":
ret += ["PB_FIELD_16BIT=1"]
return ret
def grpc_cc_library(name, srcs = [], public_hdrs = [], hdrs = [],
external_deps = [], deps = [], standalone = False,
language = "C++", testonly = False, visibility = None,
@ -64,10 +70,11 @@ def grpc_cc_library(name, srcs = [], public_hdrs = [], hdrs = [],
copts = []
if language.upper() == "C":
copts = if_not_windows(["-std=c99"])
defines = _maybe_update_cc_library_defines(name)
native.cc_library(
name = name,
srcs = srcs,
defines = select({"//:grpc_no_ares": ["GRPC_ARES=0"],
defines = defines + select({"//:grpc_no_ares": ["GRPC_ARES=0"],
"//conditions:default": [],}) +
select({"//:remote_execution": ["GRPC_PORT_ISOLATED_RUNTIME=1"],
"//conditions:default": [],}) +

@ -16,6 +16,84 @@ settings:
g_stands_for: gorgeous
version: 1.11.0-dev
filegroups:
- name: alts_proto
headers:
- src/core/tsi/alts/handshaker/altscontext.pb.h
- src/core/tsi/alts/handshaker/handshaker.pb.h
- src/core/tsi/alts/handshaker/transport_security_common.pb.h
src:
- src/core/tsi/alts/handshaker/altscontext.pb.c
- src/core/tsi/alts/handshaker/handshaker.pb.c
- src/core/tsi/alts/handshaker/transport_security_common.pb.c
uses:
- nanopb
- name: alts_tsi
headers:
- src/core/tsi/alts/crypt/gsec.h
- src/core/tsi/alts/frame_protector/alts_counter.h
- src/core/tsi/alts/frame_protector/alts_crypter.h
- src/core/tsi/alts/frame_protector/alts_frame_protector.h
- src/core/tsi/alts/frame_protector/alts_record_protocol_crypter_common.h
- src/core/tsi/alts/frame_protector/frame_handler.h
- src/core/tsi/alts/handshaker/alts_handshaker_client.h
- src/core/tsi/alts/handshaker/alts_tsi_event.h
- src/core/tsi/alts/handshaker/alts_tsi_handshaker.h
- src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h
- src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.h
- src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.h
- src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol.h
- src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.h
- src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.h
- src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.h
src:
- src/core/tsi/alts/crypt/aes_gcm.cc
- src/core/tsi/alts/crypt/gsec.cc
- src/core/tsi/alts/frame_protector/alts_counter.cc
- src/core/tsi/alts/frame_protector/alts_crypter.cc
- src/core/tsi/alts/frame_protector/alts_frame_protector.cc
- src/core/tsi/alts/frame_protector/alts_record_protocol_crypter_common.cc
- src/core/tsi/alts/frame_protector/alts_seal_privacy_integrity_crypter.cc
- src/core/tsi/alts/frame_protector/alts_unseal_privacy_integrity_crypter.cc
- src/core/tsi/alts/frame_protector/frame_handler.cc
- src/core/tsi/alts/handshaker/alts_handshaker_client.cc
- src/core/tsi/alts/handshaker/alts_tsi_event.cc
- src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc
- src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.cc
- src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.cc
- src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.cc
- src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.cc
- src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.cc
uses:
- alts_util
- grpc_base
- grpc_transport_chttp2_client_insecure
- tsi_interface
- tsi
- name: alts_util
headers:
- src/core/lib/security/credentials/alts/check_gcp_environment.h
- src/core/lib/security/credentials/alts/grpc_alts_credentials_options.h
- src/core/tsi/alts/handshaker/alts_handshaker_service_api.h
- src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.h
- src/core/tsi/alts/handshaker/alts_tsi_utils.h
- src/core/tsi/alts/handshaker/transport_security_common_api.h
src:
- src/core/lib/security/credentials/alts/check_gcp_environment.cc
- src/core/lib/security/credentials/alts/check_gcp_environment_linux.cc
- src/core/lib/security/credentials/alts/check_gcp_environment_no_op.cc
- src/core/lib/security/credentials/alts/check_gcp_environment_windows.cc
- src/core/lib/security/credentials/alts/grpc_alts_credentials_client_options.cc
- src/core/lib/security/credentials/alts/grpc_alts_credentials_options.cc
- src/core/lib/security/credentials/alts/grpc_alts_credentials_server_options.cc
- src/core/tsi/alts/handshaker/alts_handshaker_service_api.cc
- src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.cc
- src/core/tsi/alts/handshaker/alts_tsi_utils.cc
- src/core/tsi/alts/handshaker/transport_security_common_api.cc
uses:
- alts_proto
- grpc_base
- tsi_interface
- nanopb
- name: census
public_headers:
- include/grpc/census.h
@ -642,6 +720,7 @@ filegroups:
- include/grpc/grpc_security.h
headers:
- src/core/lib/security/context/security_context.h
- src/core/lib/security/credentials/alts/alts_credentials.h
- src/core/lib/security/credentials/composite/composite_credentials.h
- src/core/lib/security/credentials/credentials.h
- src/core/lib/security/credentials/fake/fake_credentials.h
@ -653,6 +732,7 @@ filegroups:
- src/core/lib/security/credentials/oauth2/oauth2_credentials.h
- src/core/lib/security/credentials/plugin/plugin_credentials.h
- src/core/lib/security/credentials/ssl/ssl_credentials.h
- src/core/lib/security/security_connector/alts_security_connector.h
- src/core/lib/security/security_connector/security_connector.h
- src/core/lib/security/transport/auth_filters.h
- src/core/lib/security/transport/secure_endpoint.h
@ -663,6 +743,7 @@ filegroups:
src:
- src/core/lib/http/httpcli_security_connector.cc
- src/core/lib/security/context/security_context.cc
- src/core/lib/security/credentials/alts/alts_credentials.cc
- src/core/lib/security/credentials/composite/composite_credentials.cc
- src/core/lib/security/credentials/credentials.cc
- src/core/lib/security/credentials/credentials_metadata.cc
@ -676,6 +757,7 @@ filegroups:
- src/core/lib/security/credentials/oauth2/oauth2_credentials.cc
- src/core/lib/security/credentials/plugin/plugin_credentials.cc
- src/core/lib/security/credentials/ssl/ssl_credentials.cc
- src/core/lib/security/security_connector/alts_security_connector.cc
- src/core/lib/security/security_connector/security_connector.cc
- src/core/lib/security/transport/client_auth_filter.cc
- src/core/lib/security/transport/secure_endpoint.cc
@ -687,6 +769,7 @@ filegroups:
- src/core/lib/surface/init_secure.cc
secure: true
uses:
- alts_tsi
- grpc_base
- grpc_transport_chttp2_alpn
- tsi
@ -1211,6 +1294,18 @@ filegroups:
- grpc++
- grpc
libs:
- name: alts_test_util
build: private
language: c
headers:
- test/core/tsi/alts/crypt/gsec_test_util.h
- test/core/tsi/alts/handshaker/alts_handshaker_service_api_test_lib.h
src:
- test/core/tsi/alts/crypt/gsec_test_util.cc
- test/core/tsi/alts/handshaker/alts_handshaker_service_api_test_lib.cc
deps:
- grpc
secure: true
- name: gpr
build: all
language: c
@ -3496,6 +3591,125 @@ targets:
- grpc_unsecure
- gpr_test_util
- gpr
- name: alts_counter_test
build: test
language: c++
src:
- test/core/tsi/alts/frame_protector/alts_counter_test.cc
deps:
- alts_test_util
- gpr
- grpc
- name: alts_crypt_test
build: test
language: c++
src:
- test/core/tsi/alts/crypt/aes_gcm_test.cc
deps:
- alts_test_util
- gpr_test_util
- gpr
- grpc
- name: alts_crypter_test
build: test
language: c++
src:
- test/core/tsi/alts/frame_protector/alts_crypter_test.cc
deps:
- alts_test_util
- gpr
- grpc
- name: alts_frame_handler_test
build: test
language: c++
src:
- test/core/tsi/alts/frame_protector/frame_handler_test.cc
deps:
- alts_test_util
- gpr
- grpc
- name: alts_frame_protector_test
build: test
language: c++
src:
- test/core/tsi/alts/frame_protector/alts_frame_protector_test.cc
deps:
- alts_test_util
- gpr
- grpc
filegroups:
- transport_security_test_lib
- name: alts_grpc_record_protocol_test
build: test
language: c++
src:
- test/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_test.cc
deps:
- alts_test_util
- gpr
- grpc
- name: alts_handshaker_client_test
build: test
language: c++
src:
- test/core/tsi/alts/handshaker/alts_handshaker_client_test.cc
deps:
- alts_test_util
- gpr
- grpc
- name: alts_handshaker_service_api_test
build: test
language: c++
src:
- test/core/tsi/alts/handshaker/alts_handshaker_service_api_test.cc
deps:
- alts_test_util
- gpr
- grpc
- name: alts_iovec_record_protocol_test
build: test
language: c++
src:
- test/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol_test.cc
deps:
- alts_test_util
- gpr
- grpc
- name: alts_security_connector_test
build: test
language: c++
src:
- test/core/security/alts_security_connector_test.cc
deps:
- gpr
- grpc
- name: alts_tsi_handshaker_test
build: test
language: c++
src:
- test/core/tsi/alts/handshaker/alts_tsi_handshaker_test.cc
deps:
- alts_test_util
- gpr
- grpc
- name: alts_tsi_utils_test
build: test
language: c++
src:
- test/core/tsi/alts/handshaker/alts_tsi_utils_test.cc
deps:
- alts_test_util
- gpr
- grpc
- name: alts_zero_copy_grpc_protector_test
build: test
language: c++
src:
- test/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector_test.cc
deps:
- alts_test_util
- gpr
- grpc
- name: async_end2end_test
gtest: true
build: test
@ -3879,6 +4093,22 @@ targets:
- grpc
- gpr
uses_polling: false
- name: check_gcp_environment_linux_test
build: test
language: c++
src:
- test/core/security/check_gcp_environment_linux_test.cc
deps:
- grpc
- gpr
- name: check_gcp_environment_windows_test
build: test
language: c++
src:
- test/core/security/check_gcp_environment_windows_test.cc
deps:
- grpc
- gpr
- name: chttp2_settings_timeout_test
gtest: true
build: test
@ -4137,6 +4367,14 @@ targets:
args:
- --generated_file_path=gens/src/proto/grpc/testing/
uses_polling: false
- name: grpc_alts_credentials_options_test
build: test
language: c++
src:
- test/core/security/grpc_alts_credentials_options_test.cc
deps:
- grpc
- gpr
- name: grpc_cli
build: test
run: false
@ -4972,6 +5210,15 @@ targets:
- grpc
- gpr_test_util
- gpr
- name: transport_security_common_api_test
build: test
language: c++
src:
- test/core/tsi/alts/handshaker/transport_security_common_api_test.cc
deps:
- alts_test_util
- gpr
- grpc
- name: writes_per_rpc_test
gtest: true
cpu_cost: 0.5

@ -244,6 +244,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/filters/http/server/http_server_filter.cc \
src/core/lib/http/httpcli_security_connector.cc \
src/core/lib/security/context/security_context.cc \
src/core/lib/security/credentials/alts/alts_credentials.cc \
src/core/lib/security/credentials/composite/composite_credentials.cc \
src/core/lib/security/credentials/credentials.cc \
src/core/lib/security/credentials/credentials_metadata.cc \
@ -257,6 +258,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/security/credentials/oauth2/oauth2_credentials.cc \
src/core/lib/security/credentials/plugin/plugin_credentials.cc \
src/core/lib/security/credentials/ssl/ssl_credentials.cc \
src/core/lib/security/security_connector/alts_security_connector.cc \
src/core/lib/security/security_connector/security_connector.cc \
src/core/lib/security/transport/client_auth_filter.cc \
src/core/lib/security/transport/secure_endpoint.cc \
@ -266,14 +268,45 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/security/transport/tsi_error.cc \
src/core/lib/security/util/json_util.cc \
src/core/lib/surface/init_secure.cc \
src/core/tsi/alts_transport_security.cc \
src/core/tsi/fake_transport_security.cc \
src/core/tsi/ssl_transport_security.cc \
src/core/tsi/transport_security_grpc.cc \
src/core/tsi/alts/crypt/aes_gcm.cc \
src/core/tsi/alts/crypt/gsec.cc \
src/core/tsi/alts/frame_protector/alts_counter.cc \
src/core/tsi/alts/frame_protector/alts_crypter.cc \
src/core/tsi/alts/frame_protector/alts_frame_protector.cc \
src/core/tsi/alts/frame_protector/alts_record_protocol_crypter_common.cc \
src/core/tsi/alts/frame_protector/alts_seal_privacy_integrity_crypter.cc \
src/core/tsi/alts/frame_protector/alts_unseal_privacy_integrity_crypter.cc \
src/core/tsi/alts/frame_protector/frame_handler.cc \
src/core/tsi/alts/handshaker/alts_handshaker_client.cc \
src/core/tsi/alts/handshaker/alts_tsi_event.cc \
src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc \
src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.cc \
src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.cc \
src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.cc \
src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.cc \
src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.cc \
src/core/lib/security/credentials/alts/check_gcp_environment.cc \
src/core/lib/security/credentials/alts/check_gcp_environment_linux.cc \
src/core/lib/security/credentials/alts/check_gcp_environment_no_op.cc \
src/core/lib/security/credentials/alts/check_gcp_environment_windows.cc \
src/core/lib/security/credentials/alts/grpc_alts_credentials_client_options.cc \
src/core/lib/security/credentials/alts/grpc_alts_credentials_options.cc \
src/core/lib/security/credentials/alts/grpc_alts_credentials_server_options.cc \
src/core/tsi/alts/handshaker/alts_handshaker_service_api.cc \
src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.cc \
src/core/tsi/alts/handshaker/alts_tsi_utils.cc \
src/core/tsi/alts/handshaker/transport_security_common_api.cc \
src/core/tsi/alts/handshaker/altscontext.pb.c \
src/core/tsi/alts/handshaker/handshaker.pb.c \
src/core/tsi/alts/handshaker/transport_security_common.pb.c \
third_party/nanopb/pb_common.c \
third_party/nanopb/pb_decode.c \
third_party/nanopb/pb_encode.c \
src/core/tsi/transport_security.cc \
src/core/tsi/transport_security_adapter.cc \
src/core/ext/transport/chttp2/server/chttp2_server.cc \
src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc \
src/core/ext/transport/chttp2/client/insecure/channel_create.cc \
src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc \
src/core/ext/transport/chttp2/client/chttp2_connector.cc \
src/core/ext/filters/client_channel/backup_poller.cc \
src/core/ext/filters/client_channel/channel_connectivity.cc \
src/core/ext/filters/client_channel/client_channel.cc \
@ -297,11 +330,14 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/filters/client_channel/subchannel_index.cc \
src/core/ext/filters/client_channel/uri_parser.cc \
src/core/ext/filters/deadline/deadline_filter.cc \
src/core/ext/transport/chttp2/client/chttp2_connector.cc \
src/core/tsi/alts_transport_security.cc \
src/core/tsi/fake_transport_security.cc \
src/core/tsi/ssl_transport_security.cc \
src/core/tsi/transport_security_grpc.cc \
src/core/ext/transport/chttp2/server/chttp2_server.cc \
src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc \
src/core/ext/transport/chttp2/server/insecure/server_chttp2.cc \
src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.cc \
src/core/ext/transport/chttp2/client/insecure/channel_create.cc \
src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc \
src/core/ext/transport/inproc/inproc_plugin.cc \
src/core/ext/transport/inproc/inproc_transport.cc \
src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc \
@ -310,9 +346,6 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc \
src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc \
src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \
third_party/nanopb/pb_common.c \
third_party/nanopb/pb_decode.c \
third_party/nanopb/pb_encode.c \
src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc \
src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc \
src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc \
@ -635,6 +668,7 @@ if test "$PHP_GRPC" != "no"; then
PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/profiling)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/context)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/alts)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/composite)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/fake)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/google_default)
@ -651,6 +685,10 @@ if test "$PHP_GRPC" != "no"; then
PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/transport)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/plugin_registry)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/tsi)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/tsi/alts/crypt)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/tsi/alts/frame_protector)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/tsi/alts/handshaker)
PHP_ADD_BUILD_DIR($ext_builddir/src/core/tsi/alts/zero_copy_frame_protector)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/asn1)
PHP_ADD_BUILD_DIR($ext_builddir/third_party/boringssl/crypto/base64)

@ -221,6 +221,7 @@ if (PHP_GRPC != "no") {
"src\\core\\ext\\filters\\http\\server\\http_server_filter.cc " +
"src\\core\\lib\\http\\httpcli_security_connector.cc " +
"src\\core\\lib\\security\\context\\security_context.cc " +
"src\\core\\lib\\security\\credentials\\alts\\alts_credentials.cc " +
"src\\core\\lib\\security\\credentials\\composite\\composite_credentials.cc " +
"src\\core\\lib\\security\\credentials\\credentials.cc " +
"src\\core\\lib\\security\\credentials\\credentials_metadata.cc " +
@ -234,6 +235,7 @@ if (PHP_GRPC != "no") {
"src\\core\\lib\\security\\credentials\\oauth2\\oauth2_credentials.cc " +
"src\\core\\lib\\security\\credentials\\plugin\\plugin_credentials.cc " +
"src\\core\\lib\\security\\credentials\\ssl\\ssl_credentials.cc " +
"src\\core\\lib\\security\\security_connector\\alts_security_connector.cc " +
"src\\core\\lib\\security\\security_connector\\security_connector.cc " +
"src\\core\\lib\\security\\transport\\client_auth_filter.cc " +
"src\\core\\lib\\security\\transport\\secure_endpoint.cc " +
@ -243,14 +245,45 @@ if (PHP_GRPC != "no") {
"src\\core\\lib\\security\\transport\\tsi_error.cc " +
"src\\core\\lib\\security\\util\\json_util.cc " +
"src\\core\\lib\\surface\\init_secure.cc " +
"src\\core\\tsi\\alts_transport_security.cc " +
"src\\core\\tsi\\fake_transport_security.cc " +
"src\\core\\tsi\\ssl_transport_security.cc " +
"src\\core\\tsi\\transport_security_grpc.cc " +
"src\\core\\tsi\\alts\\crypt\\aes_gcm.cc " +
"src\\core\\tsi\\alts\\crypt\\gsec.cc " +
"src\\core\\tsi\\alts\\frame_protector\\alts_counter.cc " +
"src\\core\\tsi\\alts\\frame_protector\\alts_crypter.cc " +
"src\\core\\tsi\\alts\\frame_protector\\alts_frame_protector.cc " +
"src\\core\\tsi\\alts\\frame_protector\\alts_record_protocol_crypter_common.cc " +
"src\\core\\tsi\\alts\\frame_protector\\alts_seal_privacy_integrity_crypter.cc " +
"src\\core\\tsi\\alts\\frame_protector\\alts_unseal_privacy_integrity_crypter.cc " +
"src\\core\\tsi\\alts\\frame_protector\\frame_handler.cc " +
"src\\core\\tsi\\alts\\handshaker\\alts_handshaker_client.cc " +
"src\\core\\tsi\\alts\\handshaker\\alts_tsi_event.cc " +
"src\\core\\tsi\\alts\\handshaker\\alts_tsi_handshaker.cc " +
"src\\core\\tsi\\alts\\zero_copy_frame_protector\\alts_grpc_integrity_only_record_protocol.cc " +
"src\\core\\tsi\\alts\\zero_copy_frame_protector\\alts_grpc_privacy_integrity_record_protocol.cc " +
"src\\core\\tsi\\alts\\zero_copy_frame_protector\\alts_grpc_record_protocol_common.cc " +
"src\\core\\tsi\\alts\\zero_copy_frame_protector\\alts_iovec_record_protocol.cc " +
"src\\core\\tsi\\alts\\zero_copy_frame_protector\\alts_zero_copy_grpc_protector.cc " +
"src\\core\\lib\\security\\credentials\\alts\\check_gcp_environment.cc " +
"src\\core\\lib\\security\\credentials\\alts\\check_gcp_environment_linux.cc " +
"src\\core\\lib\\security\\credentials\\alts\\check_gcp_environment_no_op.cc " +
"src\\core\\lib\\security\\credentials\\alts\\check_gcp_environment_windows.cc " +
"src\\core\\lib\\security\\credentials\\alts\\grpc_alts_credentials_client_options.cc " +
"src\\core\\lib\\security\\credentials\\alts\\grpc_alts_credentials_options.cc " +
"src\\core\\lib\\security\\credentials\\alts\\grpc_alts_credentials_server_options.cc " +
"src\\core\\tsi\\alts\\handshaker\\alts_handshaker_service_api.cc " +
"src\\core\\tsi\\alts\\handshaker\\alts_handshaker_service_api_util.cc " +
"src\\core\\tsi\\alts\\handshaker\\alts_tsi_utils.cc " +
"src\\core\\tsi\\alts\\handshaker\\transport_security_common_api.cc " +
"src\\core\\tsi\\alts\\handshaker\\altscontext.pb.c " +
"src\\core\\tsi\\alts\\handshaker\\handshaker.pb.c " +
"src\\core\\tsi\\alts\\handshaker\\transport_security_common.pb.c " +
"third_party\\nanopb\\pb_common.c " +
"third_party\\nanopb\\pb_decode.c " +
"third_party\\nanopb\\pb_encode.c " +
"src\\core\\tsi\\transport_security.cc " +
"src\\core\\tsi\\transport_security_adapter.cc " +
"src\\core\\ext\\transport\\chttp2\\server\\chttp2_server.cc " +
"src\\core\\ext\\transport\\chttp2\\client\\secure\\secure_channel_create.cc " +
"src\\core\\ext\\transport\\chttp2\\client\\insecure\\channel_create.cc " +
"src\\core\\ext\\transport\\chttp2\\client\\insecure\\channel_create_posix.cc " +
"src\\core\\ext\\transport\\chttp2\\client\\chttp2_connector.cc " +
"src\\core\\ext\\filters\\client_channel\\backup_poller.cc " +
"src\\core\\ext\\filters\\client_channel\\channel_connectivity.cc " +
"src\\core\\ext\\filters\\client_channel\\client_channel.cc " +
@ -274,11 +307,14 @@ if (PHP_GRPC != "no") {
"src\\core\\ext\\filters\\client_channel\\subchannel_index.cc " +
"src\\core\\ext\\filters\\client_channel\\uri_parser.cc " +
"src\\core\\ext\\filters\\deadline\\deadline_filter.cc " +
"src\\core\\ext\\transport\\chttp2\\client\\chttp2_connector.cc " +
"src\\core\\tsi\\alts_transport_security.cc " +
"src\\core\\tsi\\fake_transport_security.cc " +
"src\\core\\tsi\\ssl_transport_security.cc " +
"src\\core\\tsi\\transport_security_grpc.cc " +
"src\\core\\ext\\transport\\chttp2\\server\\chttp2_server.cc " +
"src\\core\\ext\\transport\\chttp2\\client\\secure\\secure_channel_create.cc " +
"src\\core\\ext\\transport\\chttp2\\server\\insecure\\server_chttp2.cc " +
"src\\core\\ext\\transport\\chttp2\\server\\insecure\\server_chttp2_posix.cc " +
"src\\core\\ext\\transport\\chttp2\\client\\insecure\\channel_create.cc " +
"src\\core\\ext\\transport\\chttp2\\client\\insecure\\channel_create_posix.cc " +
"src\\core\\ext\\transport\\inproc\\inproc_plugin.cc " +
"src\\core\\ext\\transport\\inproc\\inproc_transport.cc " +
"src\\core\\ext\\filters\\client_channel\\lb_policy\\grpclb\\client_load_reporting_filter.cc " +
@ -287,9 +323,6 @@ if (PHP_GRPC != "no") {
"src\\core\\ext\\filters\\client_channel\\lb_policy\\grpclb\\grpclb_client_stats.cc " +
"src\\core\\ext\\filters\\client_channel\\lb_policy\\grpclb\\load_balancer_api.cc " +
"src\\core\\ext\\filters\\client_channel\\lb_policy\\grpclb\\proto\\grpc\\lb\\v1\\load_balancer.pb.c " +
"third_party\\nanopb\\pb_common.c " +
"third_party\\nanopb\\pb_decode.c " +
"third_party\\nanopb\\pb_encode.c " +
"src\\core\\ext\\filters\\client_channel\\resolver\\fake\\fake_resolver.cc " +
"src\\core\\ext\\filters\\client_channel\\lb_policy\\pick_first\\pick_first.cc " +
"src\\core\\ext\\filters\\client_channel\\lb_policy\\subchannel_list.cc " +
@ -648,6 +681,7 @@ if (PHP_GRPC != "no") {
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\security");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\security\\context");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\security\\credentials");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\security\\credentials\\alts");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\security\\credentials\\composite");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\security\\credentials\\fake");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\security\\credentials\\google_default");
@ -664,6 +698,11 @@ if (PHP_GRPC != "no") {
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\transport");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\plugin_registry");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\tsi");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\tsi\\alts");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\tsi\\alts\\crypt");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\tsi\\alts\\frame_protector");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\tsi\\alts\\handshaker");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\tsi\\alts\\zero_copy_frame_protector");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\php");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\php\\ext");
FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\php\\ext\\grpc");

@ -260,6 +260,7 @@ Pod::Spec.new do |s|
'src/core/ext/filters/http/message_compress/message_compress_filter.h',
'src/core/ext/filters/http/server/http_server_filter.h',
'src/core/lib/security/context/security_context.h',
'src/core/lib/security/credentials/alts/alts_credentials.h',
'src/core/lib/security/credentials/composite/composite_credentials.h',
'src/core/lib/security/credentials/credentials.h',
'src/core/lib/security/credentials/fake/fake_credentials.h',
@ -271,6 +272,7 @@ Pod::Spec.new do |s|
'src/core/lib/security/credentials/oauth2/oauth2_credentials.h',
'src/core/lib/security/credentials/plugin/plugin_credentials.h',
'src/core/lib/security/credentials/ssl/ssl_credentials.h',
'src/core/lib/security/security_connector/alts_security_connector.h',
'src/core/lib/security/security_connector/security_connector.h',
'src/core/lib/security/transport/auth_filters.h',
'src/core/lib/security/transport/secure_endpoint.h',
@ -278,15 +280,35 @@ Pod::Spec.new do |s|
'src/core/lib/security/transport/target_authority_table.h',
'src/core/lib/security/transport/tsi_error.h',
'src/core/lib/security/util/json_util.h',
'src/core/tsi/alts_transport_security.h',
'src/core/tsi/fake_transport_security.h',
'src/core/tsi/ssl_transport_security.h',
'src/core/tsi/ssl_types.h',
'src/core/tsi/transport_security_grpc.h',
'src/core/tsi/alts/crypt/gsec.h',
'src/core/tsi/alts/frame_protector/alts_counter.h',
'src/core/tsi/alts/frame_protector/alts_crypter.h',
'src/core/tsi/alts/frame_protector/alts_frame_protector.h',
'src/core/tsi/alts/frame_protector/alts_record_protocol_crypter_common.h',
'src/core/tsi/alts/frame_protector/frame_handler.h',
'src/core/tsi/alts/handshaker/alts_handshaker_client.h',
'src/core/tsi/alts/handshaker/alts_tsi_event.h',
'src/core/tsi/alts/handshaker/alts_tsi_handshaker.h',
'src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h',
'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.h',
'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.h',
'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol.h',
'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.h',
'src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.h',
'src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.h',
'src/core/lib/security/credentials/alts/check_gcp_environment.h',
'src/core/lib/security/credentials/alts/grpc_alts_credentials_options.h',
'src/core/tsi/alts/handshaker/alts_handshaker_service_api.h',
'src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.h',
'src/core/tsi/alts/handshaker/alts_tsi_utils.h',
'src/core/tsi/alts/handshaker/transport_security_common_api.h',
'src/core/tsi/alts/handshaker/altscontext.pb.h',
'src/core/tsi/alts/handshaker/handshaker.pb.h',
'src/core/tsi/alts/handshaker/transport_security_common.pb.h',
'src/core/tsi/transport_security.h',
'src/core/tsi/transport_security_adapter.h',
'src/core/tsi/transport_security_interface.h',
'src/core/ext/transport/chttp2/server/chttp2_server.h',
'src/core/ext/transport/chttp2/client/chttp2_connector.h',
'src/core/ext/filters/client_channel/backup_poller.h',
'src/core/ext/filters/client_channel/client_channel.h',
'src/core/ext/filters/client_channel/client_channel_factory.h',
@ -309,7 +331,12 @@ Pod::Spec.new do |s|
'src/core/ext/filters/client_channel/subchannel_index.h',
'src/core/ext/filters/client_channel/uri_parser.h',
'src/core/ext/filters/deadline/deadline_filter.h',
'src/core/ext/transport/chttp2/client/chttp2_connector.h',
'src/core/tsi/alts_transport_security.h',
'src/core/tsi/fake_transport_security.h',
'src/core/tsi/ssl_transport_security.h',
'src/core/tsi/ssl_types.h',
'src/core/tsi/transport_security_grpc.h',
'src/core/ext/transport/chttp2/server/chttp2_server.h',
'src/core/ext/transport/inproc/inproc_transport.h',
'src/core/lib/avl/avl.h',
'src/core/lib/backoff/backoff.h',

@ -93,7 +93,7 @@ Pod::Spec.new do |s|
}
s.default_subspecs = 'Interface', 'Implementation'
s.compiler_flags = '-DGRPC_ARES=0'
s.compiler_flags = '-DGRPC_ARES=0', '-DPB_FIELD_16BIT'
s.libraries = 'c++'
# Like many other C libraries, gRPC-Core has its public headers under `include/<libname>/` and its
@ -271,6 +271,7 @@ Pod::Spec.new do |s|
'src/core/ext/filters/http/message_compress/message_compress_filter.h',
'src/core/ext/filters/http/server/http_server_filter.h',
'src/core/lib/security/context/security_context.h',
'src/core/lib/security/credentials/alts/alts_credentials.h',
'src/core/lib/security/credentials/composite/composite_credentials.h',
'src/core/lib/security/credentials/credentials.h',
'src/core/lib/security/credentials/fake/fake_credentials.h',
@ -282,6 +283,7 @@ Pod::Spec.new do |s|
'src/core/lib/security/credentials/oauth2/oauth2_credentials.h',
'src/core/lib/security/credentials/plugin/plugin_credentials.h',
'src/core/lib/security/credentials/ssl/ssl_credentials.h',
'src/core/lib/security/security_connector/alts_security_connector.h',
'src/core/lib/security/security_connector/security_connector.h',
'src/core/lib/security/transport/auth_filters.h',
'src/core/lib/security/transport/secure_endpoint.h',
@ -289,15 +291,35 @@ Pod::Spec.new do |s|
'src/core/lib/security/transport/target_authority_table.h',
'src/core/lib/security/transport/tsi_error.h',
'src/core/lib/security/util/json_util.h',
'src/core/tsi/alts_transport_security.h',
'src/core/tsi/fake_transport_security.h',
'src/core/tsi/ssl_transport_security.h',
'src/core/tsi/ssl_types.h',
'src/core/tsi/transport_security_grpc.h',
'src/core/tsi/alts/crypt/gsec.h',
'src/core/tsi/alts/frame_protector/alts_counter.h',
'src/core/tsi/alts/frame_protector/alts_crypter.h',
'src/core/tsi/alts/frame_protector/alts_frame_protector.h',
'src/core/tsi/alts/frame_protector/alts_record_protocol_crypter_common.h',
'src/core/tsi/alts/frame_protector/frame_handler.h',
'src/core/tsi/alts/handshaker/alts_handshaker_client.h',
'src/core/tsi/alts/handshaker/alts_tsi_event.h',
'src/core/tsi/alts/handshaker/alts_tsi_handshaker.h',
'src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h',
'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.h',
'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.h',
'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol.h',
'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.h',
'src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.h',
'src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.h',
'src/core/lib/security/credentials/alts/check_gcp_environment.h',
'src/core/lib/security/credentials/alts/grpc_alts_credentials_options.h',
'src/core/tsi/alts/handshaker/alts_handshaker_service_api.h',
'src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.h',
'src/core/tsi/alts/handshaker/alts_tsi_utils.h',
'src/core/tsi/alts/handshaker/transport_security_common_api.h',
'src/core/tsi/alts/handshaker/altscontext.pb.h',
'src/core/tsi/alts/handshaker/handshaker.pb.h',
'src/core/tsi/alts/handshaker/transport_security_common.pb.h',
'src/core/tsi/transport_security.h',
'src/core/tsi/transport_security_adapter.h',
'src/core/tsi/transport_security_interface.h',
'src/core/ext/transport/chttp2/server/chttp2_server.h',
'src/core/ext/transport/chttp2/client/chttp2_connector.h',
'src/core/ext/filters/client_channel/backup_poller.h',
'src/core/ext/filters/client_channel/client_channel.h',
'src/core/ext/filters/client_channel/client_channel_factory.h',
@ -320,7 +342,12 @@ Pod::Spec.new do |s|
'src/core/ext/filters/client_channel/subchannel_index.h',
'src/core/ext/filters/client_channel/uri_parser.h',
'src/core/ext/filters/deadline/deadline_filter.h',
'src/core/ext/transport/chttp2/client/chttp2_connector.h',
'src/core/tsi/alts_transport_security.h',
'src/core/tsi/fake_transport_security.h',
'src/core/tsi/ssl_transport_security.h',
'src/core/tsi/ssl_types.h',
'src/core/tsi/transport_security_grpc.h',
'src/core/ext/transport/chttp2/server/chttp2_server.h',
'src/core/ext/transport/inproc/inproc_transport.h',
'src/core/lib/avl/avl.h',
'src/core/lib/backoff/backoff.h',
@ -631,6 +658,7 @@ Pod::Spec.new do |s|
'src/core/ext/filters/http/server/http_server_filter.cc',
'src/core/lib/http/httpcli_security_connector.cc',
'src/core/lib/security/context/security_context.cc',
'src/core/lib/security/credentials/alts/alts_credentials.cc',
'src/core/lib/security/credentials/composite/composite_credentials.cc',
'src/core/lib/security/credentials/credentials.cc',
'src/core/lib/security/credentials/credentials_metadata.cc',
@ -644,6 +672,7 @@ Pod::Spec.new do |s|
'src/core/lib/security/credentials/oauth2/oauth2_credentials.cc',
'src/core/lib/security/credentials/plugin/plugin_credentials.cc',
'src/core/lib/security/credentials/ssl/ssl_credentials.cc',
'src/core/lib/security/security_connector/alts_security_connector.cc',
'src/core/lib/security/security_connector/security_connector.cc',
'src/core/lib/security/transport/client_auth_filter.cc',
'src/core/lib/security/transport/secure_endpoint.cc',
@ -653,14 +682,42 @@ Pod::Spec.new do |s|
'src/core/lib/security/transport/tsi_error.cc',
'src/core/lib/security/util/json_util.cc',
'src/core/lib/surface/init_secure.cc',
'src/core/tsi/alts_transport_security.cc',
'src/core/tsi/fake_transport_security.cc',
'src/core/tsi/ssl_transport_security.cc',
'src/core/tsi/transport_security_grpc.cc',
'src/core/tsi/alts/crypt/aes_gcm.cc',
'src/core/tsi/alts/crypt/gsec.cc',
'src/core/tsi/alts/frame_protector/alts_counter.cc',
'src/core/tsi/alts/frame_protector/alts_crypter.cc',
'src/core/tsi/alts/frame_protector/alts_frame_protector.cc',
'src/core/tsi/alts/frame_protector/alts_record_protocol_crypter_common.cc',
'src/core/tsi/alts/frame_protector/alts_seal_privacy_integrity_crypter.cc',
'src/core/tsi/alts/frame_protector/alts_unseal_privacy_integrity_crypter.cc',
'src/core/tsi/alts/frame_protector/frame_handler.cc',
'src/core/tsi/alts/handshaker/alts_handshaker_client.cc',
'src/core/tsi/alts/handshaker/alts_tsi_event.cc',
'src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc',
'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.cc',
'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.cc',
'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.cc',
'src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.cc',
'src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.cc',
'src/core/lib/security/credentials/alts/check_gcp_environment.cc',
'src/core/lib/security/credentials/alts/check_gcp_environment_linux.cc',
'src/core/lib/security/credentials/alts/check_gcp_environment_no_op.cc',
'src/core/lib/security/credentials/alts/check_gcp_environment_windows.cc',
'src/core/lib/security/credentials/alts/grpc_alts_credentials_client_options.cc',
'src/core/lib/security/credentials/alts/grpc_alts_credentials_options.cc',
'src/core/lib/security/credentials/alts/grpc_alts_credentials_server_options.cc',
'src/core/tsi/alts/handshaker/alts_handshaker_service_api.cc',
'src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.cc',
'src/core/tsi/alts/handshaker/alts_tsi_utils.cc',
'src/core/tsi/alts/handshaker/transport_security_common_api.cc',
'src/core/tsi/alts/handshaker/altscontext.pb.c',
'src/core/tsi/alts/handshaker/handshaker.pb.c',
'src/core/tsi/alts/handshaker/transport_security_common.pb.c',
'src/core/tsi/transport_security.cc',
'src/core/tsi/transport_security_adapter.cc',
'src/core/ext/transport/chttp2/server/chttp2_server.cc',
'src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc',
'src/core/ext/transport/chttp2/client/insecure/channel_create.cc',
'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc',
'src/core/ext/transport/chttp2/client/chttp2_connector.cc',
'src/core/ext/filters/client_channel/backup_poller.cc',
'src/core/ext/filters/client_channel/channel_connectivity.cc',
'src/core/ext/filters/client_channel/client_channel.cc',
@ -684,11 +741,14 @@ Pod::Spec.new do |s|
'src/core/ext/filters/client_channel/subchannel_index.cc',
'src/core/ext/filters/client_channel/uri_parser.cc',
'src/core/ext/filters/deadline/deadline_filter.cc',
'src/core/ext/transport/chttp2/client/chttp2_connector.cc',
'src/core/tsi/alts_transport_security.cc',
'src/core/tsi/fake_transport_security.cc',
'src/core/tsi/ssl_transport_security.cc',
'src/core/tsi/transport_security_grpc.cc',
'src/core/ext/transport/chttp2/server/chttp2_server.cc',
'src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc',
'src/core/ext/transport/chttp2/server/insecure/server_chttp2.cc',
'src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.cc',
'src/core/ext/transport/chttp2/client/insecure/channel_create.cc',
'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc',
'src/core/ext/transport/inproc/inproc_plugin.cc',
'src/core/ext/transport/inproc/inproc_transport.cc',
'src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc',
@ -765,6 +825,7 @@ Pod::Spec.new do |s|
'src/core/ext/filters/http/message_compress/message_compress_filter.h',
'src/core/ext/filters/http/server/http_server_filter.h',
'src/core/lib/security/context/security_context.h',
'src/core/lib/security/credentials/alts/alts_credentials.h',
'src/core/lib/security/credentials/composite/composite_credentials.h',
'src/core/lib/security/credentials/credentials.h',
'src/core/lib/security/credentials/fake/fake_credentials.h',
@ -776,6 +837,7 @@ Pod::Spec.new do |s|
'src/core/lib/security/credentials/oauth2/oauth2_credentials.h',
'src/core/lib/security/credentials/plugin/plugin_credentials.h',
'src/core/lib/security/credentials/ssl/ssl_credentials.h',
'src/core/lib/security/security_connector/alts_security_connector.h',
'src/core/lib/security/security_connector/security_connector.h',
'src/core/lib/security/transport/auth_filters.h',
'src/core/lib/security/transport/secure_endpoint.h',
@ -783,15 +845,35 @@ Pod::Spec.new do |s|
'src/core/lib/security/transport/target_authority_table.h',
'src/core/lib/security/transport/tsi_error.h',
'src/core/lib/security/util/json_util.h',
'src/core/tsi/alts_transport_security.h',
'src/core/tsi/fake_transport_security.h',
'src/core/tsi/ssl_transport_security.h',
'src/core/tsi/ssl_types.h',
'src/core/tsi/transport_security_grpc.h',
'src/core/tsi/alts/crypt/gsec.h',
'src/core/tsi/alts/frame_protector/alts_counter.h',
'src/core/tsi/alts/frame_protector/alts_crypter.h',
'src/core/tsi/alts/frame_protector/alts_frame_protector.h',
'src/core/tsi/alts/frame_protector/alts_record_protocol_crypter_common.h',
'src/core/tsi/alts/frame_protector/frame_handler.h',
'src/core/tsi/alts/handshaker/alts_handshaker_client.h',
'src/core/tsi/alts/handshaker/alts_tsi_event.h',
'src/core/tsi/alts/handshaker/alts_tsi_handshaker.h',
'src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h',
'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.h',
'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.h',
'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol.h',
'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.h',
'src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.h',
'src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.h',
'src/core/lib/security/credentials/alts/check_gcp_environment.h',
'src/core/lib/security/credentials/alts/grpc_alts_credentials_options.h',
'src/core/tsi/alts/handshaker/alts_handshaker_service_api.h',
'src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.h',
'src/core/tsi/alts/handshaker/alts_tsi_utils.h',
'src/core/tsi/alts/handshaker/transport_security_common_api.h',
'src/core/tsi/alts/handshaker/altscontext.pb.h',
'src/core/tsi/alts/handshaker/handshaker.pb.h',
'src/core/tsi/alts/handshaker/transport_security_common.pb.h',
'src/core/tsi/transport_security.h',
'src/core/tsi/transport_security_adapter.h',
'src/core/tsi/transport_security_interface.h',
'src/core/ext/transport/chttp2/server/chttp2_server.h',
'src/core/ext/transport/chttp2/client/chttp2_connector.h',
'src/core/ext/filters/client_channel/backup_poller.h',
'src/core/ext/filters/client_channel/client_channel.h',
'src/core/ext/filters/client_channel/client_channel_factory.h',
@ -814,7 +896,12 @@ Pod::Spec.new do |s|
'src/core/ext/filters/client_channel/subchannel_index.h',
'src/core/ext/filters/client_channel/uri_parser.h',
'src/core/ext/filters/deadline/deadline_filter.h',
'src/core/ext/transport/chttp2/client/chttp2_connector.h',
'src/core/tsi/alts_transport_security.h',
'src/core/tsi/fake_transport_security.h',
'src/core/tsi/ssl_transport_security.h',
'src/core/tsi/ssl_types.h',
'src/core/tsi/transport_security_grpc.h',
'src/core/ext/transport/chttp2/server/chttp2_server.h',
'src/core/ext/transport/inproc/inproc_transport.h',
'src/core/lib/avl/avl.h',
'src/core/lib/backoff/backoff.h',
@ -975,8 +1062,15 @@ Pod::Spec.new do |s|
ss.source_files = 'src/core/ext/transport/cronet/client/secure/cronet_channel_create.cc',
'src/core/ext/transport/cronet/transport/cronet_transport.cc',
'third_party/nanopb/pb_common.c',
'third_party/nanopb/pb_decode.c',
'third_party/nanopb/pb_encode.c',
'src/core/ext/transport/cronet/transport/cronet_transport.h',
'third_party/objective_c/Cronet/bidirectional_stream_c.h'
'third_party/objective_c/Cronet/bidirectional_stream_c.h',
'third_party/nanopb/pb.h',
'third_party/nanopb/pb_common.h',
'third_party/nanopb/pb_decode.h',
'third_party/nanopb/pb_encode.h'
end
s.subspec 'Tests' do |ss|

@ -197,6 +197,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/filters/http/message_compress/message_compress_filter.h )
s.files += %w( src/core/ext/filters/http/server/http_server_filter.h )
s.files += %w( src/core/lib/security/context/security_context.h )
s.files += %w( src/core/lib/security/credentials/alts/alts_credentials.h )
s.files += %w( src/core/lib/security/credentials/composite/composite_credentials.h )
s.files += %w( src/core/lib/security/credentials/credentials.h )
s.files += %w( src/core/lib/security/credentials/fake/fake_credentials.h )
@ -208,6 +209,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/security/credentials/oauth2/oauth2_credentials.h )
s.files += %w( src/core/lib/security/credentials/plugin/plugin_credentials.h )
s.files += %w( src/core/lib/security/credentials/ssl/ssl_credentials.h )
s.files += %w( src/core/lib/security/security_connector/alts_security_connector.h )
s.files += %w( src/core/lib/security/security_connector/security_connector.h )
s.files += %w( src/core/lib/security/transport/auth_filters.h )
s.files += %w( src/core/lib/security/transport/secure_endpoint.h )
@ -215,15 +217,39 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/security/transport/target_authority_table.h )
s.files += %w( src/core/lib/security/transport/tsi_error.h )
s.files += %w( src/core/lib/security/util/json_util.h )
s.files += %w( src/core/tsi/alts_transport_security.h )
s.files += %w( src/core/tsi/fake_transport_security.h )
s.files += %w( src/core/tsi/ssl_transport_security.h )
s.files += %w( src/core/tsi/ssl_types.h )
s.files += %w( src/core/tsi/transport_security_grpc.h )
s.files += %w( src/core/tsi/alts/crypt/gsec.h )
s.files += %w( src/core/tsi/alts/frame_protector/alts_counter.h )
s.files += %w( src/core/tsi/alts/frame_protector/alts_crypter.h )
s.files += %w( src/core/tsi/alts/frame_protector/alts_frame_protector.h )
s.files += %w( src/core/tsi/alts/frame_protector/alts_record_protocol_crypter_common.h )
s.files += %w( src/core/tsi/alts/frame_protector/frame_handler.h )
s.files += %w( src/core/tsi/alts/handshaker/alts_handshaker_client.h )
s.files += %w( src/core/tsi/alts/handshaker/alts_tsi_event.h )
s.files += %w( src/core/tsi/alts/handshaker/alts_tsi_handshaker.h )
s.files += %w( src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h )
s.files += %w( src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.h )
s.files += %w( src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.h )
s.files += %w( src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol.h )
s.files += %w( src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.h )
s.files += %w( src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.h )
s.files += %w( src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.h )
s.files += %w( src/core/lib/security/credentials/alts/check_gcp_environment.h )
s.files += %w( src/core/lib/security/credentials/alts/grpc_alts_credentials_options.h )
s.files += %w( src/core/tsi/alts/handshaker/alts_handshaker_service_api.h )
s.files += %w( src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.h )
s.files += %w( src/core/tsi/alts/handshaker/alts_tsi_utils.h )
s.files += %w( src/core/tsi/alts/handshaker/transport_security_common_api.h )
s.files += %w( src/core/tsi/alts/handshaker/altscontext.pb.h )
s.files += %w( src/core/tsi/alts/handshaker/handshaker.pb.h )
s.files += %w( src/core/tsi/alts/handshaker/transport_security_common.pb.h )
s.files += %w( third_party/nanopb/pb.h )
s.files += %w( third_party/nanopb/pb_common.h )
s.files += %w( third_party/nanopb/pb_decode.h )
s.files += %w( third_party/nanopb/pb_encode.h )
s.files += %w( src/core/tsi/transport_security.h )
s.files += %w( src/core/tsi/transport_security_adapter.h )
s.files += %w( src/core/tsi/transport_security_interface.h )
s.files += %w( src/core/ext/transport/chttp2/server/chttp2_server.h )
s.files += %w( src/core/ext/transport/chttp2/client/chttp2_connector.h )
s.files += %w( src/core/ext/filters/client_channel/backup_poller.h )
s.files += %w( src/core/ext/filters/client_channel/client_channel.h )
s.files += %w( src/core/ext/filters/client_channel/client_channel_factory.h )
@ -246,7 +272,12 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/filters/client_channel/subchannel_index.h )
s.files += %w( src/core/ext/filters/client_channel/uri_parser.h )
s.files += %w( src/core/ext/filters/deadline/deadline_filter.h )
s.files += %w( src/core/ext/transport/chttp2/client/chttp2_connector.h )
s.files += %w( src/core/tsi/alts_transport_security.h )
s.files += %w( src/core/tsi/fake_transport_security.h )
s.files += %w( src/core/tsi/ssl_transport_security.h )
s.files += %w( src/core/tsi/ssl_types.h )
s.files += %w( src/core/tsi/transport_security_grpc.h )
s.files += %w( src/core/ext/transport/chttp2/server/chttp2_server.h )
s.files += %w( src/core/ext/transport/inproc/inproc_transport.h )
s.files += %w( src/core/lib/avl/avl.h )
s.files += %w( src/core/lib/backoff/backoff.h )
@ -381,10 +412,6 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h )
s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h )
s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h )
s.files += %w( third_party/nanopb/pb.h )
s.files += %w( third_party/nanopb/pb_common.h )
s.files += %w( third_party/nanopb/pb_decode.h )
s.files += %w( third_party/nanopb/pb_encode.h )
s.files += %w( src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h )
s.files += %w( src/core/ext/filters/client_channel/lb_policy/subchannel_list.h )
s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h )
@ -561,6 +588,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/filters/http/server/http_server_filter.cc )
s.files += %w( src/core/lib/http/httpcli_security_connector.cc )
s.files += %w( src/core/lib/security/context/security_context.cc )
s.files += %w( src/core/lib/security/credentials/alts/alts_credentials.cc )
s.files += %w( src/core/lib/security/credentials/composite/composite_credentials.cc )
s.files += %w( src/core/lib/security/credentials/credentials.cc )
s.files += %w( src/core/lib/security/credentials/credentials_metadata.cc )
@ -574,6 +602,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/security/credentials/oauth2/oauth2_credentials.cc )
s.files += %w( src/core/lib/security/credentials/plugin/plugin_credentials.cc )
s.files += %w( src/core/lib/security/credentials/ssl/ssl_credentials.cc )
s.files += %w( src/core/lib/security/security_connector/alts_security_connector.cc )
s.files += %w( src/core/lib/security/security_connector/security_connector.cc )
s.files += %w( src/core/lib/security/transport/client_auth_filter.cc )
s.files += %w( src/core/lib/security/transport/secure_endpoint.cc )
@ -583,14 +612,45 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/security/transport/tsi_error.cc )
s.files += %w( src/core/lib/security/util/json_util.cc )
s.files += %w( src/core/lib/surface/init_secure.cc )
s.files += %w( src/core/tsi/alts_transport_security.cc )
s.files += %w( src/core/tsi/fake_transport_security.cc )
s.files += %w( src/core/tsi/ssl_transport_security.cc )
s.files += %w( src/core/tsi/transport_security_grpc.cc )
s.files += %w( src/core/tsi/alts/crypt/aes_gcm.cc )
s.files += %w( src/core/tsi/alts/crypt/gsec.cc )
s.files += %w( src/core/tsi/alts/frame_protector/alts_counter.cc )
s.files += %w( src/core/tsi/alts/frame_protector/alts_crypter.cc )
s.files += %w( src/core/tsi/alts/frame_protector/alts_frame_protector.cc )
s.files += %w( src/core/tsi/alts/frame_protector/alts_record_protocol_crypter_common.cc )
s.files += %w( src/core/tsi/alts/frame_protector/alts_seal_privacy_integrity_crypter.cc )
s.files += %w( src/core/tsi/alts/frame_protector/alts_unseal_privacy_integrity_crypter.cc )
s.files += %w( src/core/tsi/alts/frame_protector/frame_handler.cc )
s.files += %w( src/core/tsi/alts/handshaker/alts_handshaker_client.cc )
s.files += %w( src/core/tsi/alts/handshaker/alts_tsi_event.cc )
s.files += %w( src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc )
s.files += %w( src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.cc )
s.files += %w( src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.cc )
s.files += %w( src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.cc )
s.files += %w( src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.cc )
s.files += %w( src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.cc )
s.files += %w( src/core/lib/security/credentials/alts/check_gcp_environment.cc )
s.files += %w( src/core/lib/security/credentials/alts/check_gcp_environment_linux.cc )
s.files += %w( src/core/lib/security/credentials/alts/check_gcp_environment_no_op.cc )
s.files += %w( src/core/lib/security/credentials/alts/check_gcp_environment_windows.cc )
s.files += %w( src/core/lib/security/credentials/alts/grpc_alts_credentials_client_options.cc )
s.files += %w( src/core/lib/security/credentials/alts/grpc_alts_credentials_options.cc )
s.files += %w( src/core/lib/security/credentials/alts/grpc_alts_credentials_server_options.cc )
s.files += %w( src/core/tsi/alts/handshaker/alts_handshaker_service_api.cc )
s.files += %w( src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.cc )
s.files += %w( src/core/tsi/alts/handshaker/alts_tsi_utils.cc )
s.files += %w( src/core/tsi/alts/handshaker/transport_security_common_api.cc )
s.files += %w( src/core/tsi/alts/handshaker/altscontext.pb.c )
s.files += %w( src/core/tsi/alts/handshaker/handshaker.pb.c )
s.files += %w( src/core/tsi/alts/handshaker/transport_security_common.pb.c )
s.files += %w( third_party/nanopb/pb_common.c )
s.files += %w( third_party/nanopb/pb_decode.c )
s.files += %w( third_party/nanopb/pb_encode.c )
s.files += %w( src/core/tsi/transport_security.cc )
s.files += %w( src/core/tsi/transport_security_adapter.cc )
s.files += %w( src/core/ext/transport/chttp2/server/chttp2_server.cc )
s.files += %w( src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc )
s.files += %w( src/core/ext/transport/chttp2/client/insecure/channel_create.cc )
s.files += %w( src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc )
s.files += %w( src/core/ext/transport/chttp2/client/chttp2_connector.cc )
s.files += %w( src/core/ext/filters/client_channel/backup_poller.cc )
s.files += %w( src/core/ext/filters/client_channel/channel_connectivity.cc )
s.files += %w( src/core/ext/filters/client_channel/client_channel.cc )
@ -614,11 +674,14 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/filters/client_channel/subchannel_index.cc )
s.files += %w( src/core/ext/filters/client_channel/uri_parser.cc )
s.files += %w( src/core/ext/filters/deadline/deadline_filter.cc )
s.files += %w( src/core/ext/transport/chttp2/client/chttp2_connector.cc )
s.files += %w( src/core/tsi/alts_transport_security.cc )
s.files += %w( src/core/tsi/fake_transport_security.cc )
s.files += %w( src/core/tsi/ssl_transport_security.cc )
s.files += %w( src/core/tsi/transport_security_grpc.cc )
s.files += %w( src/core/ext/transport/chttp2/server/chttp2_server.cc )
s.files += %w( src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc )
s.files += %w( src/core/ext/transport/chttp2/server/insecure/server_chttp2.cc )
s.files += %w( src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.cc )
s.files += %w( src/core/ext/transport/chttp2/client/insecure/channel_create.cc )
s.files += %w( src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc )
s.files += %w( src/core/ext/transport/inproc/inproc_plugin.cc )
s.files += %w( src/core/ext/transport/inproc/inproc_transport.cc )
s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc )
@ -627,9 +690,6 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc )
s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc )
s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c )
s.files += %w( third_party/nanopb/pb_common.c )
s.files += %w( third_party/nanopb/pb_decode.c )
s.files += %w( third_party/nanopb/pb_encode.c )
s.files += %w( src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc )
s.files += %w( src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc )
s.files += %w( src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc )

@ -64,11 +64,11 @@
],
'cflags_c': [
'-Werror',
'-std=c99'
'-std=c99',
],
'cflags_cc': [
'-Werror',
'-std=c++11'
'-std=c++11',
],
'include_dirs': [
'.',
@ -148,13 +148,24 @@
'-Wno-deprecated-declarations',
'-stdlib=libc++',
'-std=c++11',
'-Wno-error=deprecated-declarations'
'-Wno-error=deprecated-declarations',
],
},
}]
]
},
'targets': [
{
'target_name': 'alts_test_util',
'type': 'static_library',
'dependencies': [
'grpc',
],
'sources': [
'test/core/tsi/alts/crypt/gsec_test_util.cc',
'test/core/tsi/alts/handshaker/alts_handshaker_service_api_test_lib.cc',
],
},
{
'target_name': 'gpr',
'type': 'static_library',
@ -385,6 +396,7 @@
'src/core/ext/filters/http/server/http_server_filter.cc',
'src/core/lib/http/httpcli_security_connector.cc',
'src/core/lib/security/context/security_context.cc',
'src/core/lib/security/credentials/alts/alts_credentials.cc',
'src/core/lib/security/credentials/composite/composite_credentials.cc',
'src/core/lib/security/credentials/credentials.cc',
'src/core/lib/security/credentials/credentials_metadata.cc',
@ -398,6 +410,7 @@
'src/core/lib/security/credentials/oauth2/oauth2_credentials.cc',
'src/core/lib/security/credentials/plugin/plugin_credentials.cc',
'src/core/lib/security/credentials/ssl/ssl_credentials.cc',
'src/core/lib/security/security_connector/alts_security_connector.cc',
'src/core/lib/security/security_connector/security_connector.cc',
'src/core/lib/security/transport/client_auth_filter.cc',
'src/core/lib/security/transport/secure_endpoint.cc',
@ -407,14 +420,45 @@
'src/core/lib/security/transport/tsi_error.cc',
'src/core/lib/security/util/json_util.cc',
'src/core/lib/surface/init_secure.cc',
'src/core/tsi/alts_transport_security.cc',
'src/core/tsi/fake_transport_security.cc',
'src/core/tsi/ssl_transport_security.cc',
'src/core/tsi/transport_security_grpc.cc',
'src/core/tsi/alts/crypt/aes_gcm.cc',
'src/core/tsi/alts/crypt/gsec.cc',
'src/core/tsi/alts/frame_protector/alts_counter.cc',
'src/core/tsi/alts/frame_protector/alts_crypter.cc',
'src/core/tsi/alts/frame_protector/alts_frame_protector.cc',
'src/core/tsi/alts/frame_protector/alts_record_protocol_crypter_common.cc',
'src/core/tsi/alts/frame_protector/alts_seal_privacy_integrity_crypter.cc',
'src/core/tsi/alts/frame_protector/alts_unseal_privacy_integrity_crypter.cc',
'src/core/tsi/alts/frame_protector/frame_handler.cc',
'src/core/tsi/alts/handshaker/alts_handshaker_client.cc',
'src/core/tsi/alts/handshaker/alts_tsi_event.cc',
'src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc',
'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.cc',
'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.cc',
'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.cc',
'src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.cc',
'src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.cc',
'src/core/lib/security/credentials/alts/check_gcp_environment.cc',
'src/core/lib/security/credentials/alts/check_gcp_environment_linux.cc',
'src/core/lib/security/credentials/alts/check_gcp_environment_no_op.cc',
'src/core/lib/security/credentials/alts/check_gcp_environment_windows.cc',
'src/core/lib/security/credentials/alts/grpc_alts_credentials_client_options.cc',
'src/core/lib/security/credentials/alts/grpc_alts_credentials_options.cc',
'src/core/lib/security/credentials/alts/grpc_alts_credentials_server_options.cc',
'src/core/tsi/alts/handshaker/alts_handshaker_service_api.cc',
'src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.cc',
'src/core/tsi/alts/handshaker/alts_tsi_utils.cc',
'src/core/tsi/alts/handshaker/transport_security_common_api.cc',
'src/core/tsi/alts/handshaker/altscontext.pb.c',
'src/core/tsi/alts/handshaker/handshaker.pb.c',
'src/core/tsi/alts/handshaker/transport_security_common.pb.c',
'third_party/nanopb/pb_common.c',
'third_party/nanopb/pb_decode.c',
'third_party/nanopb/pb_encode.c',
'src/core/tsi/transport_security.cc',
'src/core/tsi/transport_security_adapter.cc',
'src/core/ext/transport/chttp2/server/chttp2_server.cc',
'src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc',
'src/core/ext/transport/chttp2/client/insecure/channel_create.cc',
'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc',
'src/core/ext/transport/chttp2/client/chttp2_connector.cc',
'src/core/ext/filters/client_channel/backup_poller.cc',
'src/core/ext/filters/client_channel/channel_connectivity.cc',
'src/core/ext/filters/client_channel/client_channel.cc',
@ -438,11 +482,14 @@
'src/core/ext/filters/client_channel/subchannel_index.cc',
'src/core/ext/filters/client_channel/uri_parser.cc',
'src/core/ext/filters/deadline/deadline_filter.cc',
'src/core/ext/transport/chttp2/client/chttp2_connector.cc',
'src/core/tsi/alts_transport_security.cc',
'src/core/tsi/fake_transport_security.cc',
'src/core/tsi/ssl_transport_security.cc',
'src/core/tsi/transport_security_grpc.cc',
'src/core/ext/transport/chttp2/server/chttp2_server.cc',
'src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc',
'src/core/ext/transport/chttp2/server/insecure/server_chttp2.cc',
'src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.cc',
'src/core/ext/transport/chttp2/client/insecure/channel_create.cc',
'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc',
'src/core/ext/transport/inproc/inproc_plugin.cc',
'src/core/ext/transport/inproc/inproc_transport.cc',
'src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc',
@ -451,9 +498,6 @@
'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc',
'src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc',
'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c',
'third_party/nanopb/pb_common.c',
'third_party/nanopb/pb_decode.c',
'third_party/nanopb/pb_encode.c',
'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc',
'src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc',
'src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc',

@ -204,6 +204,7 @@
<file baseinstalldir="/" name="src/core/ext/filters/http/message_compress/message_compress_filter.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/http/server/http_server_filter.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/context/security_context.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/alts/alts_credentials.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/composite/composite_credentials.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/credentials.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/fake/fake_credentials.h" role="src" />
@ -215,6 +216,7 @@
<file baseinstalldir="/" name="src/core/lib/security/credentials/oauth2/oauth2_credentials.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/plugin/plugin_credentials.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/ssl/ssl_credentials.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/security_connector/alts_security_connector.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/security_connector/security_connector.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/transport/auth_filters.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/transport/secure_endpoint.h" role="src" />
@ -222,15 +224,39 @@
<file baseinstalldir="/" name="src/core/lib/security/transport/target_authority_table.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/transport/tsi_error.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/util/json_util.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts_transport_security.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/fake_transport_security.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/ssl_transport_security.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/ssl_types.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/transport_security_grpc.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/crypt/gsec.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/frame_protector/alts_counter.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/frame_protector/alts_crypter.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/frame_protector/alts_frame_protector.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/frame_protector/alts_record_protocol_crypter_common.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/frame_protector/frame_handler.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/handshaker/alts_handshaker_client.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/handshaker/alts_tsi_event.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/handshaker/alts_tsi_handshaker.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/alts/check_gcp_environment.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/alts/grpc_alts_credentials_options.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/handshaker/alts_handshaker_service_api.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/handshaker/alts_tsi_utils.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/handshaker/transport_security_common_api.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/handshaker/altscontext.pb.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/handshaker/handshaker.pb.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/handshaker/transport_security_common.pb.h" role="src" />
<file baseinstalldir="/" name="third_party/nanopb/pb.h" role="src" />
<file baseinstalldir="/" name="third_party/nanopb/pb_common.h" role="src" />
<file baseinstalldir="/" name="third_party/nanopb/pb_decode.h" role="src" />
<file baseinstalldir="/" name="third_party/nanopb/pb_encode.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/transport_security.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/transport_security_adapter.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/transport_security_interface.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/server/chttp2_server.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/chttp2_connector.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/backup_poller.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/client_channel.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/client_channel_factory.h" role="src" />
@ -253,7 +279,12 @@
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/subchannel_index.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/uri_parser.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/deadline/deadline_filter.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/chttp2_connector.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts_transport_security.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/fake_transport_security.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/ssl_transport_security.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/ssl_types.h" role="src" />
<file baseinstalldir="/" name="src/core/tsi/transport_security_grpc.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/server/chttp2_server.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/inproc/inproc_transport.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/avl/avl.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/backoff/backoff.h" role="src" />
@ -388,10 +419,6 @@
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h" role="src" />
<file baseinstalldir="/" name="third_party/nanopb/pb.h" role="src" />
<file baseinstalldir="/" name="third_party/nanopb/pb_common.h" role="src" />
<file baseinstalldir="/" name="third_party/nanopb/pb_decode.h" role="src" />
<file baseinstalldir="/" name="third_party/nanopb/pb_encode.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/subchannel_list.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h" role="src" />
@ -568,6 +595,7 @@
<file baseinstalldir="/" name="src/core/ext/filters/http/server/http_server_filter.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/http/httpcli_security_connector.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/context/security_context.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/alts/alts_credentials.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/composite/composite_credentials.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/credentials.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/credentials_metadata.cc" role="src" />
@ -581,6 +609,7 @@
<file baseinstalldir="/" name="src/core/lib/security/credentials/oauth2/oauth2_credentials.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/plugin/plugin_credentials.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/ssl/ssl_credentials.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/security_connector/alts_security_connector.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/security_connector/security_connector.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/transport/client_auth_filter.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/transport/secure_endpoint.cc" role="src" />
@ -590,14 +619,45 @@
<file baseinstalldir="/" name="src/core/lib/security/transport/tsi_error.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/util/json_util.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/surface/init_secure.cc" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts_transport_security.cc" role="src" />
<file baseinstalldir="/" name="src/core/tsi/fake_transport_security.cc" role="src" />
<file baseinstalldir="/" name="src/core/tsi/ssl_transport_security.cc" role="src" />
<file baseinstalldir="/" name="src/core/tsi/transport_security_grpc.cc" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/crypt/aes_gcm.cc" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/crypt/gsec.cc" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/frame_protector/alts_counter.cc" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/frame_protector/alts_crypter.cc" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/frame_protector/alts_frame_protector.cc" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/frame_protector/alts_record_protocol_crypter_common.cc" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/frame_protector/alts_seal_privacy_integrity_crypter.cc" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/frame_protector/alts_unseal_privacy_integrity_crypter.cc" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/frame_protector/frame_handler.cc" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/handshaker/alts_handshaker_client.cc" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/handshaker/alts_tsi_event.cc" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.cc" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.cc" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.cc" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.cc" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/alts/check_gcp_environment.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/alts/check_gcp_environment_linux.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/alts/check_gcp_environment_no_op.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/alts/check_gcp_environment_windows.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/alts/grpc_alts_credentials_client_options.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/alts/grpc_alts_credentials_options.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/credentials/alts/grpc_alts_credentials_server_options.cc" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/handshaker/alts_handshaker_service_api.cc" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.cc" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/handshaker/alts_tsi_utils.cc" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/handshaker/transport_security_common_api.cc" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/handshaker/altscontext.pb.c" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/handshaker/handshaker.pb.c" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts/handshaker/transport_security_common.pb.c" role="src" />
<file baseinstalldir="/" name="third_party/nanopb/pb_common.c" role="src" />
<file baseinstalldir="/" name="third_party/nanopb/pb_decode.c" role="src" />
<file baseinstalldir="/" name="third_party/nanopb/pb_encode.c" role="src" />
<file baseinstalldir="/" name="src/core/tsi/transport_security.cc" role="src" />
<file baseinstalldir="/" name="src/core/tsi/transport_security_adapter.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/server/chttp2_server.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/insecure/channel_create.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/chttp2_connector.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/backup_poller.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/channel_connectivity.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/client_channel.cc" role="src" />
@ -621,11 +681,14 @@
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/subchannel_index.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/uri_parser.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/deadline/deadline_filter.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/chttp2_connector.cc" role="src" />
<file baseinstalldir="/" name="src/core/tsi/alts_transport_security.cc" role="src" />
<file baseinstalldir="/" name="src/core/tsi/fake_transport_security.cc" role="src" />
<file baseinstalldir="/" name="src/core/tsi/ssl_transport_security.cc" role="src" />
<file baseinstalldir="/" name="src/core/tsi/transport_security_grpc.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/server/chttp2_server.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/server/insecure/server_chttp2.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/insecure/channel_create.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/inproc/inproc_plugin.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/inproc/inproc_transport.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc" role="src" />
@ -634,9 +697,6 @@
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c" role="src" />
<file baseinstalldir="/" name="third_party/nanopb/pb_common.c" role="src" />
<file baseinstalldir="/" name="third_party/nanopb/pb_decode.c" role="src" />
<file baseinstalldir="/" name="third_party/nanopb/pb_encode.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc" role="src" />

@ -118,6 +118,7 @@ if EXTRA_ENV_COMPILE_ARGS is None:
EXTRA_ENV_COMPILE_ARGS += ' -std=c++11 -std=gnu99 -fvisibility=hidden -fno-wrapv -fno-exceptions'
elif "darwin" in sys.platform:
EXTRA_ENV_COMPILE_ARGS += ' -fvisibility=hidden -fno-wrapv -fno-exceptions'
EXTRA_ENV_COMPILE_ARGS += ' -DPB_FIELD_16BIT'
if EXTRA_ENV_LINK_ARGS is None:
EXTRA_ENV_LINK_ARGS = ''
@ -160,7 +161,7 @@ if "win32" in sys.platform:
DEFINE_MACROS = (
('OPENSSL_NO_ASM', 1), ('_WIN32_WINNT', 0x600),
('GPR_BACKWARDS_COMPATIBILITY_MODE', 1),)
('GPR_BACKWARDS_COMPATIBILITY_MODE', 1))
if "win32" in sys.platform:
# TODO(zyc): Re-enble c-ares on x64 and x86 windows after fixing the
# ares_library_init compilation issue

@ -0,0 +1,119 @@
/*
*
* Copyright 2018 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 <grpc/support/port_platform.h>
#include "src/core/lib/security/credentials/alts/alts_credentials.h"
#include <cstring>
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include "src/core/lib/security/credentials/alts/check_gcp_environment.h"
#include "src/core/lib/security/security_connector/alts_security_connector.h"
#define GRPC_CREDENTIALS_TYPE_ALTS "Alts"
#define GRPC_ALTS_HANDSHAKER_SERVICE_URL "metadata.google.internal:8080"
static void alts_credentials_destruct(grpc_channel_credentials* creds) {
grpc_alts_credentials* alts_creds =
reinterpret_cast<grpc_alts_credentials*>(creds);
grpc_alts_credentials_options_destroy(alts_creds->options);
gpr_free(alts_creds->handshaker_service_url);
}
static void alts_server_credentials_destruct(grpc_server_credentials* creds) {
grpc_alts_server_credentials* alts_creds =
reinterpret_cast<grpc_alts_server_credentials*>(creds);
grpc_alts_credentials_options_destroy(alts_creds->options);
gpr_free(alts_creds->handshaker_service_url);
}
static grpc_security_status alts_create_security_connector(
grpc_channel_credentials* creds,
grpc_call_credentials* request_metadata_creds, const char* target_name,
const grpc_channel_args* args, grpc_channel_security_connector** sc,
grpc_channel_args** new_args) {
return grpc_alts_channel_security_connector_create(
creds, request_metadata_creds, target_name, sc);
}
static grpc_security_status alts_server_create_security_connector(
grpc_server_credentials* creds, grpc_server_security_connector** sc) {
return grpc_alts_server_security_connector_create(creds, sc);
}
static const grpc_channel_credentials_vtable alts_credentials_vtable = {
alts_credentials_destruct, alts_create_security_connector,
/*duplicate_without_call_credentials=*/nullptr};
static const grpc_server_credentials_vtable alts_server_credentials_vtable = {
alts_server_credentials_destruct, alts_server_create_security_connector};
grpc_channel_credentials* grpc_alts_credentials_create_customized(
const grpc_alts_credentials_options* options,
const char* handshaker_service_url, bool enable_untrusted_alts) {
if (!enable_untrusted_alts && !grpc_alts_is_running_on_gcp()) {
return nullptr;
}
auto creds = static_cast<grpc_alts_credentials*>(
gpr_zalloc(sizeof(grpc_alts_credentials)));
creds->options = grpc_alts_credentials_options_copy(options);
creds->handshaker_service_url =
handshaker_service_url == nullptr
? gpr_strdup(GRPC_ALTS_HANDSHAKER_SERVICE_URL)
: gpr_strdup(handshaker_service_url);
creds->base.type = GRPC_CREDENTIALS_TYPE_ALTS;
creds->base.vtable = &alts_credentials_vtable;
gpr_ref_init(&creds->base.refcount, 1);
return &creds->base;
}
grpc_server_credentials* grpc_alts_server_credentials_create_customized(
const grpc_alts_credentials_options* options,
const char* handshaker_service_url, bool enable_untrusted_alts) {
if (!enable_untrusted_alts && !grpc_alts_is_running_on_gcp()) {
return nullptr;
}
auto creds = static_cast<grpc_alts_server_credentials*>(
gpr_zalloc(sizeof(grpc_alts_server_credentials)));
creds->options = grpc_alts_credentials_options_copy(options);
creds->handshaker_service_url =
handshaker_service_url == nullptr
? gpr_strdup(GRPC_ALTS_HANDSHAKER_SERVICE_URL)
: gpr_strdup(handshaker_service_url);
creds->base.type = GRPC_CREDENTIALS_TYPE_ALTS;
creds->base.vtable = &alts_server_credentials_vtable;
gpr_ref_init(&creds->base.refcount, 1);
return &creds->base;
}
grpc_channel_credentials* grpc_alts_credentials_create(
const grpc_alts_credentials_options* options) {
return grpc_alts_credentials_create_customized(
options, GRPC_ALTS_HANDSHAKER_SERVICE_URL, false);
}
grpc_server_credentials* grpc_alts_server_credentials_create(
const grpc_alts_credentials_options* options) {
return grpc_alts_server_credentials_create_customized(
options, GRPC_ALTS_HANDSHAKER_SERVICE_URL, false);
}

@ -0,0 +1,102 @@
/*
*
* Copyright 2018 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_CORE_LIB_SECURITY_CREDENTIALS_ALTS_ALTS_CREDENTIALS_H
#define GRPC_CORE_LIB_SECURITY_CREDENTIALS_ALTS_ALTS_CREDENTIALS_H
#include <grpc/support/port_platform.h>
#include <grpc/grpc_security.h>
#include "src/core/lib/security/credentials/alts/grpc_alts_credentials_options.h"
#include "src/core/lib/security/credentials/credentials.h"
/* Main struct for grpc ALTS channel credential. */
typedef struct grpc_alts_credentials {
grpc_channel_credentials base;
grpc_alts_credentials_options* options;
char* handshaker_service_url;
} grpc_alts_credentials;
/* Main struct for grpc ALTS server credential. */
typedef struct grpc_alts_server_credentials {
grpc_server_credentials base;
grpc_alts_credentials_options* options;
char* handshaker_service_url;
} grpc_alts_server_credentials;
/**
* This method creates an ALTS channel credential object.
*
* - options: grpc ALTS credentials options instance for client.
*
* It returns the created ALTS channel credential object.
*/
grpc_channel_credentials* grpc_alts_credentials_create(
const grpc_alts_credentials_options* options);
/**
* This method creates an ALTS server credential object.
*
* - options: grpc ALTS credentials options instance for server.
*
* It returns the created ALTS server credential object.
*/
grpc_server_credentials* grpc_alts_server_credentials_create(
const grpc_alts_credentials_options* options);
/**
* This method creates an ALTS channel credential object with customized
* information provided by caller.
*
* - options: grpc ALTS credentials options instance for client.
* - handshaker_service_url: address of ALTS handshaker service in the format of
* "host:port". If it's nullptr, the address of default metadata server will
* be used.
* - enable_untrusted_alts: a boolean flag used to enable ALTS in untrusted
* mode. This mode can be enabled when we are sure ALTS is running on GCP or
* for testing purpose.
*
* It returns nullptr if the flag is disabled AND ALTS is not running on GCP.
* Otherwise, it returns the created credential object.
*/
grpc_channel_credentials* grpc_alts_credentials_create_customized(
const grpc_alts_credentials_options* options,
const char* handshaker_service_url, bool enable_untrusted_alts);
/**
* This method creates an ALTS server credential object with customized
* information provided by caller.
*
* - options: grpc ALTS credentials options instance for server.
* - handshaker_service_url: address of ALTS handshaker service in the format of
* "host:port". If it's nullptr, the address of default metadata server will
* be used.
* - enable_untrusted_alts: a boolean flag used to enable ALTS in untrusted
* mode. This mode can be enabled when we are sure ALTS is running on GCP or
* for testing purpose.
*
* It returns nullptr if the flag is disabled and ALTS is not running on GCP.
* Otherwise, it returns the created credential object.
*/
grpc_server_credentials* grpc_alts_server_credentials_create_customized(
const grpc_alts_credentials_options* options,
const char* handshaker_service_url, bool enable_untrusted_alts);
#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_ALTS_ALTS_CREDENTIALS_H */

@ -0,0 +1,72 @@
/*
*
* Copyright 2018 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 <grpc/support/port_platform.h>
#include "src/core/lib/security/credentials/alts/check_gcp_environment.h"
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
const size_t kBiosDataBufferSize = 256;
static char* trim(const char* src) {
if (src == nullptr) {
return nullptr;
}
char* des = nullptr;
size_t start = 0, end = strlen(src) - 1;
/* find the last character that is not a whitespace. */
while (end != 0 && isspace(src[end])) {
end--;
}
/* find the first character that is not a whitespace. */
while (start < strlen(src) && isspace(src[start])) {
start++;
}
if (start <= end) {
des = static_cast<char*>(
gpr_zalloc(sizeof(char) * (end - start + 2 /* '\0' */)));
memcpy(des, src + start, end - start + 1);
}
return des;
}
namespace grpc_core {
namespace internal {
char* read_bios_file(const char* bios_file) {
FILE* fp = fopen(bios_file, "r");
if (!fp) {
gpr_log(GPR_ERROR, "BIOS data file cannot be opened.");
return nullptr;
}
char buf[kBiosDataBufferSize + 1];
size_t ret = fread(buf, sizeof(char), kBiosDataBufferSize, fp);
buf[ret] = '\0';
char* trimmed_buf = trim(buf);
fclose(fp);
return trimmed_buf;
}
} // namespace internal
} // namespace grpc_core

@ -0,0 +1,57 @@
/*
*
* Copyright 2018 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_CORE_LIB_SECURITY_CREDENTIALS_ALTS_CHECK_GCP_ENVIRONMENT_H
#define GRPC_CORE_LIB_SECURITY_CREDENTIALS_ALTS_CHECK_GCP_ENVIRONMENT_H
namespace grpc_core {
namespace internal {
/**
* This method is a helper function that reads a file containing system bios
* data. Exposed for testing only.
*
* - bios_file: a file containing BIOS data used to determine GCE tenancy
* information.
*
* It returns a buffer containing the data read from the file.
*/
char* read_bios_file(const char* bios_file);
/**
* This method checks if system BIOS data contains Google-specific phrases.
* Exposed for testing only.
*
* - bios_data: a buffer containing system BIOS data.
*
* It returns true if the BIOS data contains Google-specific phrases, and false
* otherwise.
*/
bool check_bios_data(const char* bios_data);
} // namespace internal
} // namespace grpc_core
/**
* This method checks if a VM (Windows or Linux) is running within Google
* compute Engine (GCE) or not. It returns true if the VM is running in GCE and
* false otherwise.
*/
bool grpc_alts_is_running_on_gcp();
#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_ALTS_CHECK_GCP_ENVIRONMENT_H */

@ -0,0 +1,67 @@
/*
*
* Copyright 2018 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 <grpc/support/port_platform.h>
#ifdef GPR_LINUX
#include "src/core/lib/security/credentials/alts/check_gcp_environment.h"
#include <grpc/support/alloc.h>
#include <grpc/support/sync.h>
#include <string.h>
#define GRPC_ALTS_EXPECT_NAME_GOOGLE "Google"
#define GRPC_ALTS_EXPECT_NAME_GCE "Google Compute Engine"
#define GRPC_ALTS_PRODUCT_NAME_FILE "/sys/class/dmi/id/product_name"
static bool g_compute_engine_detection_done = false;
static bool g_is_on_compute_engine = false;
static gpr_mu g_mu;
static gpr_once g_once = GPR_ONCE_INIT;
namespace grpc_core {
namespace internal {
bool check_bios_data(const char* bios_data_file) {
char* bios_data = read_bios_file(bios_data_file);
bool result = (!strcmp(bios_data, GRPC_ALTS_EXPECT_NAME_GOOGLE)) ||
(!strcmp(bios_data, GRPC_ALTS_EXPECT_NAME_GCE));
gpr_free(bios_data);
return result;
}
} // namespace internal
} // namespace grpc_core
static void init_mu(void) { gpr_mu_init(&g_mu); }
bool grpc_alts_is_running_on_gcp() {
gpr_once_init(&g_once, init_mu);
gpr_mu_lock(&g_mu);
if (!g_compute_engine_detection_done) {
g_is_on_compute_engine =
grpc_core::internal::check_bios_data(GRPC_ALTS_PRODUCT_NAME_FILE);
g_compute_engine_detection_done = true;
}
gpr_mu_unlock(&g_mu);
return g_is_on_compute_engine;
}
#endif // GPR_LINUX

@ -0,0 +1,33 @@
/*
*
* Copyright 2018 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 <grpc/support/port_platform.h>
#if !defined(GPR_LINUX) && !defined(GPR_WINDOWS)
#include "src/core/lib/security/credentials/alts/check_gcp_environment.h"
#include <grpc/support/log.h>
bool grpc_alts_is_running_on_gcp() {
gpr_log(GPR_ERROR,
"Platforms other than Linux and Windows are not supported");
return false;
}
#endif // !defined(LINUX) && !defined(GPR_WINDOWS)

@ -0,0 +1,114 @@
/*
*
* Copyright 2018 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 <grpc/support/port_platform.h>
#ifdef GPR_WINDOWS
#include "src/core/lib/security/credentials/alts/check_gcp_environment.h"
#include <shellapi.h>
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/sync.h>
#define GRPC_ALTS_EXPECT_NAME_GOOGLE "Google"
#define GRPC_ALTS_WINDOWS_CHECK_COMMAND "powershell.exe"
#define GRPC_ALTS_WINDOWS_CHECK_COMMAND_ARGS \
"(Get-WmiObject -Class Win32_BIOS).Manufacturer"
#define GRPC_ALTS_WINDOWS_CHECK_BIOS_FILE "windows_bios.data"
const size_t kBiosDataBufferSize = 256;
static bool g_compute_engine_detection_done = false;
static bool g_is_on_compute_engine = false;
static gpr_mu g_mu;
static gpr_once g_once = GPR_ONCE_INIT;
namespace grpc_core {
namespace internal {
bool check_bios_data(const char* bios_data_file) {
char* bios_data = read_bios_file(bios_data_file);
bool result = !strcmp(bios_data, GRPC_ALTS_EXPECT_NAME_GOOGLE);
remove(GRPC_ALTS_WINDOWS_CHECK_BIOS_FILE);
gpr_free(bios_data);
return result;
}
} // namespace internal
} // namespace grpc_core
static void init_mu(void) { gpr_mu_init(&g_mu); }
static bool run_powershell() {
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
HANDLE h = CreateFile(_T(GRPC_ALTS_WINDOWS_CHECK_BIOS_FILE), GENERIC_WRITE,
FILE_SHARE_WRITE | FILE_SHARE_READ, &sa, OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
if (h == INVALID_HANDLE_VALUE) {
gpr_log(GPR_ERROR, "CreateFile failed (%d).", GetLastError());
return false;
}
PROCESS_INFORMATION pi;
STARTUPINFO si;
DWORD flags = CREATE_NO_WINDOW;
ZeroMemory(&pi, sizeof(pi));
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
si.dwFlags |= STARTF_USESTDHANDLES;
si.hStdInput = NULL;
si.hStdError = h;
si.hStdOutput = h;
TCHAR cmd[kBiosDataBufferSize];
_sntprintf(cmd, kBiosDataBufferSize, _T("%s %s"),
_T(GRPC_ALTS_WINDOWS_CHECK_COMMAND),
_T(GRPC_ALTS_WINDOWS_CHECK_COMMAND_ARGS));
if (!CreateProcess(NULL, cmd, NULL, NULL, TRUE, flags, NULL, NULL, &si,
&pi)) {
gpr_log(GPR_ERROR, "CreateProcess failed (%d).\n", GetLastError());
return false;
}
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
CloseHandle(h);
return true;
}
bool grpc_alts_is_running_on_gcp() {
gpr_once_init(&g_once, init_mu);
gpr_mu_lock(&g_mu);
if (!g_compute_engine_detection_done) {
g_is_on_compute_engine =
run_powershell() &&
grpc_core::internal::check_bios_data(GRPC_ALTS_WINDOWS_CHECK_BIOS_FILE);
g_compute_engine_detection_done = true;
}
gpr_mu_unlock(&g_mu);
return g_is_on_compute_engine;
}
#endif // GPR_WINDOWS

@ -0,0 +1,126 @@
/*
*
* Copyright 2018 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 <grpc/support/port_platform.h>
#include <stdlib.h>
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include "src/core/lib/security/credentials/alts/grpc_alts_credentials_options.h"
#include "src/core/tsi/alts/handshaker/transport_security_common_api.h"
static grpc_alts_credentials_options* alts_client_options_copy(
const grpc_alts_credentials_options* options);
static void alts_client_options_destroy(grpc_alts_credentials_options* options);
static target_service_account* target_service_account_create(
const char* service_account) {
if (service_account == nullptr) {
return nullptr;
}
auto* sa = static_cast<target_service_account*>(
gpr_zalloc(sizeof(target_service_account)));
sa->data = gpr_strdup(service_account);
return sa;
}
bool grpc_alts_credentials_client_options_add_target_service_account(
grpc_alts_credentials_client_options* options,
const char* service_account) {
if (options == nullptr || service_account == nullptr) {
gpr_log(
GPR_ERROR,
"Invalid nullptr arguments to "
"grpc_alts_credentials_client_options_add_target_service_account()");
return false;
}
target_service_account* node = target_service_account_create(service_account);
node->next = options->target_account_list_head;
options->target_account_list_head = node;
return true;
}
static void target_service_account_destroy(
target_service_account* service_account) {
if (service_account == nullptr) {
return;
}
gpr_free(service_account->data);
gpr_free(service_account);
}
static const grpc_alts_credentials_options_vtable vtable = {
alts_client_options_copy, alts_client_options_destroy};
grpc_alts_credentials_options* grpc_alts_credentials_client_options_create() {
auto client_options = static_cast<grpc_alts_credentials_client_options*>(
gpr_zalloc(sizeof(grpc_alts_credentials_client_options)));
client_options->base.vtable = &vtable;
return &client_options->base;
}
static grpc_alts_credentials_options* alts_client_options_copy(
const grpc_alts_credentials_options* options) {
if (options == nullptr) {
return nullptr;
}
grpc_alts_credentials_options* new_options =
grpc_alts_credentials_client_options_create();
auto new_client_options =
reinterpret_cast<grpc_alts_credentials_client_options*>(new_options);
/* Copy target service accounts. */
target_service_account* prev = nullptr;
auto node =
(reinterpret_cast<const grpc_alts_credentials_client_options*>(options))
->target_account_list_head;
while (node != nullptr) {
target_service_account* new_node =
target_service_account_create(node->data);
if (prev == nullptr) {
new_client_options->target_account_list_head = new_node;
} else {
prev->next = new_node;
}
prev = new_node;
node = node->next;
}
/* Copy rpc protocol versions. */
grpc_gcp_rpc_protocol_versions_copy(&options->rpc_versions,
&new_options->rpc_versions);
return new_options;
}
static void alts_client_options_destroy(
grpc_alts_credentials_options* options) {
if (options == nullptr) {
return;
}
auto* client_options =
reinterpret_cast<grpc_alts_credentials_client_options*>(options);
target_service_account* node = client_options->target_account_list_head;
while (node != nullptr) {
target_service_account* next_node = node->next;
target_service_account_destroy(node);
node = next_node;
}
}

@ -0,0 +1,46 @@
/*
*
* Copyright 2018 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 <grpc/support/port_platform.h>
#include "src/core/lib/security/credentials/alts/grpc_alts_credentials_options.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
grpc_alts_credentials_options* grpc_alts_credentials_options_copy(
const grpc_alts_credentials_options* options) {
if (options != nullptr && options->vtable != nullptr &&
options->vtable->copy != nullptr) {
return options->vtable->copy(options);
}
/* An error occurred. */
gpr_log(GPR_ERROR,
"Invalid arguments to grpc_alts_credentials_options_copy()");
return nullptr;
}
void grpc_alts_credentials_options_destroy(
grpc_alts_credentials_options* options) {
if (options != nullptr) {
if (options->vtable != nullptr && options->vtable->destruct != nullptr) {
options->vtable->destruct(options);
}
gpr_free(options);
}
}

@ -0,0 +1,112 @@
/*
*
* Copyright 2018 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_CORE_LIB_SECURITY_CREDENTIALS_ALTS_GRPC_ALTS_CREDENTIALS_OPTIONS_H
#define GRPC_CORE_LIB_SECURITY_CREDENTIALS_ALTS_GRPC_ALTS_CREDENTIALS_OPTIONS_H
#include <grpc/support/port_platform.h>
#include <stdbool.h>
#include "src/core/tsi/alts/handshaker/transport_security_common_api.h"
/**
* Main interface for ALTS credentials options. The options will contain
* information that will be passed from grpc to TSI layer such as RPC protocol
* versions. ALTS client (channel) and server credentials will have their own
* implementation of this interface. The APIs listed in this header are
* thread-compatible.
*/
typedef struct grpc_alts_credentials_options grpc_alts_credentials_options;
/* V-table for grpc_alts_credentials_options */
typedef struct grpc_alts_credentials_options_vtable {
grpc_alts_credentials_options* (*copy)(
const grpc_alts_credentials_options* options);
void (*destruct)(grpc_alts_credentials_options* options);
} grpc_alts_credentials_options_vtable;
struct grpc_alts_credentials_options {
const struct grpc_alts_credentials_options_vtable* vtable;
grpc_gcp_rpc_protocol_versions rpc_versions;
};
typedef struct target_service_account {
struct target_service_account* next;
char* data;
} target_service_account;
/**
* Main struct for ALTS client credentials options. The options contain a
* a list of target service accounts (if specified) used for secure naming
* check.
*/
typedef struct grpc_alts_credentials_client_options {
grpc_alts_credentials_options base;
target_service_account* target_account_list_head;
} grpc_alts_credentials_client_options;
/**
* Main struct for ALTS server credentials options. The options currently
* do not contain any server-specific fields.
*/
typedef struct grpc_alts_credentials_server_options {
grpc_alts_credentials_options base;
} grpc_alts_credentials_server_options;
/**
* This method performs a deep copy on grpc_alts_credentials_options instance.
*
* - options: a grpc_alts_credentials_options instance that needs to be copied.
*
* It returns a new grpc_alts_credentials_options instance on success and NULL
* on failure.
*/
grpc_alts_credentials_options* grpc_alts_credentials_options_copy(
const grpc_alts_credentials_options* options);
/**
* This method destroys a grpc_alts_credentials_options instance by
* de-allocating all of its occupied memory.
*
* - options: a grpc_alts_credentials_options instance that needs to be
* destroyed.
*/
void grpc_alts_credentials_options_destroy(
grpc_alts_credentials_options* options);
/* This method creates a grpc ALTS credentials client options instance. */
grpc_alts_credentials_options* grpc_alts_credentials_client_options_create();
/* This method creates a grpc ALTS credentials server options instance. */
grpc_alts_credentials_options* grpc_alts_credentials_server_options_create();
/**
* This method adds a target service account to grpc ALTS credentials client
* options instance.
*
* - options: grpc ALTS credentials client options instance.
* - service_account: service account of target endpoint.
*
* It returns true on success and false on failure.
*/
bool grpc_alts_credentials_client_options_add_target_service_account(
grpc_alts_credentials_client_options* options, const char* service_account);
#endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_ALTS_GRPC_ALTS_CREDENTIALS_OPTIONS_H \
*/

@ -0,0 +1,58 @@
/*
*
* Copyright 2018 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 <grpc/support/port_platform.h>
#include <stdlib.h>
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "src/core/lib/security/credentials/alts/grpc_alts_credentials_options.h"
#include "src/core/tsi/alts/handshaker/transport_security_common_api.h"
static grpc_alts_credentials_options* alts_server_options_copy(
const grpc_alts_credentials_options* options);
static void alts_server_options_destroy(
grpc_alts_credentials_options* options) {}
static const grpc_alts_credentials_options_vtable vtable = {
alts_server_options_copy, alts_server_options_destroy};
grpc_alts_credentials_options* grpc_alts_credentials_server_options_create() {
grpc_alts_credentials_server_options* server_options =
static_cast<grpc_alts_credentials_server_options*>(
gpr_zalloc(sizeof(*server_options)));
server_options->base.vtable = &vtable;
return &server_options->base;
}
static grpc_alts_credentials_options* alts_server_options_copy(
const grpc_alts_credentials_options* options) {
if (options == nullptr) {
return nullptr;
}
grpc_alts_credentials_options* new_options =
grpc_alts_credentials_server_options_create();
/* Copy rpc protocol versions. */
grpc_gcp_rpc_protocol_versions_copy(&options->rpc_versions,
&new_options->rpc_versions);
return new_options;
}

@ -0,0 +1,287 @@
/*
*
* Copyright 2018 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 <grpc/support/port_platform.h>
#include "src/core/lib/security/security_connector/alts_security_connector.h"
#include <stdbool.h>
#include <string.h>
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include "src/core/lib/security/credentials/alts/alts_credentials.h"
#include "src/core/lib/security/transport/security_handshaker.h"
#include "src/core/lib/transport/transport.h"
#include "src/core/tsi/alts/handshaker/alts_tsi_handshaker.h"
typedef struct {
grpc_channel_security_connector base;
char* target_name;
} grpc_alts_channel_security_connector;
typedef struct {
grpc_server_security_connector base;
} grpc_alts_server_security_connector;
static void alts_channel_destroy(grpc_security_connector* sc) {
if (sc == nullptr) {
return;
}
auto c = reinterpret_cast<grpc_alts_channel_security_connector*>(sc);
grpc_call_credentials_unref(c->base.request_metadata_creds);
grpc_channel_credentials_unref(c->base.channel_creds);
gpr_free(c->target_name);
gpr_free(sc);
}
static void alts_server_destroy(grpc_security_connector* sc) {
if (sc == nullptr) {
return;
}
auto c = reinterpret_cast<grpc_alts_server_security_connector*>(sc);
grpc_server_credentials_unref(c->base.server_creds);
gpr_free(sc);
}
static void alts_channel_add_handshakers(
grpc_channel_security_connector* sc,
grpc_handshake_manager* handshake_manager) {
tsi_handshaker* handshaker = nullptr;
auto c = reinterpret_cast<grpc_alts_channel_security_connector*>(sc);
grpc_alts_credentials* creds =
reinterpret_cast<grpc_alts_credentials*>(c->base.channel_creds);
GPR_ASSERT(alts_tsi_handshaker_create(creds->options, c->target_name,
creds->handshaker_service_url, true,
&handshaker) == TSI_OK);
grpc_handshake_manager_add(handshake_manager, grpc_security_handshaker_create(
handshaker, &sc->base));
}
static void alts_server_add_handshakers(
grpc_server_security_connector* sc,
grpc_handshake_manager* handshake_manager) {
tsi_handshaker* handshaker = nullptr;
auto c = reinterpret_cast<grpc_alts_server_security_connector*>(sc);
grpc_alts_server_credentials* creds =
reinterpret_cast<grpc_alts_server_credentials*>(c->base.server_creds);
GPR_ASSERT(alts_tsi_handshaker_create(creds->options, nullptr,
creds->handshaker_service_url, false,
&handshaker) == TSI_OK);
grpc_handshake_manager_add(handshake_manager, grpc_security_handshaker_create(
handshaker, &sc->base));
}
static void alts_set_rpc_protocol_versions(
grpc_gcp_rpc_protocol_versions* rpc_versions) {
grpc_gcp_rpc_protocol_versions_set_max(rpc_versions,
GRPC_PROTOCOL_VERSION_MAX_MAJOR,
GRPC_PROTOCOL_VERSION_MAX_MINOR);
grpc_gcp_rpc_protocol_versions_set_min(rpc_versions,
GRPC_PROTOCOL_VERSION_MIN_MAJOR,
GRPC_PROTOCOL_VERSION_MIN_MINOR);
}
namespace grpc_core {
namespace internal {
grpc_security_status grpc_alts_auth_context_from_tsi_peer(
const tsi_peer* peer, grpc_auth_context** ctx) {
if (peer == nullptr || ctx == nullptr) {
gpr_log(GPR_ERROR,
"Invalid arguments to grpc_alts_auth_context_from_tsi_peer()");
return GRPC_SECURITY_ERROR;
}
*ctx = nullptr;
/* Validate certificate type. */
const tsi_peer_property* cert_type_prop =
tsi_peer_get_property_by_name(peer, TSI_CERTIFICATE_TYPE_PEER_PROPERTY);
if (cert_type_prop == nullptr ||
strncmp(cert_type_prop->value.data, TSI_ALTS_CERTIFICATE_TYPE,
cert_type_prop->value.length) != 0) {
gpr_log(GPR_ERROR, "Invalid or missing certificate type property.");
return GRPC_SECURITY_ERROR;
}
/* Validate RPC protocol versions. */
const tsi_peer_property* rpc_versions_prop =
tsi_peer_get_property_by_name(peer, TSI_ALTS_RPC_VERSIONS);
if (rpc_versions_prop == nullptr) {
gpr_log(GPR_ERROR, "Missing rpc protocol versions property.");
return GRPC_SECURITY_ERROR;
}
grpc_gcp_rpc_protocol_versions local_versions, peer_versions;
alts_set_rpc_protocol_versions(&local_versions);
grpc_slice slice = grpc_slice_from_copied_buffer(
rpc_versions_prop->value.data, rpc_versions_prop->value.length);
bool decode_result =
grpc_gcp_rpc_protocol_versions_decode(slice, &peer_versions);
grpc_slice_unref(slice);
if (!decode_result) {
gpr_log(GPR_ERROR, "Invalid peer rpc protocol versions.");
return GRPC_SECURITY_ERROR;
}
/* TODO: Pass highest common rpc protocol version to grpc caller. */
bool check_result = grpc_gcp_rpc_protocol_versions_check(
&local_versions, &peer_versions, nullptr);
if (!check_result) {
gpr_log(GPR_ERROR, "Mismatch of local and peer rpc protocol versions.");
return GRPC_SECURITY_ERROR;
}
/* Create auth context. */
*ctx = grpc_auth_context_create(nullptr);
grpc_auth_context_add_cstring_property(
*ctx, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME,
GRPC_ALTS_TRANSPORT_SECURITY_TYPE);
size_t i = 0;
for (i = 0; i < peer->property_count; i++) {
const tsi_peer_property* tsi_prop = &peer->properties[i];
/* Add service account to auth context. */
if (strcmp(tsi_prop->name, TSI_ALTS_SERVICE_ACCOUNT_PEER_PROPERTY) == 0) {
grpc_auth_context_add_property(
*ctx, TSI_ALTS_SERVICE_ACCOUNT_PEER_PROPERTY, tsi_prop->value.data,
tsi_prop->value.length);
GPR_ASSERT(grpc_auth_context_set_peer_identity_property_name(
*ctx, TSI_ALTS_SERVICE_ACCOUNT_PEER_PROPERTY) == 1);
}
}
if (!grpc_auth_context_peer_is_authenticated(*ctx)) {
gpr_log(GPR_ERROR, "Invalid unauthenticated peer.");
GRPC_AUTH_CONTEXT_UNREF(*ctx, "test");
*ctx = nullptr;
return GRPC_SECURITY_ERROR;
}
return GRPC_SECURITY_OK;
}
} // namespace internal
} // namespace grpc_core
static void alts_check_peer(grpc_security_connector* sc, tsi_peer peer,
grpc_auth_context** auth_context,
grpc_closure* on_peer_checked) {
grpc_security_status status;
status = grpc_core::internal::grpc_alts_auth_context_from_tsi_peer(
&peer, auth_context);
tsi_peer_destruct(&peer);
grpc_error* error =
status == GRPC_SECURITY_OK
? GRPC_ERROR_NONE
: GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Could not get ALTS auth context from TSI peer");
GRPC_CLOSURE_SCHED(on_peer_checked, error);
}
static int alts_channel_cmp(grpc_security_connector* sc1,
grpc_security_connector* sc2) {
grpc_alts_channel_security_connector* c1 =
reinterpret_cast<grpc_alts_channel_security_connector*>(sc1);
grpc_alts_channel_security_connector* c2 =
reinterpret_cast<grpc_alts_channel_security_connector*>(sc2);
int c = grpc_channel_security_connector_cmp(&c1->base, &c2->base);
if (c != 0) return c;
return strcmp(c1->target_name, c2->target_name);
}
static int alts_server_cmp(grpc_security_connector* sc1,
grpc_security_connector* sc2) {
grpc_alts_server_security_connector* c1 =
reinterpret_cast<grpc_alts_server_security_connector*>(sc1);
grpc_alts_server_security_connector* c2 =
reinterpret_cast<grpc_alts_server_security_connector*>(sc2);
return grpc_server_security_connector_cmp(&c1->base, &c2->base);
}
static grpc_security_connector_vtable alts_channel_vtable = {
alts_channel_destroy, alts_check_peer, alts_channel_cmp};
static grpc_security_connector_vtable alts_server_vtable = {
alts_server_destroy, alts_check_peer, alts_server_cmp};
static bool alts_check_call_host(grpc_channel_security_connector* sc,
const char* host,
grpc_auth_context* auth_context,
grpc_closure* on_call_host_checked,
grpc_error** error) {
grpc_alts_channel_security_connector* alts_sc =
reinterpret_cast<grpc_alts_channel_security_connector*>(sc);
if (host == nullptr || alts_sc == nullptr ||
strcmp(host, alts_sc->target_name) != 0) {
*error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"ALTS call host does not match target name");
}
return true;
}
static void alts_cancel_check_call_host(grpc_channel_security_connector* sc,
grpc_closure* on_call_host_checked,
grpc_error* error) {
GRPC_ERROR_UNREF(error);
}
grpc_security_status grpc_alts_channel_security_connector_create(
grpc_channel_credentials* channel_creds,
grpc_call_credentials* request_metadata_creds, const char* target_name,
grpc_channel_security_connector** sc) {
if (channel_creds == nullptr || sc == nullptr || target_name == nullptr) {
gpr_log(
GPR_ERROR,
"Invalid arguments to grpc_alts_channel_security_connector_create()");
return GRPC_SECURITY_ERROR;
}
auto c = static_cast<grpc_alts_channel_security_connector*>(
gpr_zalloc(sizeof(grpc_alts_channel_security_connector)));
gpr_ref_init(&c->base.base.refcount, 1);
c->base.base.vtable = &alts_channel_vtable;
c->base.add_handshakers = alts_channel_add_handshakers;
c->base.channel_creds = grpc_channel_credentials_ref(channel_creds);
c->base.request_metadata_creds =
grpc_call_credentials_ref(request_metadata_creds);
c->base.check_call_host = alts_check_call_host;
c->base.cancel_check_call_host = alts_cancel_check_call_host;
grpc_alts_credentials* creds =
reinterpret_cast<grpc_alts_credentials*>(c->base.channel_creds);
alts_set_rpc_protocol_versions(&creds->options->rpc_versions);
c->target_name = gpr_strdup(target_name);
*sc = &c->base;
return GRPC_SECURITY_OK;
}
grpc_security_status grpc_alts_server_security_connector_create(
grpc_server_credentials* server_creds,
grpc_server_security_connector** sc) {
if (server_creds == nullptr || sc == nullptr) {
gpr_log(
GPR_ERROR,
"Invalid arguments to grpc_alts_server_security_connector_create()");
return GRPC_SECURITY_ERROR;
}
auto c = static_cast<grpc_alts_server_security_connector*>(
gpr_zalloc(sizeof(grpc_alts_server_security_connector)));
gpr_ref_init(&c->base.base.refcount, 1);
c->base.base.vtable = &alts_server_vtable;
c->base.server_creds = grpc_server_credentials_ref(server_creds);
c->base.add_handshakers = alts_server_add_handshakers;
grpc_alts_server_credentials* creds =
reinterpret_cast<grpc_alts_server_credentials*>(c->base.server_creds);
alts_set_rpc_protocol_versions(&creds->options->rpc_versions);
*sc = &c->base;
return GRPC_SECURITY_OK;
}

@ -0,0 +1,69 @@
/*
*
* Copyright 2018 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_CORE_LIB_SECURITY_SECURITY_CONNECTOR_ALTS_SECURITY_CONNECTOR_H
#define GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_ALTS_SECURITY_CONNECTOR_H
#include <grpc/support/port_platform.h>
#include "src/core/lib/security/context/security_context.h"
#include "src/core/lib/security/credentials/alts/grpc_alts_credentials_options.h"
#define GRPC_ALTS_TRANSPORT_SECURITY_TYPE "alts"
/**
* This method creates an ALTS channel security connector.
*
* - channel_creds: channel credential instance.
* - request_metadata_creds: credential object which will be sent with each
* request. This parameter can be nullptr.
* - target_name: the name of the endpoint that the channel is connecting to.
* - sc: address of ALTS channel security connector instance to be returned from
* the method.
*
* It returns GRPC_SECURITY_OK on success, and an error stauts code on failure.
*/
grpc_security_status grpc_alts_channel_security_connector_create(
grpc_channel_credentials* channel_creds,
grpc_call_credentials* request_metadata_creds, const char* target_name,
grpc_channel_security_connector** sc);
/**
* This method creates an ALTS server security connector.
*
* - server_creds: server credential instance.
* - sc: address of ALTS server security connector instance to be returned from
* the method.
*
* It returns GRPC_SECURITY_OK on success, and an error status code on failure.
*/
grpc_security_status grpc_alts_server_security_connector_create(
grpc_server_credentials* server_creds, grpc_server_security_connector** sc);
namespace grpc_core {
namespace internal {
/* Exposed only for testing. */
grpc_security_status grpc_alts_auth_context_from_tsi_peer(
const tsi_peer* peer, grpc_auth_context** ctx);
} // namespace internal
} // namespace grpc_core
#endif /* GRPC_CORE_LIB_SECURITY_SECURITY_CONNECTOR_ALTS_SECURITY_CONNECTOR_H \
*/

@ -24,12 +24,12 @@ void grpc_http_filters_init(void);
void grpc_http_filters_shutdown(void);
void grpc_chttp2_plugin_init(void);
void grpc_chttp2_plugin_shutdown(void);
void grpc_tsi_alts_init(void);
void grpc_tsi_alts_shutdown(void);
void grpc_deadline_filter_init(void);
void grpc_deadline_filter_shutdown(void);
void grpc_client_channel_init(void);
void grpc_client_channel_shutdown(void);
void grpc_tsi_alts_init(void);
void grpc_tsi_alts_shutdown(void);
void grpc_inproc_plugin_init(void);
void grpc_inproc_plugin_shutdown(void);
void grpc_resolver_fake_init(void);
@ -60,12 +60,12 @@ void grpc_register_built_in_plugins(void) {
grpc_http_filters_shutdown);
grpc_register_plugin(grpc_chttp2_plugin_init,
grpc_chttp2_plugin_shutdown);
grpc_register_plugin(grpc_tsi_alts_init,
grpc_tsi_alts_shutdown);
grpc_register_plugin(grpc_deadline_filter_init,
grpc_deadline_filter_shutdown);
grpc_register_plugin(grpc_client_channel_init,
grpc_client_channel_shutdown);
grpc_register_plugin(grpc_tsi_alts_init,
grpc_tsi_alts_shutdown);
grpc_register_plugin(grpc_inproc_plugin_init,
grpc_inproc_plugin_shutdown);
grpc_register_plugin(grpc_resolver_fake_init,

@ -0,0 +1,687 @@
/*
*
* Copyright 2018 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 <grpc/support/port_platform.h>
#include "src/core/tsi/alts/crypt/gsec.h"
#include <openssl/bio.h>
#include <openssl/buffer.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <string.h>
#include <grpc/support/alloc.h>
constexpr size_t kKdfKeyLen = 32;
constexpr size_t kKdfCounterLen = 6;
constexpr size_t kKdfCounterOffset = 2;
constexpr size_t kRekeyAeadKeyLen = kAes128GcmKeyLength;
/* Struct for additional data required if rekeying is enabled. */
struct gsec_aes_gcm_aead_rekey_data {
uint8_t kdf_counter[kKdfCounterLen];
uint8_t nonce_mask[kAesGcmNonceLength];
};
/* Main struct for AES_GCM crypter interface. */
struct gsec_aes_gcm_aead_crypter {
gsec_aead_crypter crypter;
size_t key_length;
size_t nonce_length;
size_t tag_length;
uint8_t* key;
gsec_aes_gcm_aead_rekey_data* rekey_data;
EVP_CIPHER_CTX* ctx;
};
static char* aes_gcm_get_openssl_errors() {
BIO* bio = BIO_new(BIO_s_mem());
ERR_print_errors(bio);
BUF_MEM* mem = nullptr;
char* error_msg = nullptr;
BIO_get_mem_ptr(bio, &mem);
if (mem != nullptr) {
error_msg = static_cast<char*>(gpr_malloc(mem->length + 1));
memcpy(error_msg, mem->data, mem->length);
error_msg[mem->length] = '\0';
}
BIO_free_all(bio);
return error_msg;
}
static void aes_gcm_format_errors(const char* error_msg, char** error_details) {
if (error_details == nullptr) {
return;
}
unsigned long error = ERR_get_error();
if (error == 0 && error_msg != nullptr) {
*error_details = static_cast<char*>(gpr_malloc(strlen(error_msg) + 1));
memcpy(*error_details, error_msg, strlen(error_msg) + 1);
return;
}
char* openssl_errors = aes_gcm_get_openssl_errors();
if (openssl_errors != nullptr && error_msg != nullptr) {
size_t len = strlen(error_msg) + strlen(openssl_errors) + 2; /* ", " */
*error_details = static_cast<char*>(gpr_malloc(len + 1));
snprintf(*error_details, len + 1, "%s, %s", error_msg, openssl_errors);
gpr_free(openssl_errors);
}
}
static grpc_status_code gsec_aes_gcm_aead_crypter_max_ciphertext_and_tag_length(
const gsec_aead_crypter* crypter, size_t plaintext_length,
size_t* max_ciphertext_and_tag_length, char** error_details) {
if (max_ciphertext_and_tag_length == nullptr) {
aes_gcm_format_errors("max_ciphertext_and_tag_length is nullptr.",
error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
gsec_aes_gcm_aead_crypter* aes_gcm_crypter =
reinterpret_cast<gsec_aes_gcm_aead_crypter*>(
const_cast<gsec_aead_crypter*>(crypter));
*max_ciphertext_and_tag_length =
plaintext_length + aes_gcm_crypter->tag_length;
return GRPC_STATUS_OK;
}
static grpc_status_code gsec_aes_gcm_aead_crypter_max_plaintext_length(
const gsec_aead_crypter* crypter, size_t ciphertext_and_tag_length,
size_t* max_plaintext_length, char** error_details) {
if (max_plaintext_length == nullptr) {
aes_gcm_format_errors("max_plaintext_length is nullptr.", error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
gsec_aes_gcm_aead_crypter* aes_gcm_crypter =
reinterpret_cast<gsec_aes_gcm_aead_crypter*>(
const_cast<gsec_aead_crypter*>(crypter));
if (ciphertext_and_tag_length < aes_gcm_crypter->tag_length) {
*max_plaintext_length = 0;
aes_gcm_format_errors(
"ciphertext_and_tag_length is smaller than tag_length.", error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
*max_plaintext_length =
ciphertext_and_tag_length - aes_gcm_crypter->tag_length;
return GRPC_STATUS_OK;
}
static grpc_status_code gsec_aes_gcm_aead_crypter_nonce_length(
const gsec_aead_crypter* crypter, size_t* nonce_length,
char** error_details) {
if (nonce_length == nullptr) {
aes_gcm_format_errors("nonce_length is nullptr.", error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
gsec_aes_gcm_aead_crypter* aes_gcm_crypter =
reinterpret_cast<gsec_aes_gcm_aead_crypter*>(
const_cast<gsec_aead_crypter*>(crypter));
*nonce_length = aes_gcm_crypter->nonce_length;
return GRPC_STATUS_OK;
}
static grpc_status_code gsec_aes_gcm_aead_crypter_key_length(
const gsec_aead_crypter* crypter, size_t* key_length,
char** error_details) {
if (key_length == nullptr) {
aes_gcm_format_errors("key_length is nullptr.", error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
gsec_aes_gcm_aead_crypter* aes_gcm_crypter =
reinterpret_cast<gsec_aes_gcm_aead_crypter*>(
const_cast<gsec_aead_crypter*>(crypter));
*key_length = aes_gcm_crypter->key_length;
return GRPC_STATUS_OK;
}
static grpc_status_code gsec_aes_gcm_aead_crypter_tag_length(
const gsec_aead_crypter* crypter, size_t* tag_length,
char** error_details) {
if (tag_length == nullptr) {
aes_gcm_format_errors("tag_length is nullptr.", error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
gsec_aes_gcm_aead_crypter* aes_gcm_crypter =
reinterpret_cast<gsec_aes_gcm_aead_crypter*>(
const_cast<gsec_aead_crypter*>(crypter));
*tag_length = aes_gcm_crypter->tag_length;
return GRPC_STATUS_OK;
}
static void aes_gcm_mask_nonce(uint8_t* dst, const uint8_t* nonce,
const uint8_t* mask) {
uint64_t mask1;
uint32_t mask2;
memcpy(&mask1, mask, sizeof(mask1));
memcpy(&mask2, mask + sizeof(mask1), sizeof(mask2));
uint64_t nonce1;
uint32_t nonce2;
memcpy(&nonce1, nonce, sizeof(nonce1));
memcpy(&nonce2, nonce + sizeof(nonce1), sizeof(nonce2));
nonce1 ^= mask1;
nonce2 ^= mask2;
memcpy(dst, &nonce1, sizeof(nonce1));
memcpy(dst + sizeof(nonce1), &nonce2, sizeof(nonce2));
}
static grpc_status_code aes_gcm_derive_aead_key(uint8_t* dst,
const uint8_t* kdf_key,
const uint8_t* kdf_counter) {
unsigned char buf[EVP_MAX_MD_SIZE];
unsigned char ctr = 1;
#if OPENSSL_VERSION_NUMBER < 0x10100000L
HMAC_CTX hmac;
HMAC_CTX_init(&hmac);
if (!HMAC_Init_ex(&hmac, kdf_key, kKdfKeyLen, EVP_sha256(), nullptr) ||
!HMAC_Update(&hmac, kdf_counter, kKdfCounterLen) ||
!HMAC_Update(&hmac, &ctr, 1) || !HMAC_Final(&hmac, buf, nullptr)) {
HMAC_CTX_cleanup(&hmac);
return GRPC_STATUS_INTERNAL;
}
HMAC_CTX_cleanup(&hmac);
#else
HMAC_CTX* hmac = HMAC_CTX_new();
if (hmac == nullptr) {
return GRPC_STATUS_INTERNAL;
}
if (!HMAC_Init_ex(hmac, kdf_key, kKdfKeyLen, EVP_sha256(), nullptr) ||
!HMAC_Update(hmac, kdf_counter, kKdfCounterLen) ||
!HMAC_Update(hmac, &ctr, 1) || !HMAC_Final(hmac, buf, nullptr)) {
HMAC_CTX_free(hmac);
return GRPC_STATUS_INTERNAL;
}
HMAC_CTX_free(hmac);
#endif
memcpy(dst, buf, kRekeyAeadKeyLen);
return GRPC_STATUS_OK;
}
static grpc_status_code aes_gcm_rekey_if_required(
gsec_aes_gcm_aead_crypter* aes_gcm_crypter, const uint8_t* nonce,
char** error_details) {
// If rekey_data is nullptr, then rekeying is not supported and not required.
// If bytes 2-7 of kdf_counter differ from the (per message) nonce, then the
// encryption key is recomputed from a new kdf_counter to ensure that we don't
// encrypt more than 2^16 messages per encryption key (in each direction).
if (aes_gcm_crypter->rekey_data == nullptr ||
memcmp(aes_gcm_crypter->rekey_data->kdf_counter,
nonce + kKdfCounterOffset, kKdfCounterLen) == 0) {
return GRPC_STATUS_OK;
}
memcpy(aes_gcm_crypter->rekey_data->kdf_counter, nonce + kKdfCounterOffset,
kKdfCounterLen);
uint8_t aead_key[kRekeyAeadKeyLen];
if (aes_gcm_derive_aead_key(aead_key, aes_gcm_crypter->key,
aes_gcm_crypter->rekey_data->kdf_counter) !=
GRPC_STATUS_OK) {
aes_gcm_format_errors("Rekeying failed in key derivation.", error_details);
return GRPC_STATUS_INTERNAL;
}
if (!EVP_DecryptInit_ex(aes_gcm_crypter->ctx, nullptr, nullptr, aead_key,
nullptr)) {
aes_gcm_format_errors("Rekeying failed in context update.", error_details);
return GRPC_STATUS_INTERNAL;
}
return GRPC_STATUS_OK;
}
static grpc_status_code gsec_aes_gcm_aead_crypter_encrypt_iovec(
gsec_aead_crypter* crypter, const uint8_t* nonce, size_t nonce_length,
const struct iovec* aad_vec, size_t aad_vec_length,
const struct iovec* plaintext_vec, size_t plaintext_vec_length,
struct iovec ciphertext_vec, size_t* ciphertext_bytes_written,
char** error_details) {
gsec_aes_gcm_aead_crypter* aes_gcm_crypter =
reinterpret_cast<gsec_aes_gcm_aead_crypter*>(crypter);
// Input checks
if (nonce == nullptr) {
aes_gcm_format_errors("Nonce buffer is nullptr.", error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
if (kAesGcmNonceLength != nonce_length) {
aes_gcm_format_errors("Nonce buffer has the wrong length.", error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
if (aad_vec_length > 0 && aad_vec == nullptr) {
aes_gcm_format_errors("Non-zero aad_vec_length but aad_vec is nullptr.",
error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
if (plaintext_vec_length > 0 && plaintext_vec == nullptr) {
aes_gcm_format_errors(
"Non-zero plaintext_vec_length but plaintext_vec is nullptr.",
error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
if (ciphertext_bytes_written == nullptr) {
aes_gcm_format_errors("bytes_written is nullptr.", error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
*ciphertext_bytes_written = 0;
// rekey if required
if (aes_gcm_rekey_if_required(aes_gcm_crypter, nonce, error_details) !=
GRPC_STATUS_OK) {
return GRPC_STATUS_INTERNAL;
}
// mask nonce if required
const uint8_t* nonce_aead = nonce;
uint8_t nonce_masked[kAesGcmNonceLength];
if (aes_gcm_crypter->rekey_data != nullptr) {
aes_gcm_mask_nonce(nonce_masked, aes_gcm_crypter->rekey_data->nonce_mask,
nonce);
nonce_aead = nonce_masked;
}
// init openssl context
if (!EVP_EncryptInit_ex(aes_gcm_crypter->ctx, nullptr, nullptr, nullptr,
nonce_aead)) {
aes_gcm_format_errors("Initializing nonce failed", error_details);
return GRPC_STATUS_INTERNAL;
}
// process aad
size_t i;
for (i = 0; i < aad_vec_length; i++) {
const uint8_t* aad = static_cast<uint8_t*>(aad_vec[i].iov_base);
size_t aad_length = aad_vec[i].iov_len;
if (aad_length == 0) {
continue;
}
size_t aad_bytes_read = 0;
if (aad == nullptr) {
aes_gcm_format_errors("aad is nullptr.", error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
if (!EVP_EncryptUpdate(aes_gcm_crypter->ctx, nullptr,
reinterpret_cast<int*>(&aad_bytes_read), aad,
static_cast<int>(aad_length)) ||
aad_bytes_read != aad_length) {
aes_gcm_format_errors("Setting authenticated associated data failed",
error_details);
return GRPC_STATUS_INTERNAL;
}
}
uint8_t* ciphertext = static_cast<uint8_t*>(ciphertext_vec.iov_base);
size_t ciphertext_length = ciphertext_vec.iov_len;
if (ciphertext == nullptr) {
aes_gcm_format_errors("ciphertext is nullptr.", error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
// process plaintext
for (i = 0; i < plaintext_vec_length; i++) {
const uint8_t* plaintext = static_cast<uint8_t*>(plaintext_vec[i].iov_base);
size_t plaintext_length = plaintext_vec[i].iov_len;
if (plaintext == nullptr) {
if (plaintext_length == 0) {
continue;
}
aes_gcm_format_errors("plaintext is nullptr.", error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
if (ciphertext_length < plaintext_length) {
aes_gcm_format_errors(
"ciphertext is not large enough to hold the result.", error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
int bytes_written = 0;
int bytes_to_write = static_cast<int>(plaintext_length);
if (!EVP_EncryptUpdate(aes_gcm_crypter->ctx, ciphertext, &bytes_written,
plaintext, bytes_to_write)) {
aes_gcm_format_errors("Encrypting plaintext failed.", error_details);
return GRPC_STATUS_INTERNAL;
}
if (bytes_written > bytes_to_write) {
aes_gcm_format_errors("More bytes written than expected.", error_details);
return GRPC_STATUS_INTERNAL;
}
ciphertext += bytes_written;
ciphertext_length -= bytes_written;
}
int bytes_written_temp = 0;
if (!EVP_EncryptFinal_ex(aes_gcm_crypter->ctx, nullptr,
&bytes_written_temp)) {
aes_gcm_format_errors("Finalizing encryption failed.", error_details);
return GRPC_STATUS_INTERNAL;
}
if (bytes_written_temp != 0) {
aes_gcm_format_errors("Openssl wrote some unexpected bytes.",
error_details);
return GRPC_STATUS_INTERNAL;
}
if (ciphertext_length < kAesGcmTagLength) {
aes_gcm_format_errors("ciphertext is too small to hold a tag.",
error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
if (!EVP_CIPHER_CTX_ctrl(aes_gcm_crypter->ctx, EVP_CTRL_GCM_GET_TAG,
kAesGcmTagLength, ciphertext)) {
aes_gcm_format_errors("Writing tag failed.", error_details);
return GRPC_STATUS_INTERNAL;
}
ciphertext += kAesGcmTagLength;
ciphertext_length -= kAesGcmTagLength;
*ciphertext_bytes_written = ciphertext_vec.iov_len - ciphertext_length;
return GRPC_STATUS_OK;
}
static grpc_status_code gsec_aes_gcm_aead_crypter_decrypt_iovec(
gsec_aead_crypter* crypter, const uint8_t* nonce, size_t nonce_length,
const struct iovec* aad_vec, size_t aad_vec_length,
const struct iovec* ciphertext_vec, size_t ciphertext_vec_length,
struct iovec plaintext_vec, size_t* plaintext_bytes_written,
char** error_details) {
gsec_aes_gcm_aead_crypter* aes_gcm_crypter =
reinterpret_cast<gsec_aes_gcm_aead_crypter*>(
const_cast<gsec_aead_crypter*>(crypter));
if (nonce == nullptr) {
aes_gcm_format_errors("Nonce buffer is nullptr.", error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
if (kAesGcmNonceLength != nonce_length) {
aes_gcm_format_errors("Nonce buffer has the wrong length.", error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
if (aad_vec_length > 0 && aad_vec == nullptr) {
aes_gcm_format_errors("Non-zero aad_vec_length but aad_vec is nullptr.",
error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
if (ciphertext_vec_length > 0 && ciphertext_vec == nullptr) {
aes_gcm_format_errors(
"Non-zero plaintext_vec_length but plaintext_vec is nullptr.",
error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
// Compute the total length so we can ensure we don't pass the tag into
// EVP_decrypt.
size_t total_ciphertext_length = 0;
size_t i;
for (i = 0; i < ciphertext_vec_length; i++) {
total_ciphertext_length += ciphertext_vec[i].iov_len;
}
if (total_ciphertext_length < kAesGcmTagLength) {
aes_gcm_format_errors("ciphertext is too small to hold a tag.",
error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
if (plaintext_bytes_written == nullptr) {
aes_gcm_format_errors("bytes_written is nullptr.", error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
*plaintext_bytes_written = 0;
// rekey if required
if (aes_gcm_rekey_if_required(aes_gcm_crypter, nonce, error_details) !=
GRPC_STATUS_OK) {
aes_gcm_format_errors("Rekeying failed.", error_details);
return GRPC_STATUS_INTERNAL;
}
// mask nonce if required
const uint8_t* nonce_aead = nonce;
uint8_t nonce_masked[kAesGcmNonceLength];
if (aes_gcm_crypter->rekey_data != nullptr) {
aes_gcm_mask_nonce(nonce_masked, aes_gcm_crypter->rekey_data->nonce_mask,
nonce);
nonce_aead = nonce_masked;
}
// init openssl context
if (!EVP_DecryptInit_ex(aes_gcm_crypter->ctx, nullptr, nullptr, nullptr,
nonce_aead)) {
aes_gcm_format_errors("Initializing nonce failed.", error_details);
return GRPC_STATUS_INTERNAL;
}
// process aad
for (i = 0; i < aad_vec_length; i++) {
const uint8_t* aad = static_cast<uint8_t*>(aad_vec[i].iov_base);
size_t aad_length = aad_vec[i].iov_len;
if (aad_length == 0) {
continue;
}
size_t aad_bytes_read = 0;
if (aad == nullptr) {
aes_gcm_format_errors("aad is nullptr.", error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
if (!EVP_DecryptUpdate(aes_gcm_crypter->ctx, nullptr,
reinterpret_cast<int*>(&aad_bytes_read), aad,
static_cast<int>(aad_length)) ||
aad_bytes_read != aad_length) {
aes_gcm_format_errors("Setting authenticated associated data failed.",
error_details);
return GRPC_STATUS_INTERNAL;
}
}
// process ciphertext
uint8_t* plaintext = static_cast<uint8_t*>(plaintext_vec.iov_base);
size_t plaintext_length = plaintext_vec.iov_len;
if (plaintext_length > 0 && plaintext == nullptr) {
aes_gcm_format_errors(
"plaintext is nullptr, but plaintext_length is positive.",
error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
const uint8_t* ciphertext = nullptr;
size_t ciphertext_length = 0;
for (i = 0;
i < ciphertext_vec_length && total_ciphertext_length > kAesGcmTagLength;
i++) {
ciphertext = static_cast<uint8_t*>(ciphertext_vec[i].iov_base);
ciphertext_length = ciphertext_vec[i].iov_len;
if (ciphertext == nullptr) {
if (ciphertext_length == 0) {
continue;
}
aes_gcm_format_errors("ciphertext is nullptr.", error_details);
memset(plaintext_vec.iov_base, 0x00, plaintext_vec.iov_len);
return GRPC_STATUS_INVALID_ARGUMENT;
}
size_t bytes_written = 0;
size_t bytes_to_write = ciphertext_length;
// Don't include the tag
if (bytes_to_write > total_ciphertext_length - kAesGcmTagLength) {
bytes_to_write = total_ciphertext_length - kAesGcmTagLength;
}
if (plaintext_length < bytes_to_write) {
aes_gcm_format_errors(
"Not enough plaintext buffer to hold encrypted ciphertext.",
error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
if (!EVP_DecryptUpdate(aes_gcm_crypter->ctx, plaintext,
reinterpret_cast<int*>(&bytes_written), ciphertext,
static_cast<int>(bytes_to_write))) {
aes_gcm_format_errors("Decrypting ciphertext failed.", error_details);
memset(plaintext_vec.iov_base, 0x00, plaintext_vec.iov_len);
return GRPC_STATUS_INTERNAL;
}
if (bytes_written > ciphertext_length) {
aes_gcm_format_errors("More bytes written than expected.", error_details);
memset(plaintext_vec.iov_base, 0x00, plaintext_vec.iov_len);
return GRPC_STATUS_INTERNAL;
}
ciphertext += bytes_written;
ciphertext_length -= bytes_written;
total_ciphertext_length -= bytes_written;
plaintext += bytes_written;
plaintext_length -= bytes_written;
}
if (total_ciphertext_length > kAesGcmTagLength) {
aes_gcm_format_errors(
"Not enough plaintext buffer to hold encrypted ciphertext.",
error_details);
memset(plaintext_vec.iov_base, 0x00, plaintext_vec.iov_len);
return GRPC_STATUS_INVALID_ARGUMENT;
}
uint8_t tag[kAesGcmTagLength];
uint8_t* tag_tmp = tag;
if (ciphertext_length > 0) {
memcpy(tag_tmp, ciphertext, ciphertext_length);
tag_tmp += ciphertext_length;
total_ciphertext_length -= ciphertext_length;
}
for (; i < ciphertext_vec_length; i++) {
ciphertext = static_cast<uint8_t*>(ciphertext_vec[i].iov_base);
ciphertext_length = ciphertext_vec[i].iov_len;
if (ciphertext == nullptr) {
if (ciphertext_length == 0) {
continue;
}
aes_gcm_format_errors("ciphertext is nullptr.", error_details);
memset(plaintext_vec.iov_base, 0x00, plaintext_vec.iov_len);
return GRPC_STATUS_INVALID_ARGUMENT;
}
memcpy(tag_tmp, ciphertext, ciphertext_length);
tag_tmp += ciphertext_length;
total_ciphertext_length -= ciphertext_length;
}
if (!EVP_CIPHER_CTX_ctrl(aes_gcm_crypter->ctx, EVP_CTRL_GCM_SET_TAG,
kAesGcmTagLength, reinterpret_cast<void*>(tag))) {
aes_gcm_format_errors("Setting tag failed.", error_details);
memset(plaintext_vec.iov_base, 0x00, plaintext_vec.iov_len);
return GRPC_STATUS_INTERNAL;
}
int bytes_written_temp = 0;
if (!EVP_DecryptFinal_ex(aes_gcm_crypter->ctx, nullptr,
&bytes_written_temp)) {
aes_gcm_format_errors("Checking tag failed.", error_details);
memset(plaintext_vec.iov_base, 0x00, plaintext_vec.iov_len);
return GRPC_STATUS_FAILED_PRECONDITION;
}
if (bytes_written_temp != 0) {
aes_gcm_format_errors("Openssl wrote some unexpected bytes.",
error_details);
memset(plaintext_vec.iov_base, 0x00, plaintext_vec.iov_len);
return GRPC_STATUS_INTERNAL;
}
*plaintext_bytes_written = plaintext_vec.iov_len - plaintext_length;
return GRPC_STATUS_OK;
}
static void gsec_aes_gcm_aead_crypter_destroy(gsec_aead_crypter* crypter) {
gsec_aes_gcm_aead_crypter* aes_gcm_crypter =
reinterpret_cast<gsec_aes_gcm_aead_crypter*>(
const_cast<gsec_aead_crypter*>(crypter));
gpr_free(aes_gcm_crypter->key);
gpr_free(aes_gcm_crypter->rekey_data);
EVP_CIPHER_CTX_free(aes_gcm_crypter->ctx);
}
static const gsec_aead_crypter_vtable vtable = {
gsec_aes_gcm_aead_crypter_encrypt_iovec,
gsec_aes_gcm_aead_crypter_decrypt_iovec,
gsec_aes_gcm_aead_crypter_max_ciphertext_and_tag_length,
gsec_aes_gcm_aead_crypter_max_plaintext_length,
gsec_aes_gcm_aead_crypter_nonce_length,
gsec_aes_gcm_aead_crypter_key_length,
gsec_aes_gcm_aead_crypter_tag_length,
gsec_aes_gcm_aead_crypter_destroy};
static grpc_status_code aes_gcm_new_evp_cipher_ctx(
gsec_aes_gcm_aead_crypter* aes_gcm_crypter, char** error_details) {
const EVP_CIPHER* cipher = nullptr;
bool is_rekey = aes_gcm_crypter->rekey_data != nullptr;
switch (is_rekey ? kRekeyAeadKeyLen : aes_gcm_crypter->key_length) {
case kAes128GcmKeyLength:
cipher = EVP_aes_128_gcm();
break;
case kAes256GcmKeyLength:
cipher = EVP_aes_256_gcm();
break;
}
const uint8_t* aead_key = aes_gcm_crypter->key;
uint8_t aead_key_rekey[kRekeyAeadKeyLen];
if (is_rekey) {
if (aes_gcm_derive_aead_key(aead_key_rekey, aes_gcm_crypter->key,
aes_gcm_crypter->rekey_data->kdf_counter) !=
GRPC_STATUS_OK) {
aes_gcm_format_errors("Deriving key failed.", error_details);
return GRPC_STATUS_INTERNAL;
}
aead_key = aead_key_rekey;
}
if (!EVP_DecryptInit_ex(aes_gcm_crypter->ctx, cipher, nullptr, aead_key,
nullptr)) {
aes_gcm_format_errors("Setting key failed.", error_details);
return GRPC_STATUS_INTERNAL;
}
if (!EVP_CIPHER_CTX_ctrl(aes_gcm_crypter->ctx, EVP_CTRL_GCM_SET_IVLEN,
static_cast<int>(aes_gcm_crypter->nonce_length),
nullptr)) {
aes_gcm_format_errors("Setting nonce length failed.", error_details);
return GRPC_STATUS_INTERNAL;
}
return GRPC_STATUS_OK;
}
grpc_status_code gsec_aes_gcm_aead_crypter_create(const uint8_t* key,
size_t key_length,
size_t nonce_length,
size_t tag_length, bool rekey,
gsec_aead_crypter** crypter,
char** error_details) {
if (key == nullptr) {
aes_gcm_format_errors("key is nullptr.", error_details);
return GRPC_STATUS_FAILED_PRECONDITION;
}
if (crypter == nullptr) {
aes_gcm_format_errors("crypter is nullptr.", error_details);
return GRPC_STATUS_FAILED_PRECONDITION;
}
*crypter = nullptr;
if ((rekey && key_length != kAes128GcmRekeyKeyLength) ||
(!rekey && key_length != kAes128GcmKeyLength &&
key_length != kAes256GcmKeyLength) ||
(tag_length != kAesGcmTagLength) ||
(nonce_length != kAesGcmNonceLength)) {
aes_gcm_format_errors(
"Invalid key and/or nonce and/or tag length are provided at AEAD "
"crypter instance construction time.",
error_details);
return GRPC_STATUS_FAILED_PRECONDITION;
}
gsec_aes_gcm_aead_crypter* aes_gcm_crypter =
static_cast<gsec_aes_gcm_aead_crypter*>(
gpr_malloc(sizeof(gsec_aes_gcm_aead_crypter)));
aes_gcm_crypter->crypter.vtable = &vtable;
aes_gcm_crypter->nonce_length = nonce_length;
aes_gcm_crypter->tag_length = tag_length;
if (rekey) {
aes_gcm_crypter->key_length = kKdfKeyLen;
aes_gcm_crypter->rekey_data = static_cast<gsec_aes_gcm_aead_rekey_data*>(
gpr_malloc(sizeof(gsec_aes_gcm_aead_rekey_data)));
memcpy(aes_gcm_crypter->rekey_data->nonce_mask, key + kKdfKeyLen,
kAesGcmNonceLength);
// Set kdf_counter to all-zero for initial key derivation.
memset(aes_gcm_crypter->rekey_data->kdf_counter, 0, kKdfCounterLen);
} else {
aes_gcm_crypter->key_length = key_length;
aes_gcm_crypter->rekey_data = nullptr;
}
aes_gcm_crypter->key =
static_cast<uint8_t*>(gpr_malloc(aes_gcm_crypter->key_length));
memcpy(aes_gcm_crypter->key, key, aes_gcm_crypter->key_length);
aes_gcm_crypter->ctx = EVP_CIPHER_CTX_new();
grpc_status_code status =
aes_gcm_new_evp_cipher_ctx(aes_gcm_crypter, error_details);
if (status != GRPC_STATUS_OK) {
gsec_aes_gcm_aead_crypter_destroy(&aes_gcm_crypter->crypter);
gpr_free(aes_gcm_crypter);
return status;
}
*crypter = &aes_gcm_crypter->crypter;
return GRPC_STATUS_OK;
}

@ -0,0 +1,189 @@
/*
*
* Copyright 2018 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 <grpc/support/port_platform.h>
#include "src/core/tsi/alts/crypt/gsec.h"
#include <stdio.h>
#include <string.h>
#include <grpc/support/alloc.h>
static const char vtable_error_msg[] =
"crypter or crypter->vtable has not been initialized properly";
static void maybe_copy_error_msg(const char* src, char** dst) {
if (dst != nullptr && src != nullptr) {
*dst = static_cast<char*>(gpr_malloc(strlen(src) + 1));
memcpy(*dst, src, strlen(src) + 1);
}
}
grpc_status_code gsec_aead_crypter_encrypt(
gsec_aead_crypter* crypter, const uint8_t* nonce, size_t nonce_length,
const uint8_t* aad, size_t aad_length, const uint8_t* plaintext,
size_t plaintext_length, uint8_t* ciphertext_and_tag,
size_t ciphertext_and_tag_length, size_t* bytes_written,
char** error_details) {
if (crypter != nullptr && crypter->vtable != nullptr &&
crypter->vtable->encrypt_iovec != nullptr) {
struct iovec aad_vec = {(void*)aad, aad_length};
struct iovec plaintext_vec = {(void*)plaintext, plaintext_length};
struct iovec ciphertext_vec = {ciphertext_and_tag,
ciphertext_and_tag_length};
return crypter->vtable->encrypt_iovec(
crypter, nonce, nonce_length, &aad_vec, 1, &plaintext_vec, 1,
ciphertext_vec, bytes_written, error_details);
}
/* An error occurred. */
maybe_copy_error_msg(vtable_error_msg, error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
grpc_status_code gsec_aead_crypter_encrypt_iovec(
gsec_aead_crypter* crypter, const uint8_t* nonce, size_t nonce_length,
const struct iovec* aad_vec, size_t aad_vec_length,
const struct iovec* plaintext_vec, size_t plaintext_vec_length,
struct iovec ciphertext_vec, size_t* ciphertext_bytes_written,
char** error_details) {
if (crypter != nullptr && crypter->vtable != nullptr &&
crypter->vtable->encrypt_iovec != nullptr) {
return crypter->vtable->encrypt_iovec(
crypter, nonce, nonce_length, aad_vec, aad_vec_length, plaintext_vec,
plaintext_vec_length, ciphertext_vec, ciphertext_bytes_written,
error_details);
}
/* An error occurred. */
maybe_copy_error_msg(vtable_error_msg, error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
grpc_status_code gsec_aead_crypter_decrypt(
gsec_aead_crypter* crypter, const uint8_t* nonce, size_t nonce_length,
const uint8_t* aad, size_t aad_length, const uint8_t* ciphertext_and_tag,
size_t ciphertext_and_tag_length, uint8_t* plaintext,
size_t plaintext_length, size_t* bytes_written, char** error_details) {
if (crypter != nullptr && crypter->vtable != nullptr &&
crypter->vtable->decrypt_iovec != nullptr) {
struct iovec aad_vec = {(void*)aad, aad_length};
struct iovec ciphertext_vec = {(void*)ciphertext_and_tag,
ciphertext_and_tag_length};
struct iovec plaintext_vec = {plaintext, plaintext_length};
return crypter->vtable->decrypt_iovec(
crypter, nonce, nonce_length, &aad_vec, 1, &ciphertext_vec, 1,
plaintext_vec, bytes_written, error_details);
}
/* An error occurred. */
maybe_copy_error_msg(vtable_error_msg, error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
grpc_status_code gsec_aead_crypter_decrypt_iovec(
gsec_aead_crypter* crypter, const uint8_t* nonce, size_t nonce_length,
const struct iovec* aad_vec, size_t aad_vec_length,
const struct iovec* ciphertext_vec, size_t ciphertext_vec_length,
struct iovec plaintext_vec, size_t* plaintext_bytes_written,
char** error_details) {
if (crypter != nullptr && crypter->vtable != nullptr &&
crypter->vtable->encrypt_iovec != nullptr) {
return crypter->vtable->decrypt_iovec(
crypter, nonce, nonce_length, aad_vec, aad_vec_length, ciphertext_vec,
ciphertext_vec_length, plaintext_vec, plaintext_bytes_written,
error_details);
}
/* An error occurred. */
maybe_copy_error_msg(vtable_error_msg, error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
grpc_status_code gsec_aead_crypter_max_ciphertext_and_tag_length(
const gsec_aead_crypter* crypter, size_t plaintext_length,
size_t* max_ciphertext_and_tag_length_to_return, char** error_details) {
if (crypter != nullptr && crypter->vtable != nullptr &&
crypter->vtable->max_ciphertext_and_tag_length != nullptr) {
return crypter->vtable->max_ciphertext_and_tag_length(
crypter, plaintext_length, max_ciphertext_and_tag_length_to_return,
error_details);
}
/* An error occurred. */
maybe_copy_error_msg(vtable_error_msg, error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
grpc_status_code gsec_aead_crypter_max_plaintext_length(
const gsec_aead_crypter* crypter, size_t ciphertext_and_tag_length,
size_t* max_plaintext_length_to_return, char** error_details) {
if (crypter != nullptr && crypter->vtable != nullptr &&
crypter->vtable->max_plaintext_length != nullptr) {
return crypter->vtable->max_plaintext_length(
crypter, ciphertext_and_tag_length, max_plaintext_length_to_return,
error_details);
}
/* An error occurred. */
maybe_copy_error_msg(vtable_error_msg, error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
grpc_status_code gsec_aead_crypter_nonce_length(
const gsec_aead_crypter* crypter, size_t* nonce_length_to_return,
char** error_details) {
if (crypter != nullptr && crypter->vtable != nullptr &&
crypter->vtable->nonce_length != nullptr) {
return crypter->vtable->nonce_length(crypter, nonce_length_to_return,
error_details);
}
/* An error occurred. */
maybe_copy_error_msg(vtable_error_msg, error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
grpc_status_code gsec_aead_crypter_key_length(const gsec_aead_crypter* crypter,
size_t* key_length_to_return,
char** error_details) {
if (crypter != nullptr && crypter->vtable != nullptr &&
crypter->vtable->key_length != nullptr) {
return crypter->vtable->key_length(crypter, key_length_to_return,
error_details);
}
/* An error occurred */
maybe_copy_error_msg(vtable_error_msg, error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
grpc_status_code gsec_aead_crypter_tag_length(const gsec_aead_crypter* crypter,
size_t* tag_length_to_return,
char** error_details) {
if (crypter != nullptr && crypter->vtable != nullptr &&
crypter->vtable->tag_length != nullptr) {
return crypter->vtable->tag_length(crypter, tag_length_to_return,
error_details);
}
/* An error occurred. */
maybe_copy_error_msg(vtable_error_msg, error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
void gsec_aead_crypter_destroy(gsec_aead_crypter* crypter) {
if (crypter != nullptr) {
if (crypter->vtable != nullptr && crypter->vtable->destruct != nullptr) {
crypter->vtable->destruct(crypter);
}
gpr_free(crypter);
}
}

@ -0,0 +1,454 @@
/*
*
* Copyright 2018 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_CORE_TSI_ALTS_CRYPT_GSEC_H
#define GRPC_CORE_TSI_ALTS_CRYPT_GSEC_H
#include <grpc/support/port_platform.h>
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include <grpc/grpc.h>
struct iovec {
void* iov_base;
size_t iov_len;
};
/**
* A gsec interface for AEAD encryption schemes. The API is thread-compatible.
* Each implementation of this interface should specify supported values for
* key, nonce, and tag lengths.
*/
/* Key, nonce, and tag length in bytes */
const size_t kAesGcmNonceLength = 12;
const size_t kAesGcmTagLength = 16;
const size_t kAes128GcmKeyLength = 16;
const size_t kAes256GcmKeyLength = 32;
// The first 32 bytes are used as a KDF key and the remaining 12 bytes are used
// to mask the nonce.
const size_t kAes128GcmRekeyKeyLength = 44;
typedef struct gsec_aead_crypter gsec_aead_crypter;
/**
* The gsec_aead_crypter is an API for different AEAD implementations such as
* AES_GCM. It encapsulates all AEAD-related operations in the format of
* V-table that stores pointers to functions implementing those operations.
* It also provides helper functions to wrap each of those function pointers.
*
* A typical usage of this object would be:
*
*------------------------------------------------------------------------------
* // Declare a gsec_aead_crypter object, and create and assign an instance
* // of specific AEAD implementation e.g., AES_GCM to it. We assume both
* // key and nonce contain cryptographically secure random bytes, and the key
* // can be derived from an upper-layer application.
* gsec_aead_crypter* crypter;
* char* error_in_creation;
* // User can populate the message with any 100 bytes data.
* uint8_t* message = gpr_malloc(100);
* grpc_status_code creation_status = gsec_aes_gcm_aead_crypter_create(key,
* kAes128GcmKeyLength,
* kAesGcmNonceLength,
* kAesGcmTagLength,
* &crypter,
* false,
* 0
* &error_in_creation);
*
* if (creation_status == GRPC_STATUS_OK) {
* // Allocate a correct amount of memory to hold a ciphertext.
* size_t clength = 0;
* gsec_aead_crypter_max_ciphertext_and_tag_length(crypter, 100, &clength,
* nullptr);
* uint8_t* ciphertext = gpr_malloc(clength);
*
* // Perform encryption
* size_t num_encrypted_bytes = 0;
* char* error_in_encryption = nullptr;
* grpc_status_code status = gsec_aead_crypter_encrypt(crypter, nonce,
* kAesGcmNonceLength,
* nullptr, 0, message,
* 100, ciphertext,
* clength,
* &num_encrypted_bytes,
* &error_in_encryption);
* if (status == GRPC_STATUS_OK) {
* // Allocate a correct amount of memory to hold a plaintext.
* size_t plength = 0;
* gsec_aead_crypter_max_plaintext_length(crypter, num_encrypted_bytes,
* &plength, nullptr);
* uint8_t* plaintext = gpr_malloc(plength);
*
* // Perform decryption.
* size_t num_decrypted_bytes = 0;
* char* error_in_decryption = nullptr;
* status = gsec_aead_crypter_decrypt(crypter, nonce,
* kAesGcmNonceLength, nullptr, 0,
* ciphertext, num_encrypted_bytes,
* plaintext, plength,
* &num_decrypted_bytes,
* &error_in_decryption);
* if (status != GRPC_STATUS_OK) {
* fprintf(stderr, "AEAD decrypt operation failed with error code:"
* "%d, message: %s\n", status, error_in_decryption);
* }
* ...
* gpr_free(plaintext);
* gpr_free(error_in_decryption);
* } else {
* fprintf(stderr, "AEAD encrypt operation failed with error code:"
* "%d, message: %s\n", status, error_in_encryption);
* }
* ...
* gpr_free(ciphertext);
* gpr_free(error_in_encryption);
* } else {
* fprintf(stderr, "Creation of AEAD crypter instance failed with error code:"
* "%d, message: %s\n", creation_status, error_in_creation);
* }
*
* // Destruct AEAD crypter instance.
* if (creation_status == GRPC_STATUS_OK) {
* gsec_aead_crypter_destroy(crypter);
* }
* gpr_free(error_in_creation);
* gpr_free(message);
* -----------------------------------------------------------------------------
*/
/* V-table for gsec AEAD operations */
typedef struct gsec_aead_crypter_vtable {
grpc_status_code (*encrypt_iovec)(
gsec_aead_crypter* crypter, const uint8_t* nonce, size_t nonce_length,
const struct iovec* aad_vec, size_t aad_vec_length,
const struct iovec* plaintext_vec, size_t plaintext_vec_length,
struct iovec ciphertext_vec, size_t* ciphertext_bytes_written,
char** error_details);
grpc_status_code (*decrypt_iovec)(
gsec_aead_crypter* crypter, const uint8_t* nonce, size_t nonce_length,
const struct iovec* aad_vec, size_t aad_vec_length,
const struct iovec* ciphertext_vec, size_t ciphertext_vec_length,
struct iovec plaintext_vec, size_t* plaintext_bytes_written,
char** error_details);
grpc_status_code (*max_ciphertext_and_tag_length)(
const gsec_aead_crypter* crypter, size_t plaintext_length,
size_t* max_ciphertext_and_tag_length_to_return, char** error_details);
grpc_status_code (*max_plaintext_length)(
const gsec_aead_crypter* crypter, size_t ciphertext_and_tag_length,
size_t* max_plaintext_length_to_return, char** error_details);
grpc_status_code (*nonce_length)(const gsec_aead_crypter* crypter,
size_t* nonce_length_to_return,
char** error_details);
grpc_status_code (*key_length)(const gsec_aead_crypter* crypter,
size_t* key_length_to_return,
char** error_details);
grpc_status_code (*tag_length)(const gsec_aead_crypter* crypter,
size_t* tag_length_to_return,
char** error_details);
void (*destruct)(gsec_aead_crypter* crypter);
} gsec_aead_crypter_vtable;
/* Main struct for gsec interface */
struct gsec_aead_crypter {
const struct gsec_aead_crypter_vtable* vtable;
};
/**
* This method performs an AEAD encrypt operation.
*
* - crypter: AEAD crypter instance.
* - nonce: buffer containing a nonce with its size equal to nonce_length.
* - nonce_length: size of nonce buffer, and must be equal to the value returned
* from method gsec_aead_crypter_nonce_length.
* - aad: buffer containing data that needs to be authenticated but not
* encrypted with its size equal to aad_length.
* - aad_length: size of aad buffer, which should be zero if the buffer is
* nullptr.
* - plaintext: buffer containing data that needs to be both encrypted and
* authenticated with its size equal to plaintext_length.
* - plaintext_length: size of plaintext buffer, which should be zero if
* plaintext is nullptr.
* - ciphertext_and_tag: buffer that will contain ciphertext and tags the method
* produced. The buffer should not overlap the plaintext buffer, and pointers
* to those buffers should not be equal. Also if the ciphertext+tag buffer is
* nullptr, the plaintext_length should be zero.
* - ciphertext_and_tag_length: size of ciphertext+tag buffer, which should be
* at least as long as the one returned from method
* gsec_aead_crypter_max_ciphertext_and_tag_length.
* - bytes_written: the actual number of bytes written to the ciphertext+tag
* buffer. If bytes_written is nullptr, the plaintext_length should be zero.
* - error_details: a buffer containing an error message if the method does not
* function correctly. It is legal to pass nullptr into error_details, and
* otherwise, the parameter should be freed with gpr_free.
*
* On the success of encryption, the method returns GRPC_STATUS_OK. Otherwise,
* it returns an error status code along with its details specified in
* error_details (if error_details is not nullptr).
*
*/
grpc_status_code gsec_aead_crypter_encrypt(
gsec_aead_crypter* crypter, const uint8_t* nonce, size_t nonce_length,
const uint8_t* aad, size_t aad_length, const uint8_t* plaintext,
size_t plaintext_length, uint8_t* ciphertext_and_tag,
size_t ciphertext_and_tag_length, size_t* bytes_written,
char** error_details);
/**
* This method performs an AEAD encrypt operation.
*
* - crypter: AEAD crypter instance.
* - nonce: buffer containing a nonce with its size equal to nonce_length.
* - nonce_length: size of nonce buffer, and must be equal to the value returned
* from method gsec_aead_crypter_nonce_length.
* - aad_vec: an iovec array containing data that needs to be authenticated but
* not encrypted.
* - aad_vec_length: the array length of aad_vec.
* - plaintext_vec: an iovec array containing data that needs to be both
* encrypted and authenticated.
* - plaintext_vec_length: the array length of plaintext_vec.
* - ciphertext_vec: an iovec containing a ciphertext buffer. The buffer should
* not overlap the plaintext buffer.
* - ciphertext_bytes_written: the actual number of bytes written to
* ciphertext_vec.
* - error_details: a buffer containing an error message if the method does not
* function correctly. It is legal to pass nullptr into error_details, and
* otherwise, the parameter should be freed with gpr_free.
*
* On the success of encryption, the method returns GRPC_STATUS_OK. Otherwise,
* it returns an error status code along with its details specified in
* error_details (if error_details is not nullptr).
*
*/
grpc_status_code gsec_aead_crypter_encrypt_iovec(
gsec_aead_crypter* crypter, const uint8_t* nonce, size_t nonce_length,
const struct iovec* aad_vec, size_t aad_vec_length,
const struct iovec* plaintext_vec, size_t plaintext_vec_length,
struct iovec ciphertext_vec, size_t* ciphertext_bytes_written,
char** error_details);
/**
* This method performs an AEAD decrypt operation.
*
* - crypter: AEAD crypter instance.
* - nonce: buffer containing a nonce with its size equal to nonce_length.
* - nonce_length: size of nonce buffer, and must be equal to the value returned
* from method gsec_aead_crypter_nonce_length.
* - aad: buffer containing data that needs to be authenticated only.
* - aad_length: size of aad buffer, which should be zero if the buffer is
* nullptr.
* - ciphertext_and_tag: buffer containing ciphertext and tag.
* - ciphertext_and_tag_length: length of ciphertext and tag. It should be zero
* if any of plaintext, ciphertext_and_tag, or bytes_written is nullptr. Also,
* ciphertext_and_tag_length should be at least as large as the tag length set
* at AEAD crypter instance construction time.
* - plaintext: buffer containing decrypted and authenticated data the method
* produced. The buffer should not overlap with the ciphertext+tag buffer, and
* pointers to those buffers should not be equal.
* - plaintext_length: size of plaintext buffer, which should be at least as
* long as the one returned from gsec_aead_crypter_max_plaintext_length
* method.
* - bytes_written: the actual number of bytes written to the plaintext
* buffer.
* - error_details: a buffer containing an error message if the method does not
* function correctly. It is legal to pass nullptr into error_details, and
* otherwise, the parameter should be freed with gpr_free.
*
* On the success of decryption, the method returns GRPC_STATUS_OK. Otherwise,
* it returns an error status code along with its details specified in
* error_details (if error_details is not nullptr).
*/
grpc_status_code gsec_aead_crypter_decrypt(
gsec_aead_crypter* crypter, const uint8_t* nonce, size_t nonce_length,
const uint8_t* aad, size_t aad_length, const uint8_t* ciphertext_and_tag,
size_t ciphertext_and_tag_length, uint8_t* plaintext,
size_t plaintext_length, size_t* bytes_written, char** error_details);
/**
* This method performs an AEAD decrypt operation.
*
* - crypter: AEAD crypter instance.
* - nonce: buffer containing a nonce with its size equal to nonce_length.
* - nonce_length: size of nonce buffer, and must be equal to the value returned
* from method gsec_aead_crypter_nonce_length.
* - aad_vec: an iovec array containing data that needs to be authenticated but
* not encrypted.
* - aad_vec_length: the array length of aad_vec.
* - ciphertext_vec: an iovec array containing the ciphertext and tag.
* - ciphertext_vec_length: the array length of ciphertext_vec.
* - plaintext_vec: an iovec containing a plaintext buffer. The buffer should
* not overlap the ciphertext buffer.
* - plaintext_bytes_written: the actual number of bytes written to
* plaintext_vec.
* - error_details: a buffer containing an error message if the method does not
* function correctly. It is legal to pass nullptr into error_details, and
* otherwise, the parameter should be freed with gpr_free.
*
* On the success of decryption, the method returns GRPC_STATUS_OK. Otherwise,
* it returns an error status code along with its details specified in
* error_details (if error_details is not nullptr).
*/
grpc_status_code gsec_aead_crypter_decrypt_iovec(
gsec_aead_crypter* crypter, const uint8_t* nonce, size_t nonce_length,
const struct iovec* aad_vec, size_t aad_vec_length,
const struct iovec* ciphertext_vec, size_t ciphertext_vec_length,
struct iovec plaintext_vec, size_t* plaintext_bytes_written,
char** error_details);
/**
* This method computes the size of ciphertext+tag buffer that must be passed to
* gsec_aead_crypter_encrypt function to ensure correct encryption of a
* plaintext. The actual size of ciphertext+tag written to the buffer could be
* smaller.
*
* - crypter: AEAD crypter instance.
* - plaintext_length: length of plaintext.
* - max_ciphertext_and_tag_length_to_return: the size of ciphertext+tag buffer
* the method returns.
* - error_details: a buffer containing an error message if the method does not
* function correctly. It is legal to pass nullptr into error_details, and
* otherwise, the parameter should be freed with gpr_free.
*
* On the success of execution, the method returns GRPC_STATUS_OK. Otherwise,
* it returns an error status code along with its details specified in
* error_details (if error_details is not nullptr).
*/
grpc_status_code gsec_aead_crypter_max_ciphertext_and_tag_length(
const gsec_aead_crypter* crypter, size_t plaintext_length,
size_t* max_ciphertext_and_tag_length_to_return, char** error_details);
/**
* This method computes the size of plaintext buffer that must be passed to
* gsec_aead_crypter_decrypt function to ensure correct decryption of a
* ciphertext. The actual size of plaintext written to the buffer could be
* smaller.
*
* - crypter: AEAD crypter instance.
* - ciphertext_and_tag_length: length of ciphertext and tag.
* - max_plaintext_length_to_return: the size of plaintext buffer the method
* returns.
* - error_details: a buffer containing an error message if the method does not
* function correctly. It is legal to pass nullptr into error_details, and
* otherwise, the parameter should be freed with gpr_free.
*
* On the success of execution, the method returns GRPC_STATUS_OK. Otherwise,
* it returns an error status code along with its details specified in
* error_details (if error_details is not nullptr).
*/
grpc_status_code gsec_aead_crypter_max_plaintext_length(
const gsec_aead_crypter* crypter, size_t ciphertext_and_tag_length,
size_t* max_plaintext_length_to_return, char** error_details);
/**
* This method returns a valid size of nonce array used at the construction of
* AEAD crypter instance. It is also the size that should be passed to encrypt
* and decrypt methods executed on the instance.
*
* - crypter: AEAD crypter instance.
* - nonce_length_to_return: the length of nonce array the method returns.
* - error_details: a buffer containing an error message if the method does not
* function correctly. It is legal to pass nullptr into error_details, and
* otherwise, the parameter should be freed with gpr_free.
*
* On the success of execution, the method returns GRPC_STATUS_OK. Otherwise,
* it returns an error status code along with its details specified in
* error_details (if error_details is not nullptr).
*/
grpc_status_code gsec_aead_crypter_nonce_length(
const gsec_aead_crypter* crypter, size_t* nonce_length_to_return,
char** error_details);
/**
* This method returns a valid size of key array used at the construction of
* AEAD crypter instance. It is also the size that should be passed to encrypt
* and decrypt methods executed on the instance.
*
* - crypter: AEAD crypter instance.
* - key_length_to_return: the length of key array the method returns.
* - error_details: a buffer containing an error message if the method does not
* function correctly. It is legal to pass nullptr into error_details, and
* otherwise, the parameter should be freed with gpr_free.
*
* On the success of execution, the method returns GRPC_STATUS_OK. Otherwise,
* it returns an error status code along with its details specified in
* error_details (if error_details is not nullptr).
*/
grpc_status_code gsec_aead_crypter_key_length(const gsec_aead_crypter* crypter,
size_t* key_length_to_return,
char** error_details);
/**
* This method returns a valid size of tag array used at the construction of
* AEAD crypter instance. It is also the size that should be passed to encrypt
* and decrypt methods executed on the instance.
*
* - crypter: AEAD crypter instance.
* - tag_length_to_return: the length of tag array the method returns.
* - error_details: a buffer containing an error message if the method does not
* function correctly. It is legal to pass nullptr into error_details, and
* otherwise, the parameter should be freed with gpr_free.
*
* On the success of execution, the method returns GRPC_STATUS_OK. Otherwise,
* it returns an error status code along with its details specified in
* error_details (if error_details is not nullptr).
*/
grpc_status_code gsec_aead_crypter_tag_length(const gsec_aead_crypter* crypter,
size_t* tag_length_to_return,
char** error_details);
/**
* This method destroys an AEAD crypter instance by de-allocating all of its
* occupied memory.
*
* - crypter: AEAD crypter instance that needs to be destroyed.
*/
void gsec_aead_crypter_destroy(gsec_aead_crypter* crypter);
/**
* This method creates an AEAD crypter instance of AES-GCM encryption scheme
* which supports 16 and 32 bytes long keys, 12 and 16 bytes long nonces, and
* 16 bytes long tags. It should be noted that once the lengths of key, nonce,
* and tag are determined at construction time, they cannot be modified later.
*
* - key: buffer containing a key which is binded with AEAD crypter instance.
* - key_length: length of a key in bytes, which should be 44 if rekeying is
* enabled and 16 or 32 otherwise.
* - nonce_length: length of a nonce in bytes, which should be either 12 or 16.
* - tag_length: length of a tag in bytes, which should be always 16.
* - rekey: enable nonce-based rekeying and nonce-masking.
* - crypter: address of AES_GCM crypter instance returned from the method.
* - error_details: a buffer containing an error message if the method does not
* function correctly. It is legal to pass nullptr into error_details, and
* otherwise, the parameter should be freed with gpr_free.
*
* On success of instance creation, it stores the address of instance at
* crypter. Otherwise, it returns an error status code together with its details
* specified in error_details.
*/
grpc_status_code gsec_aes_gcm_aead_crypter_create(const uint8_t* key,
size_t key_length,
size_t nonce_length,
size_t tag_length, bool rekey,
gsec_aead_crypter** crypter,
char** error_details);
#endif /* GRPC_CORE_TSI_ALTS_CRYPT_GSEC_H */

@ -0,0 +1,118 @@
/*
*
* Copyright 2018 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 <grpc/support/port_platform.h>
#include "src/core/tsi/alts/frame_protector/alts_counter.h"
#include <string.h>
#include <grpc/support/alloc.h>
static void maybe_copy_error_msg(const char* src, char** dst) {
if (dst != nullptr && src != nullptr) {
*dst = static_cast<char*>(gpr_malloc(strlen(src) + 1));
memcpy(*dst, src, strlen(src) + 1);
}
}
grpc_status_code alts_counter_create(bool is_client, size_t counter_size,
size_t overflow_size,
alts_counter** crypter_counter,
char** error_details) {
/* Perform input sanity check. */
if (counter_size == 0) {
const char error_msg[] = "counter_size is invalid.";
maybe_copy_error_msg(error_msg, error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
if (overflow_size == 0 || overflow_size >= counter_size) {
const char error_msg[] = "overflow_size is invalid.";
maybe_copy_error_msg(error_msg, error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
if (crypter_counter == nullptr) {
const char error_msg[] = "crypter_counter is nullptr.";
maybe_copy_error_msg(error_msg, error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
*crypter_counter =
static_cast<alts_counter*>(gpr_malloc(sizeof(**crypter_counter)));
(*crypter_counter)->size = counter_size;
(*crypter_counter)->overflow_size = overflow_size;
(*crypter_counter)->counter =
static_cast<unsigned char*>(gpr_zalloc(counter_size));
if (is_client) {
((*crypter_counter)->counter)[counter_size - 1] = 0x80;
}
return GRPC_STATUS_OK;
}
grpc_status_code alts_counter_increment(alts_counter* crypter_counter,
bool* is_overflow,
char** error_details) {
/* Perform input sanity check. */
if (crypter_counter == nullptr) {
const char error_msg[] = "crypter_counter is nullptr.";
maybe_copy_error_msg(error_msg, error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
if (is_overflow == nullptr) {
const char error_msg[] = "is_overflow is nullptr.";
maybe_copy_error_msg(error_msg, error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
/* Increment the internal counter. */
size_t i = 0;
for (; i < crypter_counter->overflow_size; i++) {
(crypter_counter->counter)[i]++;
if ((crypter_counter->counter)[i] != 0x00) {
break;
}
}
/**
* If the lower overflow_size bytes are all zero, the counter has overflowed.
*/
if (i == crypter_counter->overflow_size) {
*is_overflow = true;
return GRPC_STATUS_FAILED_PRECONDITION;
}
*is_overflow = false;
return GRPC_STATUS_OK;
}
size_t alts_counter_get_size(alts_counter* crypter_counter) {
if (crypter_counter == nullptr) {
return 0;
}
return crypter_counter->size;
}
unsigned char* alts_counter_get_counter(alts_counter* crypter_counter) {
if (crypter_counter == nullptr) {
return nullptr;
}
return crypter_counter->counter;
}
void alts_counter_destroy(alts_counter* crypter_counter) {
if (crypter_counter != nullptr) {
gpr_free(crypter_counter->counter);
gpr_free(crypter_counter);
}
}

@ -0,0 +1,98 @@
/*
*
* Copyright 2018 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_CORE_TSI_ALTS_FRAME_PROTECTOR_ALTS_COUNTER_H
#define GRPC_CORE_TSI_ALTS_FRAME_PROTECTOR_ALTS_COUNTER_H
#include <grpc/support/port_platform.h>
#include <stdbool.h>
#include <stdlib.h>
#include <grpc/grpc.h>
/* Main struct for a crypter counter managed within seal/unseal operations. */
typedef struct alts_counter {
size_t size;
size_t overflow_size;
unsigned char* counter;
} alts_counter;
/**
* This method creates and initializes an alts_counter instance.
*
* - is_client: a flag indicating if the alts_counter instance will be used
* at client (is_client = true) or server (is_client = false) side.
* - counter_size: size of buffer holding the counter value.
* - overflow_size: overflow size in bytes. The counter instance can be used
* to produce at most 2^(overflow_size*8) frames.
* - crypter_counter: an alts_counter instance to be returned from the method.
* - error_details: a buffer containing an error message if the method does not
* function correctly. It is legal to pass nullptr into error_details and
* otherwise, the parameter should be freed with gpr_free.
*
* On success, the method returns GRPC_STATUS_OK. Otherwise,
* it returns an error status code along with its details specified in
* error_details (if error_details is not nullptr).
*/
grpc_status_code alts_counter_create(bool is_client, size_t counter_size,
size_t overflow_size,
alts_counter** crypter_counter,
char** error_details);
/**
* This method increments the internal counter.
*
* - crypter_counter: an alts_counter instance.
* - is_overflow: after incrementing the internal counter, if an overflow
* occurs, is_overflow is set to true, and no further calls to
* alts_counter_increment() should be made. Otherwise, is_overflow is set to
* false.
* - error_details: a buffer containing an error message if the method does not
* function correctly. It is legal to pass nullptr into error_details and
* otherwise, the parameter should be freed with gpr_free.
*
* On success, the method returns GRPC_STATUS_OK. Otherwise,
* it returns an error status code along with its details specified in
* error_details (if error_details is not nullptr).
*/
grpc_status_code alts_counter_increment(alts_counter* crypter_counter,
bool* is_overflow,
char** error_details);
/**
* This method returns the size of counter buffer.
*
* - crypter_counter: an alts_counter instance.
*/
size_t alts_counter_get_size(alts_counter* crypter_counter);
/**
* This method returns the counter buffer.
*
* - crypter_counter: an alts_counter instance.
*/
unsigned char* alts_counter_get_counter(alts_counter* crypter_counter);
/**
* This method de-allocates all memory allocated to an alts_coutner instance.
* - crypter_counter: an alts_counter instance.
*/
void alts_counter_destroy(alts_counter* crypter_counter);
#endif /* GRPC_CORE_TSI_ALTS_FRAME_PROTECTOR_ALTS_COUNTER_H */

@ -0,0 +1,66 @@
/*
*
* Copyright 2018 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 <grpc/support/port_platform.h>
#include "src/core/tsi/alts/frame_protector/alts_crypter.h"
#include <string.h>
#include <grpc/support/alloc.h>
static void maybe_copy_error_msg(const char* src, char** dst) {
if (dst != nullptr && src != nullptr) {
*dst = static_cast<char*>(gpr_malloc(strlen(src) + 1));
memcpy(*dst, src, strlen(src) + 1);
}
}
grpc_status_code alts_crypter_process_in_place(
alts_crypter* crypter, unsigned char* data, size_t data_allocated_size,
size_t data_size, size_t* output_size, char** error_details) {
if (crypter != nullptr && crypter->vtable != nullptr &&
crypter->vtable->process_in_place != nullptr) {
return crypter->vtable->process_in_place(crypter, data, data_allocated_size,
data_size, output_size,
error_details);
}
/* An error occurred. */
const char error_msg[] =
"crypter or crypter->vtable has not been initialized properly.";
maybe_copy_error_msg(error_msg, error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
size_t alts_crypter_num_overhead_bytes(const alts_crypter* crypter) {
if (crypter != nullptr && crypter->vtable != nullptr &&
crypter->vtable->num_overhead_bytes != nullptr) {
return crypter->vtable->num_overhead_bytes(crypter);
}
/* An error occurred. */
return 0;
}
void alts_crypter_destroy(alts_crypter* crypter) {
if (crypter != nullptr) {
if (crypter->vtable != nullptr && crypter->vtable->destruct != nullptr) {
crypter->vtable->destruct(crypter);
}
gpr_free(crypter);
}
}

@ -0,0 +1,255 @@
/*
*
* Copyright 2018 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_CORE_TSI_ALTS_FRAME_PROTECTOR_ALTS_CRYPTER_H
#define GRPC_CORE_TSI_ALTS_FRAME_PROTECTOR_ALTS_CRYPTER_H
#include <grpc/support/port_platform.h>
#include <stdbool.h>
#include <string.h>
#include <grpc/grpc.h>
#include "src/core/tsi/alts/crypt/gsec.h"
/**
* An alts_crypter interface for an ALTS record protocol providing
* seal/unseal functionality. The interface is thread-compatible.
*/
typedef struct alts_crypter alts_crypter;
/**
* A typical usage of the interface would be
*------------------------------------------------------------------------------
* // Perform a seal operation. We assume the gsec_aead_crypter instance -
* // client_aead_crypter is created beforehand with a 16-byte key and 12-byte
* // nonce length.
*
* alts_crypter* client = nullptr;
* char* client_error_in_creation = nullptr;
* unsigned char* data = nullptr;
* grpc_status_code client_status =
* alts_seal_crypter_create(client_aead_crypter, 1, 5, &client,
* &client_error_in_creation);
* if (client_status == GRPC_STATUS_OK) {
* size_t data_size = 100;
* size_t num_overhead_bytes = alts_crypter_num_overhead_bytes(client);
* size_t data_allocated_size = data_size + num_overhead_bytes;
* data = gpr_malloc(data_allocated_size);
* char* client_error_in_seal = nullptr;
* // Client performs a seal operation.
* client_status = alts_crypter_process_in_place(client, data,
* data_allocated_size,
* &data_size,
* &client_error_in_seal);
* if (client_status != GRPC_STATUS_OK) {
* fprintf(stderr, "seal operation failed with error code:"
* "%d, message: %s\n", client_status,
* client_error_in_seal);
* }
* gpr_free(client_error_in_seal);
* } else {
* fprintf(stderr, "alts_crypter instance creation failed with error"
* "code: %d, message: %s\n", client_status,
* client_error_in_creation);
* }
*
* ...
*
* gpr_free(client_error_in_creation);
* alts_crypter_destroy(client);
*
* ...
*
* // Perform an unseal operation. We assume the gsec_aead_crypter instance -
* // server_aead_crypter is created beforehand with a 16-byte key and 12-byte
* // nonce length. The key used in the creation of gsec_aead_crypter instances
* // at server and client sides should be identical.
*
* alts_crypter* server = nullptr;
* char* server_error_in_creation = nullptr;
* grpc_status_code server_status =
* alts_unseal_crypter_create(server_aead_crypter, 0, 5, &server,
* &server_error_in_creation);
* if (server_status == GRPC_STATUS_OK) {
* size_t num_overhead_bytes = alts_crypter_num_overhead_bytes(server);
* size_t data_size = 100 + num_overhead_bytes;
* size_t data_allocated_size = data_size;
* char* server_error_in_unseal = nullptr;
* // Server performs an unseal operation.
* server_status = alts_crypter_process_in_place(server, data,
* data_allocated_size,
* &data_size,
* &server_error_in_unseal);
* if (server_status != GRPC_STATUS_OK) {
* fprintf(stderr, "unseal operation failed with error code:"
* "%d, message: %s\n", server_status,
* server_error_in_unseal);
* }
* gpr_free(server_error_in_unseal);
* } else {
* fprintf(stderr, "alts_crypter instance creation failed with error"
* "code: %d, message: %s\n", server_status,
* server_error_in_creation);
* }
*
* ...
*
* gpr_free(data);
* gpr_free(server_error_in_creation);
* alts_crypter_destroy(server);
*
* ...
*------------------------------------------------------------------------------
*/
/* V-table for alts_crypter operations */
typedef struct alts_crypter_vtable {
size_t (*num_overhead_bytes)(const alts_crypter* crypter);
grpc_status_code (*process_in_place)(alts_crypter* crypter,
unsigned char* data,
size_t data_allocated_size,
size_t data_size, size_t* output_size,
char** error_details);
void (*destruct)(alts_crypter* crypter);
} alts_crypter_vtable;
/* Main struct for alts_crypter interface */
struct alts_crypter {
const alts_crypter_vtable* vtable;
};
/**
* This method gets the number of overhead bytes needed for sealing data that
* is the difference in size between the protected and raw data. The counter
* value used in a seal or unseal operation is locally maintained (not sent or
* received from the other peer) and therefore, will not be counted as part of
* overhead bytes.
*
* - crypter: an alts_crypter instance.
*
* On success, the method returns the number of overhead bytes. Otherwise, it
* returns zero.
*
*/
size_t alts_crypter_num_overhead_bytes(const alts_crypter* crypter);
/**
* This method performs either a seal or an unseal operation depending on the
* alts_crypter instance - crypter passed to the method. If the crypter is
* an instance implementing a seal operation, the method will perform a seal
* operation. That is, it seals raw data and stores the result in-place, and the
* memory allocated for data must be at least data_length +
* alts_crypter_num_overhead_bytes(). If the crypter is an instance
* implementing an unseal operation, the method will perform an unseal
* operation. That is, it unseals protected data and stores the result in-place.
* The size of unsealed data will be data_length -
* alts_crypter_num_overhead_bytes(). Integrity tag will be verified during
* the unseal operation, and if verification fails, the data will be wiped.
* The counters used in both seal and unseal operations are managed internally.
*
* - crypter: an alts_crypter instance.
* - data: if the method performs a seal operation, the data represents raw data
* that needs to be sealed. It also plays the role of buffer to hold the
* protected data as a result of seal. If the method performs an unseal
* operation, the data represents protected data that needs to be unsealed. It
* also plays the role of buffer to hold raw data as a result of unseal.
* - data_allocated_size: the size of data buffer. The parameter is used to
* check whether the result of either seal or unseal can be safely written to
* the data buffer.
* - data_size: if the method performs a seal operation, data_size
* represents the size of raw data that needs to be sealed, and if the method
* performs an unseal operation, data_size represents the size of protected
* data that needs to be unsealed.
* - output_size: size of data written to the data buffer after a seal or an
* unseal operation.
* - error_details: a buffer containing an error message if the method does not
* function correctly. It is legal to pass nullptr into error_details and
* otherwise, the parameter should be freed with gpr_free.
*
* On success, the method returns GRPC_STATUS_OK. Otherwise,
* it returns an error status code along with its details specified in
* error_details (if error_details is not nullptr).
*/
grpc_status_code alts_crypter_process_in_place(
alts_crypter* crypter, unsigned char* data, size_t data_allocated_size,
size_t data_size, size_t* output_size, char** error_details);
/**
* This method creates an alts_crypter instance to be used to perform a seal
* operation, given a gsec_aead_crypter instance and a flag indicating if the
* created instance will be used at the client or server side. It takes
* ownership of gsec_aead_crypter instance.
*
* - gc: a gsec_aead_crypter instance used to perform AEAD encryption.
* - is_client: a flag indicating if the alts_crypter instance will be
* used at the client (is_client = true) or server (is_client =
* false) side.
* - overflow_size: overflow size of counter in bytes.
* - crypter: an alts_crypter instance to be returned from the method.
* - error_details: a buffer containing an error message if the method does
* not function correctly. It is legal to pass nullptr into error_details, and
* otherwise, the parameter should be freed with gpr_free.
*
* On success of creation, the method returns GRPC_STATUS_OK.
* Otherwise, it returns an error status code along with its details specified
* in error_details (if error_details is not nullptr).
*/
grpc_status_code alts_seal_crypter_create(gsec_aead_crypter* gc, bool is_client,
size_t overflow_size,
alts_crypter** crypter,
char** error_details);
/**
* This method creates an alts_crypter instance used to perform an unseal
* operation, given a gsec_aead_crypter instance and a flag indicating if the
* created instance will be used at the client or server side. It takes
* ownership of gsec_aead_crypter instance.
*
* - gc: a gsec_aead_crypter instance used to perform AEAD decryption.
* - is_client: a flag indicating if the alts_crypter instance will be
* used at the client (is_client = true) or server (is_client =
* false) side.
* - overflow_size: overflow size of counter in bytes.
* - crypter: an alts_crypter instance to be returned from the method.
* - error_details: a buffer containing an error message if the method does
* not function correctly. It is legal to pass nullptr into error_details, and
* otherwise, the parameter should be freed with gpr_free.
*
* On success of creation, the method returns GRPC_STATUS_OK.
* Otherwise, it returns an error status code along with its details specified
* in error_details (if error_details is not nullptr).
*/
grpc_status_code alts_unseal_crypter_create(gsec_aead_crypter* gc,
bool is_client,
size_t overflow_size,
alts_crypter** crypter,
char** error_details);
/**
* This method destroys an alts_crypter instance by de-allocating all of its
* occupied memory. A gsec_aead_crypter instance passed in at alts_crypter
* instance creation time will be destroyed in this method.
*
* - crypter: an alts_crypter instance.
*/
void alts_crypter_destroy(alts_crypter* crypter);
#endif /* GRPC_CORE_TSI_ALTS_FRAME_PROTECTOR_ALTS_CRYPTER_H */

@ -0,0 +1,407 @@
/*
*
* Copyright 2018 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 <grpc/support/port_platform.h>
#include "src/core/tsi/alts/frame_protector/alts_frame_protector.h"
#include <stdio.h>
#include <stdlib.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "src/core/lib/gpr/useful.h"
#include "src/core/tsi/alts/crypt/gsec.h"
#include "src/core/tsi/alts/frame_protector/alts_crypter.h"
#include "src/core/tsi/alts/frame_protector/frame_handler.h"
#include "src/core/tsi/transport_security.h"
constexpr size_t kMinFrameLength = 1024;
constexpr size_t kDefaultFrameLength = 16 * 1024;
constexpr size_t kMaxFrameLength = 1024 * 1024;
// Limit k on number of frames such that at most 2^(8 * k) frames can be sent.
constexpr size_t kAltsRecordProtocolRekeyFrameLimit = 8;
constexpr size_t kAltsRecordProtocolFrameLimit = 5;
/* Main struct for alts_frame_protector. */
struct alts_frame_protector {
tsi_frame_protector base;
alts_crypter* seal_crypter;
alts_crypter* unseal_crypter;
alts_frame_writer* writer;
alts_frame_reader* reader;
unsigned char* in_place_protect_buffer;
unsigned char* in_place_unprotect_buffer;
size_t in_place_protect_bytes_buffered;
size_t in_place_unprotect_bytes_processed;
size_t max_protected_frame_size;
size_t max_unprotected_frame_size;
size_t overhead_length;
size_t counter_overflow;
};
static tsi_result seal(alts_frame_protector* impl) {
char* error_details = nullptr;
size_t output_size = 0;
grpc_status_code status = alts_crypter_process_in_place(
impl->seal_crypter, impl->in_place_protect_buffer,
impl->max_protected_frame_size, impl->in_place_protect_bytes_buffered,
&output_size, &error_details);
impl->in_place_protect_bytes_buffered = output_size;
if (status != GRPC_STATUS_OK) {
gpr_log(GPR_ERROR, "%s", error_details);
gpr_free(error_details);
return TSI_INTERNAL_ERROR;
}
return TSI_OK;
}
static size_t max_encrypted_payload_bytes(alts_frame_protector* impl) {
return impl->max_protected_frame_size - kFrameHeaderSize;
}
static tsi_result alts_protect_flush(tsi_frame_protector* self,
unsigned char* protected_output_frames,
size_t* protected_output_frames_size,
size_t* still_pending_size) {
if (self == nullptr || protected_output_frames == nullptr ||
protected_output_frames_size == nullptr ||
still_pending_size == nullptr) {
gpr_log(GPR_ERROR, "Invalid nullptr arguments to alts_protect_flush().");
return TSI_INVALID_ARGUMENT;
}
alts_frame_protector* impl = reinterpret_cast<alts_frame_protector*>(self);
/**
* If there's nothing to flush (i.e., in_place_protect_buffer is empty),
* we're done.
*/
if (impl->in_place_protect_bytes_buffered == 0) {
*protected_output_frames_size = 0;
*still_pending_size = 0;
return TSI_OK;
}
/**
* If a new frame can start being processed, we encrypt the payload and reset
* the frame writer to point to in_place_protect_buffer that holds the newly
* sealed frame.
*/
if (alts_is_frame_writer_done(impl->writer)) {
tsi_result result = seal(impl);
if (result != TSI_OK) {
return result;
}
if (!alts_reset_frame_writer(impl->writer, impl->in_place_protect_buffer,
impl->in_place_protect_bytes_buffered)) {
gpr_log(GPR_ERROR, "Couldn't reset frame writer.");
return TSI_INTERNAL_ERROR;
}
}
/**
* Write the sealed frame as much as possible to protected_output_frames. It's
* possible a frame will not be written out completely by a single flush
* (i.e., still_pending_size != 0), in which case the flush should be called
* iteratively until a complete frame has been written out.
*/
size_t written_frame_bytes = *protected_output_frames_size;
if (!alts_write_frame_bytes(impl->writer, protected_output_frames,
&written_frame_bytes)) {
gpr_log(GPR_ERROR, "Couldn't write frame bytes.");
return TSI_INTERNAL_ERROR;
}
*protected_output_frames_size = written_frame_bytes;
*still_pending_size = alts_get_num_writer_bytes_remaining(impl->writer);
/**
* If the current frame has been finished processing (i.e., sealed and written
* out completely), we empty in_place_protect_buffer.
*/
if (alts_is_frame_writer_done(impl->writer)) {
impl->in_place_protect_bytes_buffered = 0;
}
return TSI_OK;
}
static tsi_result alts_protect(tsi_frame_protector* self,
const unsigned char* unprotected_bytes,
size_t* unprotected_bytes_size,
unsigned char* protected_output_frames,
size_t* protected_output_frames_size) {
if (self == nullptr || unprotected_bytes == nullptr ||
unprotected_bytes_size == nullptr || protected_output_frames == nullptr ||
protected_output_frames_size == nullptr) {
gpr_log(GPR_ERROR, "Invalid nullptr arguments to alts_protect().");
return TSI_INVALID_ARGUMENT;
}
alts_frame_protector* impl = reinterpret_cast<alts_frame_protector*>(self);
/**
* If more payload can be buffered, we buffer it as much as possible to
* in_place_protect_buffer.
*/
if (impl->in_place_protect_bytes_buffered + impl->overhead_length <
max_encrypted_payload_bytes(impl)) {
size_t bytes_to_buffer = GPR_MIN(*unprotected_bytes_size,
max_encrypted_payload_bytes(impl) -
impl->in_place_protect_bytes_buffered -
impl->overhead_length);
*unprotected_bytes_size = bytes_to_buffer;
if (bytes_to_buffer > 0) {
memcpy(
impl->in_place_protect_buffer + impl->in_place_protect_bytes_buffered,
unprotected_bytes, bytes_to_buffer);
impl->in_place_protect_bytes_buffered += bytes_to_buffer;
}
} else {
*unprotected_bytes_size = 0;
}
/**
* If a full frame has been buffered, we output it. If the first condition
* holds, then there exists an unencrypted full frame. If the second
* condition holds, then there exists a full frame that has already been
* encrypted.
*/
if (max_encrypted_payload_bytes(impl) ==
impl->in_place_protect_bytes_buffered + impl->overhead_length ||
max_encrypted_payload_bytes(impl) ==
impl->in_place_protect_bytes_buffered) {
size_t still_pending_size = 0;
return alts_protect_flush(self, protected_output_frames,
protected_output_frames_size,
&still_pending_size);
} else {
*protected_output_frames_size = 0;
return TSI_OK;
}
}
static tsi_result unseal(alts_frame_protector* impl) {
char* error_details = nullptr;
size_t output_size = 0;
grpc_status_code status = alts_crypter_process_in_place(
impl->unseal_crypter, impl->in_place_unprotect_buffer,
impl->max_unprotected_frame_size,
alts_get_output_bytes_read(impl->reader), &output_size, &error_details);
if (status != GRPC_STATUS_OK) {
gpr_log(GPR_ERROR, "%s", error_details);
gpr_free(error_details);
return TSI_DATA_CORRUPTED;
}
return TSI_OK;
}
static void ensure_buffer_size(alts_frame_protector* impl) {
if (!alts_has_read_frame_length(impl->reader)) {
return;
}
size_t buffer_space_remaining = impl->max_unprotected_frame_size -
alts_get_output_bytes_read(impl->reader);
/**
* Check if we need to resize in_place_unprotect_buffer in order to hold
* remaining bytes of a full frame.
*/
if (buffer_space_remaining < alts_get_reader_bytes_remaining(impl->reader)) {
size_t buffer_len = alts_get_output_bytes_read(impl->reader) +
alts_get_reader_bytes_remaining(impl->reader);
unsigned char* buffer = static_cast<unsigned char*>(gpr_malloc(buffer_len));
memcpy(buffer, impl->in_place_unprotect_buffer,
alts_get_output_bytes_read(impl->reader));
impl->max_unprotected_frame_size = buffer_len;
gpr_free(impl->in_place_unprotect_buffer);
impl->in_place_unprotect_buffer = buffer;
alts_reset_reader_output_buffer(
impl->reader, buffer + alts_get_output_bytes_read(impl->reader));
}
}
static tsi_result alts_unprotect(tsi_frame_protector* self,
const unsigned char* protected_frames_bytes,
size_t* protected_frames_bytes_size,
unsigned char* unprotected_bytes,
size_t* unprotected_bytes_size) {
if (self == nullptr || protected_frames_bytes == nullptr ||
protected_frames_bytes_size == nullptr || unprotected_bytes == nullptr ||
unprotected_bytes_size == nullptr) {
gpr_log(GPR_ERROR, "Invalid nullptr arguments to alts_unprotect().");
return TSI_INVALID_ARGUMENT;
}
alts_frame_protector* impl = reinterpret_cast<alts_frame_protector*>(self);
/**
* If a new frame can start being processed, we reset the frame reader to
* point to in_place_unprotect_buffer that will be used to hold deframed
* result.
*/
if (alts_is_frame_reader_done(impl->reader) &&
((alts_get_output_buffer(impl->reader) == nullptr) ||
(alts_get_output_bytes_read(impl->reader) ==
impl->in_place_unprotect_bytes_processed + impl->overhead_length))) {
if (!alts_reset_frame_reader(impl->reader,
impl->in_place_unprotect_buffer)) {
gpr_log(GPR_ERROR, "Couldn't reset frame reader.");
return TSI_INTERNAL_ERROR;
}
impl->in_place_unprotect_bytes_processed = 0;
}
/**
* If a full frame has not yet been read, we read more bytes from
* protected_frames_bytes until a full frame has been read. We also need to
* make sure in_place_unprotect_buffer is large enough to hold a complete
* frame.
*/
if (!alts_is_frame_reader_done(impl->reader)) {
ensure_buffer_size(impl);
*protected_frames_bytes_size =
GPR_MIN(impl->max_unprotected_frame_size -
alts_get_output_bytes_read(impl->reader),
*protected_frames_bytes_size);
size_t read_frames_bytes_size = *protected_frames_bytes_size;
if (!alts_read_frame_bytes(impl->reader, protected_frames_bytes,
&read_frames_bytes_size)) {
gpr_log(GPR_ERROR, "Failed to process frame.");
return TSI_INTERNAL_ERROR;
}
*protected_frames_bytes_size = read_frames_bytes_size;
} else {
*protected_frames_bytes_size = 0;
}
/**
* If a full frame has been read, we unseal it, and write out the
* deframed result to unprotected_bytes.
*/
if (alts_is_frame_reader_done(impl->reader)) {
if (impl->in_place_unprotect_bytes_processed == 0) {
tsi_result result = unseal(impl);
if (result != TSI_OK) {
return result;
}
}
size_t bytes_to_write = GPR_MIN(
*unprotected_bytes_size, alts_get_output_bytes_read(impl->reader) -
impl->in_place_unprotect_bytes_processed -
impl->overhead_length);
if (bytes_to_write > 0) {
memcpy(unprotected_bytes,
impl->in_place_unprotect_buffer +
impl->in_place_unprotect_bytes_processed,
bytes_to_write);
}
*unprotected_bytes_size = bytes_to_write;
impl->in_place_unprotect_bytes_processed += bytes_to_write;
return TSI_OK;
} else {
*unprotected_bytes_size = 0;
return TSI_OK;
}
}
static void alts_destroy(tsi_frame_protector* self) {
alts_frame_protector* impl = reinterpret_cast<alts_frame_protector*>(self);
if (impl != nullptr) {
alts_crypter_destroy(impl->seal_crypter);
alts_crypter_destroy(impl->unseal_crypter);
gpr_free(impl->in_place_protect_buffer);
gpr_free(impl->in_place_unprotect_buffer);
alts_destroy_frame_writer(impl->writer);
alts_destroy_frame_reader(impl->reader);
gpr_free(impl);
}
}
static const tsi_frame_protector_vtable alts_frame_protector_vtable = {
alts_protect, alts_protect_flush, alts_unprotect, alts_destroy};
static grpc_status_code create_alts_crypters(const uint8_t* key,
size_t key_size, bool is_client,
bool is_rekey,
alts_frame_protector* impl,
char** error_details) {
grpc_status_code status;
gsec_aead_crypter* aead_crypter_seal = nullptr;
gsec_aead_crypter* aead_crypter_unseal = nullptr;
status = gsec_aes_gcm_aead_crypter_create(key, key_size, kAesGcmNonceLength,
kAesGcmTagLength, is_rekey,
&aead_crypter_seal, error_details);
if (status != GRPC_STATUS_OK) {
return status;
}
status = gsec_aes_gcm_aead_crypter_create(
key, key_size, kAesGcmNonceLength, kAesGcmTagLength, is_rekey,
&aead_crypter_unseal, error_details);
if (status != GRPC_STATUS_OK) {
return status;
}
size_t overflow_size = is_rekey ? kAltsRecordProtocolRekeyFrameLimit
: kAltsRecordProtocolFrameLimit;
status = alts_seal_crypter_create(aead_crypter_seal, is_client, overflow_size,
&impl->seal_crypter, error_details);
if (status != GRPC_STATUS_OK) {
return status;
}
status =
alts_unseal_crypter_create(aead_crypter_unseal, is_client, overflow_size,
&impl->unseal_crypter, error_details);
return status;
}
tsi_result alts_create_frame_protector(const uint8_t* key, size_t key_size,
bool is_client, bool is_rekey,
size_t* max_protected_frame_size,
tsi_frame_protector** self) {
if (key == nullptr || self == nullptr) {
gpr_log(GPR_ERROR,
"Invalid nullptr arguments to alts_create_frame_protector().");
return TSI_INTERNAL_ERROR;
}
char* error_details = nullptr;
alts_frame_protector* impl =
static_cast<alts_frame_protector*>(gpr_zalloc(sizeof(*impl)));
grpc_status_code status = create_alts_crypters(
key, key_size, is_client, is_rekey, impl, &error_details);
if (status != GRPC_STATUS_OK) {
gpr_log(GPR_ERROR, "Failed to create ALTS crypters, %s.", error_details);
gpr_free(error_details);
return TSI_INTERNAL_ERROR;
}
/**
* Set maximum frame size to be used by a frame protector. If it is nullptr, a
* default frame size will be used. Otherwise, the provided frame size will be
* adjusted (if not falling into a valid frame range) and used.
*/
size_t max_protected_frame_size_to_set = kDefaultFrameLength;
if (max_protected_frame_size != nullptr) {
*max_protected_frame_size =
GPR_MIN(*max_protected_frame_size, kMaxFrameLength);
*max_protected_frame_size =
GPR_MAX(*max_protected_frame_size, kMinFrameLength);
max_protected_frame_size_to_set = *max_protected_frame_size;
}
impl->max_protected_frame_size = max_protected_frame_size_to_set;
impl->max_unprotected_frame_size = max_protected_frame_size_to_set;
impl->in_place_protect_bytes_buffered = 0;
impl->in_place_unprotect_bytes_processed = 0;
impl->in_place_protect_buffer = static_cast<unsigned char*>(
gpr_malloc(sizeof(unsigned char) * max_protected_frame_size_to_set));
impl->in_place_unprotect_buffer = static_cast<unsigned char*>(
gpr_malloc(sizeof(unsigned char) * max_protected_frame_size_to_set));
impl->overhead_length = alts_crypter_num_overhead_bytes(impl->seal_crypter);
impl->writer = alts_create_frame_writer();
impl->reader = alts_create_frame_reader();
impl->base.vtable = &alts_frame_protector_vtable;
*self = &impl->base;
return TSI_OK;
}

@ -0,0 +1,55 @@
/*
*
* Copyright 2018 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_CORE_TSI_ALTS_FRAME_PROTECTOR_ALTS_FRAME_PROTECTOR_H
#define GRPC_CORE_TSI_ALTS_FRAME_PROTECTOR_ALTS_FRAME_PROTECTOR_H
#include <grpc/support/port_platform.h>
#include <stdbool.h>
#include "src/core/tsi/transport_security_interface.h"
typedef struct alts_frame_protector alts_frame_protector;
/**
* TODO: Add a parameter to the interface to support the use of
* different record protocols within a frame protector.
*
* This method creates a frame protector.
*
* - key: a symmetric key used to seal/unseal frames.
* - key_size: the size of symmetric key.
* - is_client: a flag indicating if the frame protector will be used at client
* (is_client = true) or server (is_client = false) side.
* - is_rekey: a flag indicating if the frame protector will use an AEAD with
* rekeying.
* - max_protected_frame_size: an in/out parameter indicating max frame size
* to be used by the frame protector. If it is nullptr, the default frame
* size will be used. Otherwise, the provided frame size will be adjusted (if
* not falling into a valid frame range) and used.
* - self: a pointer to the frame protector returned from the method.
*
* This method returns TSI_OK on success and TSI_INTERNAL_ERROR otherwise.
*/
tsi_result alts_create_frame_protector(const uint8_t* key, size_t key_size,
bool is_client, bool is_rekey,
size_t* max_protected_frame_size,
tsi_frame_protector** self);
#endif /* GRPC_CORE_TSI_ALTS_FRAME_PROTECTOR_ALTS_FRAME_PROTECTOR_H */

@ -0,0 +1,114 @@
/*
*
* Copyright 2018 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 <grpc/support/port_platform.h>
#include "src/core/tsi/alts/frame_protector/alts_record_protocol_crypter_common.h"
#include <grpc/support/alloc.h>
static void maybe_copy_error_msg(const char* src, char** dst) {
if (dst != nullptr && src != nullptr) {
*dst = static_cast<char*>(gpr_malloc(strlen(src) + 1));
memcpy(*dst, src, strlen(src) + 1);
}
}
grpc_status_code input_sanity_check(
const alts_record_protocol_crypter* rp_crypter, const unsigned char* data,
size_t* output_size, char** error_details) {
if (rp_crypter == nullptr) {
maybe_copy_error_msg("alts_crypter instance is nullptr.", error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
} else if (data == nullptr) {
maybe_copy_error_msg("data is nullptr.", error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
} else if (output_size == nullptr) {
maybe_copy_error_msg("output_size is nullptr.", error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
return GRPC_STATUS_OK;
}
grpc_status_code increment_counter(alts_record_protocol_crypter* rp_crypter,
char** error_details) {
bool is_overflow = false;
grpc_status_code status =
alts_counter_increment(rp_crypter->ctr, &is_overflow, error_details);
if (status != GRPC_STATUS_OK) {
return status;
}
if (is_overflow) {
const char error_msg[] =
"crypter counter is wrapped. The connection"
"should be closed and the key should be deleted.";
maybe_copy_error_msg(error_msg, error_details);
return GRPC_STATUS_INTERNAL;
}
return GRPC_STATUS_OK;
}
size_t alts_record_protocol_crypter_num_overhead_bytes(const alts_crypter* c) {
if (c != nullptr) {
size_t num_overhead_bytes = 0;
char* error_details = nullptr;
const alts_record_protocol_crypter* rp_crypter =
reinterpret_cast<const alts_record_protocol_crypter*>(c);
grpc_status_code status = gsec_aead_crypter_tag_length(
rp_crypter->crypter, &num_overhead_bytes, &error_details);
if (status == GRPC_STATUS_OK) {
return num_overhead_bytes;
}
}
return 0;
}
void alts_record_protocol_crypter_destruct(alts_crypter* c) {
if (c != nullptr) {
alts_record_protocol_crypter* rp_crypter =
reinterpret_cast<alts_record_protocol_crypter*>(c);
alts_counter_destroy(rp_crypter->ctr);
gsec_aead_crypter_destroy(rp_crypter->crypter);
}
}
alts_record_protocol_crypter* alts_crypter_create_common(
gsec_aead_crypter* crypter, bool is_client, size_t overflow_size,
char** error_details) {
if (crypter != nullptr) {
auto* rp_crypter = static_cast<alts_record_protocol_crypter*>(
gpr_malloc(sizeof(alts_record_protocol_crypter)));
size_t counter_size = 0;
grpc_status_code status =
gsec_aead_crypter_nonce_length(crypter, &counter_size, error_details);
if (status != GRPC_STATUS_OK) {
return nullptr;
}
/* Create a counter. */
status = alts_counter_create(is_client, counter_size, overflow_size,
&rp_crypter->ctr, error_details);
if (status != GRPC_STATUS_OK) {
return nullptr;
}
rp_crypter->crypter = crypter;
return rp_crypter;
}
const char error_msg[] = "crypter is nullptr.";
maybe_copy_error_msg(error_msg, error_details);
return nullptr;
}

@ -0,0 +1,114 @@
/*
*
* Copyright 2018 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_CORE_TSI_ALTS_FRAME_PROTECTOR_ALTS_RECORD_PROTOCOL_CRYPTER_COMMON_H
#define GRPC_CORE_TSI_ALTS_FRAME_PROTECTOR_ALTS_RECORD_PROTOCOL_CRYPTER_COMMON_H
#include <grpc/support/port_platform.h>
#include <grpc/grpc.h>
#include "src/core/tsi/alts/frame_protector/alts_counter.h"
#include "src/core/tsi/alts/frame_protector/alts_crypter.h"
/**
* This file contains common implementation that will be used in both seal and
* unseal operations.
*/
/**
* Main struct for alts_record_protocol_crypter that will be used in both
* seal and unseal operations.
*/
typedef struct alts_record_protocol_crypter {
alts_crypter base;
gsec_aead_crypter* crypter;
alts_counter* ctr;
} alts_record_protocol_crypter;
/**
* This method performs input sanity checks on a subset of inputs to
* alts_crypter_process_in_place() for both seal and unseal operations.
*
* - rp_crypter: an alts_record_protocol_crypter instance.
* - data: it represents raw data that needs to be sealed in a seal operation or
* protected data that needs to be unsealed in an unseal operation.
* - output_size: size of data written to the data buffer after a seal or
* unseal operation.
* - error_details: a buffer containing an error message if any of checked
* inputs is nullptr. It is legal to pass nullptr into error_details and
* otherwise, the parameter should be freed with gpr_free.
*
* On success, the method returns GRPC_STATUS_OK. Otherwise,
* it returns an error status code along with its details specified in
* error_details (if error_details is not nullptr).
*/
grpc_status_code input_sanity_check(
const alts_record_protocol_crypter* rp_crypter, const unsigned char* data,
size_t* output_size, char** error_details);
/**
* This method increments the counter within an alts_record_protocol_crypter
* instance.
*
* - rp_crypter: an alts_record_protocol_crypter instance.
* - error_details: a buffer containing an error message if the method does not
* function correctly or the counter is wrapped. It is legal to pass nullptr
* into error_details and otherwise, the parameter should be freed with
* gpr_free.
*
* On success, the method returns GRPC_STATUS_OK. Otherwise,
* it returns an error status code along with its details specified in
* error_details (if error_details is not nullptr).
*/
grpc_status_code increment_counter(alts_record_protocol_crypter* rp_crypter,
char** error_details);
/**
* This method creates an alts_crypter instance, and populates the fields
* that are common to both seal and unseal operations.
*
* - crypter: a gsec_aead_crypter instance used to perform AEAD decryption. The
* function does not take ownership of crypter.
* - is_client: a flag indicating if the alts_crypter instance will be
* used at the client (is_client = true) or server (is_client =
* false) side.
* - overflow_size: overflow size of counter in bytes.
* - error_details: a buffer containing an error message if the method does
* not function correctly. It is legal to pass nullptr into error_details, and
* otherwise, the parameter should be freed with gpr_free.
*
* On success of creation, the method returns alts_record_protocol_crypter
* instance. Otherwise, it returns nullptr with its details specified in
* error_details (if error_details is not nullptr).
*
*/
alts_record_protocol_crypter* alts_crypter_create_common(
gsec_aead_crypter* crypter, bool is_client, size_t overflow_size,
char** error_details);
/**
* For the following two methods, please refer to the corresponding API in
* alts_crypter.h for detailed specifications.
*/
size_t alts_record_protocol_crypter_num_overhead_bytes(const alts_crypter* c);
void alts_record_protocol_crypter_destruct(alts_crypter* c);
#endif /* GRPC_CORE_TSI_ALTS_FRAME_PROTECTOR_ALTS_RECORD_PROTOCOL_CRYPTER_COMMON_H \
*/

@ -0,0 +1,105 @@
/*
*
* Copyright 2018 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 <grpc/support/port_platform.h>
#include <grpc/support/alloc.h>
#include "src/core/tsi/alts/frame_protector/alts_counter.h"
#include "src/core/tsi/alts/frame_protector/alts_crypter.h"
#include "src/core/tsi/alts/frame_protector/alts_record_protocol_crypter_common.h"
static void maybe_copy_error_msg(const char* src, char** dst) {
if (dst != nullptr && src != nullptr) {
*dst = static_cast<char*>(gpr_malloc(strlen(src) + 1));
memcpy(*dst, src, strlen(src) + 1);
}
}
/* Perform input santity check for a seal operation. */
static grpc_status_code seal_check(alts_crypter* c, const unsigned char* data,
size_t data_allocated_size, size_t data_size,
size_t* output_size, char** error_details) {
/* Do common input sanity check. */
grpc_status_code status = input_sanity_check(
reinterpret_cast<const alts_record_protocol_crypter*>(c), data,
output_size, error_details);
if (status != GRPC_STATUS_OK) return status;
/* Do seal-specific check. */
size_t num_overhead_bytes =
alts_crypter_num_overhead_bytes(reinterpret_cast<const alts_crypter*>(c));
if (data_size == 0) {
const char error_msg[] = "data_size is zero.";
maybe_copy_error_msg(error_msg, error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
if (data_size + num_overhead_bytes > data_allocated_size) {
const char error_msg[] =
"data_allocated_size is smaller than sum of data_size and "
"num_overhead_bytes.";
maybe_copy_error_msg(error_msg, error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
return GRPC_STATUS_OK;
}
static grpc_status_code alts_seal_crypter_process_in_place(
alts_crypter* c, unsigned char* data, size_t data_allocated_size,
size_t data_size, size_t* output_size, char** error_details) {
grpc_status_code status = seal_check(c, data, data_allocated_size, data_size,
output_size, error_details);
if (status != GRPC_STATUS_OK) {
return status;
}
/* Do AEAD encryption. */
alts_record_protocol_crypter* rp_crypter =
reinterpret_cast<alts_record_protocol_crypter*>(c);
status = gsec_aead_crypter_encrypt(
rp_crypter->crypter, alts_counter_get_counter(rp_crypter->ctr),
alts_counter_get_size(rp_crypter->ctr), nullptr /* aad */,
0 /* aad_length */, data, data_size, data, data_allocated_size,
output_size, error_details);
if (status != GRPC_STATUS_OK) {
return status;
}
/* Increment the crypter counter. */
return increment_counter(rp_crypter, error_details);
}
static const alts_crypter_vtable vtable = {
alts_record_protocol_crypter_num_overhead_bytes,
alts_seal_crypter_process_in_place, alts_record_protocol_crypter_destruct};
grpc_status_code alts_seal_crypter_create(gsec_aead_crypter* gc, bool is_client,
size_t overflow_size,
alts_crypter** crypter,
char** error_details) {
if (crypter == nullptr) {
const char error_msg[] = "crypter is nullptr.";
maybe_copy_error_msg(error_msg, error_details);
return GRPC_STATUS_FAILED_PRECONDITION;
}
alts_record_protocol_crypter* rp_crypter =
alts_crypter_create_common(gc, !is_client, overflow_size, error_details);
if (rp_crypter == nullptr) {
return GRPC_STATUS_FAILED_PRECONDITION;
}
rp_crypter->base.vtable = &vtable;
*crypter = &rp_crypter->base;
return GRPC_STATUS_OK;
}

@ -0,0 +1,103 @@
/*
*
* Copyright 2018 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 <grpc/support/port_platform.h>
#include <grpc/support/alloc.h>
#include "src/core/tsi/alts/frame_protector/alts_counter.h"
#include "src/core/tsi/alts/frame_protector/alts_crypter.h"
#include "src/core/tsi/alts/frame_protector/alts_record_protocol_crypter_common.h"
static void maybe_copy_error_msg(const char* src, char** dst) {
if (dst != nullptr && src != nullptr) {
*dst = static_cast<char*>(gpr_malloc(strlen(src) + 1));
memcpy(*dst, src, strlen(src) + 1);
}
}
/* Perform input santity check. */
static grpc_status_code unseal_check(alts_crypter* c, const unsigned char* data,
size_t data_allocated_size,
size_t data_size, size_t* output_size,
char** error_details) {
/* Do common input sanity check. */
grpc_status_code status = input_sanity_check(
reinterpret_cast<const alts_record_protocol_crypter*>(c), data,
output_size, error_details);
if (status != GRPC_STATUS_OK) {
return status;
}
/* Do unseal-specific input check. */
size_t num_overhead_bytes =
alts_crypter_num_overhead_bytes(reinterpret_cast<const alts_crypter*>(c));
if (num_overhead_bytes > data_size) {
const char error_msg[] = "data_size is smaller than num_overhead_bytes.";
maybe_copy_error_msg(error_msg, error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
return GRPC_STATUS_OK;
}
static grpc_status_code alts_unseal_crypter_process_in_place(
alts_crypter* c, unsigned char* data, size_t data_allocated_size,
size_t data_size, size_t* output_size, char** error_details) {
grpc_status_code status = unseal_check(c, data, data_allocated_size,
data_size, output_size, error_details);
if (status != GRPC_STATUS_OK) {
return status;
}
/* Do AEAD decryption. */
alts_record_protocol_crypter* rp_crypter =
reinterpret_cast<alts_record_protocol_crypter*>(c);
status = gsec_aead_crypter_decrypt(
rp_crypter->crypter, alts_counter_get_counter(rp_crypter->ctr),
alts_counter_get_size(rp_crypter->ctr), nullptr /* aad */,
0 /* aad_length */, data, data_size, data, data_allocated_size,
output_size, error_details);
if (status != GRPC_STATUS_OK) {
return status;
}
/* Increment the crypter counter. */
return increment_counter(rp_crypter, error_details);
}
static const alts_crypter_vtable vtable = {
alts_record_protocol_crypter_num_overhead_bytes,
alts_unseal_crypter_process_in_place,
alts_record_protocol_crypter_destruct};
grpc_status_code alts_unseal_crypter_create(gsec_aead_crypter* gc,
bool is_client,
size_t overflow_size,
alts_crypter** crypter,
char** error_details) {
if (crypter == nullptr) {
const char error_msg[] = "crypter is nullptr.";
maybe_copy_error_msg(error_msg, error_details);
return GRPC_STATUS_FAILED_PRECONDITION;
}
alts_record_protocol_crypter* rp_crypter =
alts_crypter_create_common(gc, is_client, overflow_size, error_details);
if (rp_crypter == nullptr) {
return GRPC_STATUS_FAILED_PRECONDITION;
}
rp_crypter->base.vtable = &vtable;
*crypter = &rp_crypter->base;
return GRPC_STATUS_OK;
}

@ -0,0 +1,218 @@
/*
*
* Copyright 2018 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 <grpc/support/port_platform.h>
#include "src/core/tsi/alts/frame_protector/frame_handler.h"
#include <limits.h>
#include <stdint.h>
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "src/core/lib/gpr/useful.h"
/* Use little endian to interpret a string of bytes as uint32_t. */
static uint32_t load_32_le(const unsigned char* buffer) {
return (((uint32_t)buffer[3]) << 24) | (((uint32_t)buffer[2]) << 16) |
(((uint32_t)buffer[1]) << 8) | ((uint32_t)buffer[0]);
}
/* Store uint32_t as a string of little endian bytes. */
static void store_32_le(uint32_t value, unsigned char* buffer) {
buffer[3] = (unsigned char)(value >> 24) & 0xFF;
buffer[2] = (unsigned char)(value >> 16) & 0xFF;
buffer[1] = (unsigned char)(value >> 8) & 0xFF;
buffer[0] = (unsigned char)(value)&0xFF;
}
/* Frame writer implementation. */
alts_frame_writer* alts_create_frame_writer() {
alts_frame_writer* writer =
static_cast<alts_frame_writer*>(gpr_zalloc(sizeof(*writer)));
return writer;
}
bool alts_reset_frame_writer(alts_frame_writer* writer,
const unsigned char* buffer, size_t length) {
if (buffer == nullptr) return false;
size_t max_input_size = SIZE_MAX - kFrameLengthFieldSize;
if (length > max_input_size) {
gpr_log(GPR_ERROR, "length must be at most %zu", max_input_size);
return false;
}
writer->input_buffer = buffer;
writer->input_size = length;
writer->input_bytes_written = 0;
writer->header_bytes_written = 0;
store_32_le(
static_cast<uint32_t>(writer->input_size + kFrameMessageTypeFieldSize),
writer->header_buffer);
store_32_le(kFrameMessageType, writer->header_buffer + kFrameLengthFieldSize);
return true;
}
bool alts_write_frame_bytes(alts_frame_writer* writer, unsigned char* output,
size_t* bytes_size) {
if (bytes_size == nullptr || output == nullptr) return false;
if (alts_is_frame_writer_done(writer)) {
*bytes_size = 0;
return true;
}
size_t bytes_written = 0;
/* Write some header bytes, if needed. */
if (writer->header_bytes_written != sizeof(writer->header_buffer)) {
size_t bytes_to_write =
GPR_MIN(*bytes_size,
sizeof(writer->header_buffer) - writer->header_bytes_written);
memcpy(output, writer->header_buffer + writer->header_bytes_written,
bytes_to_write);
bytes_written += bytes_to_write;
*bytes_size -= bytes_to_write;
writer->header_bytes_written += bytes_to_write;
output += bytes_to_write;
if (writer->header_bytes_written != sizeof(writer->header_buffer)) {
*bytes_size = bytes_written;
return true;
}
}
/* Write some non-header bytes. */
size_t bytes_to_write =
GPR_MIN(writer->input_size - writer->input_bytes_written, *bytes_size);
memcpy(output, writer->input_buffer, bytes_to_write);
writer->input_buffer += bytes_to_write;
bytes_written += bytes_to_write;
writer->input_bytes_written += bytes_to_write;
*bytes_size = bytes_written;
return true;
}
bool alts_is_frame_writer_done(alts_frame_writer* writer) {
return writer->input_buffer == nullptr ||
writer->input_size == writer->input_bytes_written;
}
size_t alts_get_num_writer_bytes_remaining(alts_frame_writer* writer) {
return (sizeof(writer->header_buffer) - writer->header_bytes_written) +
(writer->input_size - writer->input_bytes_written);
}
void alts_destroy_frame_writer(alts_frame_writer* writer) { gpr_free(writer); }
/* Frame reader implementation. */
alts_frame_reader* alts_create_frame_reader() {
alts_frame_reader* reader =
static_cast<alts_frame_reader*>(gpr_zalloc(sizeof(*reader)));
return reader;
}
bool alts_is_frame_reader_done(alts_frame_reader* reader) {
return reader->output_buffer == nullptr ||
(reader->header_bytes_read == sizeof(reader->header_buffer) &&
reader->bytes_remaining == 0);
}
bool alts_has_read_frame_length(alts_frame_reader* reader) {
return sizeof(reader->header_buffer) == reader->header_bytes_read;
}
size_t alts_get_reader_bytes_remaining(alts_frame_reader* reader) {
return alts_has_read_frame_length(reader) ? reader->bytes_remaining : 0;
}
void alts_reset_reader_output_buffer(alts_frame_reader* reader,
unsigned char* buffer) {
reader->output_buffer = buffer;
}
bool alts_reset_frame_reader(alts_frame_reader* reader, unsigned char* buffer) {
if (buffer == nullptr) return false;
reader->output_buffer = buffer;
reader->bytes_remaining = 0;
reader->header_bytes_read = 0;
reader->output_bytes_read = 0;
return true;
}
bool alts_read_frame_bytes(alts_frame_reader* reader,
const unsigned char* bytes, size_t* bytes_size) {
if (bytes_size == nullptr) return false;
if (bytes == nullptr) {
*bytes_size = 0;
return false;
}
if (alts_is_frame_reader_done(reader)) {
*bytes_size = 0;
return true;
}
size_t bytes_processed = 0;
/* Process the header, if needed. */
if (reader->header_bytes_read != sizeof(reader->header_buffer)) {
size_t bytes_to_write = GPR_MIN(
*bytes_size, sizeof(reader->header_buffer) - reader->header_bytes_read);
memcpy(reader->header_buffer + reader->header_bytes_read, bytes,
bytes_to_write);
reader->header_bytes_read += bytes_to_write;
bytes_processed += bytes_to_write;
bytes += bytes_to_write;
*bytes_size -= bytes_to_write;
if (reader->header_bytes_read != sizeof(reader->header_buffer)) {
*bytes_size = bytes_processed;
return true;
}
size_t frame_length = load_32_le(reader->header_buffer);
if (frame_length < kFrameMessageTypeFieldSize ||
frame_length > kFrameMaxSize) {
gpr_log(GPR_ERROR,
"Bad frame length (should be at least %zu, and at most %zu)",
kFrameMessageTypeFieldSize, kFrameMaxSize);
*bytes_size = 0;
return false;
}
size_t message_type =
load_32_le(reader->header_buffer + kFrameLengthFieldSize);
if (message_type != kFrameMessageType) {
gpr_log(GPR_ERROR, "Unsupported message type %zu (should be %zu)",
message_type, kFrameMessageType);
*bytes_size = 0;
return false;
}
reader->bytes_remaining = frame_length - kFrameMessageTypeFieldSize;
}
/* Process the non-header bytes. */
size_t bytes_to_write = GPR_MIN(*bytes_size, reader->bytes_remaining);
memcpy(reader->output_buffer, bytes, bytes_to_write);
reader->output_buffer += bytes_to_write;
bytes_processed += bytes_to_write;
reader->bytes_remaining -= bytes_to_write;
reader->output_bytes_read += bytes_to_write;
*bytes_size = bytes_processed;
return true;
}
size_t alts_get_output_bytes_read(alts_frame_reader* reader) {
return reader->output_bytes_read;
}
unsigned char* alts_get_output_buffer(alts_frame_reader* reader) {
return reader->output_buffer;
}
void alts_destroy_frame_reader(alts_frame_reader* reader) { gpr_free(reader); }

@ -0,0 +1,236 @@
/*
*
* Copyright 2018 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_CORE_TSI_ALTS_FRAME_PROTECTOR_FRAME_HANDLER_H
#define GRPC_CORE_TSI_ALTS_FRAME_PROTECTOR_FRAME_HANDLER_H
#include <grpc/support/port_platform.h>
#include <stdbool.h>
#include <stdlib.h>
const size_t kFrameMessageType = 0x06;
const size_t kFrameLengthFieldSize = 4;
const size_t kFrameMessageTypeFieldSize = 4;
const size_t kFrameMaxSize = 1024 * 1024;
const size_t kFrameHeaderSize =
kFrameLengthFieldSize + kFrameMessageTypeFieldSize;
/**
* Implementation of frame reader and frame writer. All APIs in the
* header are thread-compatible.
*/
/**
* Main struct for a frame writer. It reads frames from an input buffer, and
* writes the contents as raw bytes. It does not own the input buffer.
*/
typedef struct alts_frame_writer {
const unsigned char* input_buffer;
unsigned char header_buffer[kFrameHeaderSize];
size_t input_bytes_written;
size_t header_bytes_written;
size_t input_size;
} alts_frame_writer;
/**
* Main struct for a frame reader. It reads raw bytes and puts the framed
* result into an output buffer. It does not own the output buffer.
*/
typedef struct alts_frame_reader {
unsigned char* output_buffer;
unsigned char header_buffer[kFrameHeaderSize];
size_t header_bytes_read;
size_t output_bytes_read;
size_t bytes_remaining;
} alts_frame_reader;
/**
* This method creates a frame writer instance and initializes its internal
* states.
*/
alts_frame_writer* alts_create_frame_writer();
/**
* This method resets internal states of a frame writer and prepares to write
* a single frame. It does not take ownership of payload_buffer.
* The payload_buffer must outlive the writer.
*
* - writer: a frame writer instance.
* - buffer: a buffer storing full payload data to be framed.
* - length: size of payload data.
*
* The method returns true on success and false otherwise.
*/
bool alts_reset_frame_writer(alts_frame_writer* writer,
const unsigned char* buffer, size_t length);
/**
* This method writes up to bytes_size bytes of a frame to output.
*
* - writer: a frame writer instance.
* - output: an output buffer used to store the frame.
* - bytes_size: an in/out parameter that stores the size of output buffer
* before the call, and gets written the number of frame bytes written to the
* buffer.
*
* The method returns true on success and false otherwise.
*/
bool alts_write_frame_bytes(alts_frame_writer* writer, unsigned char* output,
size_t* bytes_size);
/**
* This method checks if a reset can be called to write a new frame. It returns
* true if it's the first time to frame a payload, or the current frame has
* been finished processing. It returns false if it's not ready yet to start a
* new frame (e.g., more payload data needs to be accumulated to process the
* current frame).
*
* if (alts_is_frame_writer_done(writer)) {
* // a new frame can be written, call reset.
* alts_reset_frame_writer(writer, payload_buffer, payload_size);
* } else {
* // accumulate more payload data until a full frame can be written.
* }
*
* - writer: a frame writer instance.
*/
bool alts_is_frame_writer_done(alts_frame_writer* writer);
/**
* This method returns the number of bytes left to write before a complete frame
* is formed.
*
* - writer: a frame writer instance.
*/
size_t alts_get_num_writer_bytes_remaining(alts_frame_writer* writer);
/**
* This method destroys a frame writer instance.
*
* - writer: a frame writer instance.
*/
void alts_destroy_frame_writer(alts_frame_writer* writer);
/**
* This method creates a frame reader instance and initializes its internal
* states.
*/
alts_frame_reader* alts_create_frame_reader();
/**
* This method resets internal states of a frame reader (including setting its
* output_buffer with buffer), and prepares to write processed bytes to
* an output_buffer. It does not take ownership of buffer. The buffer must
* outlive reader.
*
* - reader: a frame reader instance.
* - buffer: an output buffer used to store deframed results.
*
* The method returns true on success and false otherwise.
*/
bool alts_reset_frame_reader(alts_frame_reader* reader, unsigned char* buffer);
/**
* This method processes up to the number of bytes given in bytes_size. It may
* choose not to process all the bytes, if, for instance, more bytes are
* given to the method than required to complete the current frame.
*
* - reader: a frame reader instance.
* - bytes: a buffer that stores data to be processed.
* - bytes_size: an in/out parameter that stores the size of bytes before the
* call and gets written the number of bytes processed.
*
* The method returns true on success and false otherwise.
*/
bool alts_read_frame_bytes(alts_frame_reader* reader,
const unsigned char* bytes, size_t* bytes_size);
/**
* This method checks if a frame length has been read.
*
* - reader: a frame reader instance.
*
* The method returns true if a frame length has been read and false otherwise.
*/
bool alts_has_read_frame_length(alts_frame_reader* reader);
/**
* This method returns the number of bytes the frame reader intends to write.
* It may only be called if alts_has_read_frame_length() returns true.
*
* - reader: a frame reader instance.
*/
size_t alts_get_reader_bytes_remaining(alts_frame_reader* reader);
/**
* This method resets output_buffer but does not otherwise modify other internal
* states of a frame reader instance. After being set, the new output_buffer
* will hold the deframed payload held by the original output_buffer. It does
* not take ownership of buffer. The buffer must outlive the reader.
* To distinguish between two reset methods on a frame reader,
*
* if (alts_fh_is_frame_reader_done(reader)) {
* // if buffer contains a full payload to be deframed, call reset.
* alts_reset_frame_reader(reader, buffer);
* }
*
* // if remaining buffer space is not enough to hold a full payload
* if (buffer_space_remaining < alts_get_reader_bytes_remaining(reader)) {
* // allocate enough space for a new buffer, copy back data processed so far,
* // and call reset.
* alts_reset_reader_output_buffer(reader, new_buffer).
* }
*
* - reader: a frame reader instance.
* - buffer: a buffer used to set reader's output_buffer.
*/
void alts_reset_reader_output_buffer(alts_frame_reader* reader,
unsigned char* buffer);
/**
* This method checks if reset can be called to start processing a new frame.
* If true and reset was previously called, a full frame has been processed and
* the content of the frame is available in output_buffer.
* - reader: a frame reader instance.
*/
bool alts_is_frame_reader_done(alts_frame_reader* reader);
/**
* This method returns output_bytes_read of a frame reader instance.
*
* - reader: a frame reader instance.
*/
size_t alts_get_output_bytes_read(alts_frame_reader* reader);
/**
* This method returns output_buffer of a frame reader instance.
*
* - reader: a frame reader instance.
*/
unsigned char* alts_get_output_buffer(alts_frame_reader* reader);
/**
* This method destroys a frame reader instance.
*
* - reader: a frame reader instance.
*/
void alts_destroy_frame_reader(alts_frame_reader* reader);
#endif /* GRPC_CORE_TSI_ALTS_FRAME_PROTECTOR_FRAME_HANDLER_H */

@ -0,0 +1,316 @@
/*
*
* Copyright 2018 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 <grpc/support/port_platform.h>
#include "src/core/tsi/alts/handshaker/alts_handshaker_client.h"
#include <grpc/byte_buffer.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "src/core/tsi/alts/handshaker/alts_handshaker_service_api.h"
const int kHandshakerClientOpNum = 4;
typedef struct alts_grpc_handshaker_client {
alts_handshaker_client base;
grpc_call* call;
alts_grpc_caller grpc_caller;
} alts_grpc_handshaker_client;
static grpc_call_error grpc_start_batch(grpc_call* call, const grpc_op* ops,
size_t nops, void* tag) {
return grpc_call_start_batch(call, ops, nops, tag, nullptr);
}
/**
* Populate grpc operation data with the fields of ALTS TSI event and make a
* grpc call.
*/
static tsi_result make_grpc_call(alts_handshaker_client* client,
alts_tsi_event* event, bool is_start) {
GPR_ASSERT(client != nullptr && event != nullptr);
alts_grpc_handshaker_client* grpc_client =
reinterpret_cast<alts_grpc_handshaker_client*>(client);
grpc_op ops[kHandshakerClientOpNum];
memset(ops, 0, sizeof(ops));
grpc_op* op = ops;
if (is_start) {
op->op = GRPC_OP_SEND_INITIAL_METADATA;
op->data.send_initial_metadata.count = 0;
op++;
GPR_ASSERT(op - ops <= kHandshakerClientOpNum);
op->op = GRPC_OP_RECV_INITIAL_METADATA;
op->data.recv_initial_metadata.recv_initial_metadata =
&event->initial_metadata;
op++;
GPR_ASSERT(op - ops <= kHandshakerClientOpNum);
}
op->op = GRPC_OP_SEND_MESSAGE;
op->data.send_message.send_message = event->send_buffer;
op++;
GPR_ASSERT(op - ops <= kHandshakerClientOpNum);
op->op = GRPC_OP_RECV_MESSAGE;
op->data.recv_message.recv_message = &event->recv_buffer;
op++;
GPR_ASSERT(op - ops <= kHandshakerClientOpNum);
GPR_ASSERT(grpc_client->grpc_caller != nullptr);
if (grpc_client->grpc_caller(grpc_client->call, ops,
static_cast<size_t>(op - ops),
(void*)event) != GRPC_CALL_OK) {
gpr_log(GPR_ERROR, "Start batch operation failed");
return TSI_INTERNAL_ERROR;
}
return TSI_OK;
}
/* Create and populate a client_start handshaker request, then serialize it. */
static grpc_byte_buffer* get_serialized_start_client(alts_tsi_event* event) {
bool ok = true;
grpc_gcp_handshaker_req* req =
grpc_gcp_handshaker_req_create(CLIENT_START_REQ);
ok &= grpc_gcp_handshaker_req_set_handshake_protocol(
req, grpc_gcp_HandshakeProtocol_ALTS);
ok &= grpc_gcp_handshaker_req_add_application_protocol(
req, ALTS_APPLICATION_PROTOCOL);
ok &= grpc_gcp_handshaker_req_add_record_protocol(req, ALTS_RECORD_PROTOCOL);
grpc_gcp_rpc_protocol_versions* versions = &event->options->rpc_versions;
ok &= grpc_gcp_handshaker_req_set_rpc_versions(
req, versions->max_rpc_version.major, versions->max_rpc_version.minor,
versions->min_rpc_version.major, versions->min_rpc_version.minor);
char* target_name = grpc_slice_to_c_string(event->target_name);
ok &= grpc_gcp_handshaker_req_set_target_name(req, target_name);
target_service_account* ptr =
(reinterpret_cast<grpc_alts_credentials_client_options*>(event->options))
->target_account_list_head;
while (ptr != nullptr) {
grpc_gcp_handshaker_req_add_target_identity_service_account(req, ptr->data);
ptr = ptr->next;
}
grpc_slice slice;
ok &= grpc_gcp_handshaker_req_encode(req, &slice);
grpc_byte_buffer* buffer = nullptr;
if (ok) {
buffer = grpc_raw_byte_buffer_create(&slice, 1 /* number of slices */);
}
grpc_slice_unref(slice);
gpr_free(target_name);
grpc_gcp_handshaker_req_destroy(req);
return buffer;
}
static tsi_result handshaker_client_start_client(alts_handshaker_client* client,
alts_tsi_event* event) {
if (client == nullptr || event == nullptr) {
gpr_log(GPR_ERROR,
"Invalid arguments to alts_grpc_handshaker_client_start_client()");
return TSI_INVALID_ARGUMENT;
}
grpc_byte_buffer* buffer = get_serialized_start_client(event);
if (buffer == nullptr) {
gpr_log(GPR_ERROR, "get_serialized_start_client() failed");
return TSI_INTERNAL_ERROR;
}
event->send_buffer = buffer;
tsi_result result = make_grpc_call(client, event, true /* is_start */);
if (result != TSI_OK) {
gpr_log(GPR_ERROR, "make_grpc_call() failed");
}
return result;
}
/* Create and populate a start_server handshaker request, then serialize it. */
static grpc_byte_buffer* get_serialized_start_server(
alts_tsi_event* event, grpc_slice* bytes_received) {
GPR_ASSERT(bytes_received != nullptr);
grpc_gcp_handshaker_req* req =
grpc_gcp_handshaker_req_create(SERVER_START_REQ);
bool ok = grpc_gcp_handshaker_req_add_application_protocol(
req, ALTS_APPLICATION_PROTOCOL);
ok &= grpc_gcp_handshaker_req_param_add_record_protocol(
req, grpc_gcp_HandshakeProtocol_ALTS, ALTS_RECORD_PROTOCOL);
ok &= grpc_gcp_handshaker_req_set_in_bytes(
req, reinterpret_cast<const char*> GRPC_SLICE_START_PTR(*bytes_received),
GRPC_SLICE_LENGTH(*bytes_received));
grpc_gcp_rpc_protocol_versions* versions = &event->options->rpc_versions;
ok &= grpc_gcp_handshaker_req_set_rpc_versions(
req, versions->max_rpc_version.major, versions->max_rpc_version.minor,
versions->min_rpc_version.major, versions->min_rpc_version.minor);
grpc_slice req_slice;
ok &= grpc_gcp_handshaker_req_encode(req, &req_slice);
grpc_byte_buffer* buffer = nullptr;
if (ok) {
buffer = grpc_raw_byte_buffer_create(&req_slice, 1 /* number of slices */);
}
grpc_slice_unref(req_slice);
grpc_gcp_handshaker_req_destroy(req);
return buffer;
}
static tsi_result handshaker_client_start_server(alts_handshaker_client* client,
alts_tsi_event* event,
grpc_slice* bytes_received) {
if (client == nullptr || event == nullptr || bytes_received == nullptr) {
gpr_log(GPR_ERROR,
"Invalid arguments to alts_grpc_handshaker_client_start_server()");
return TSI_INVALID_ARGUMENT;
}
grpc_byte_buffer* buffer = get_serialized_start_server(event, bytes_received);
if (buffer == nullptr) {
gpr_log(GPR_ERROR, "get_serialized_start_server() failed");
return TSI_INTERNAL_ERROR;
}
event->send_buffer = buffer;
tsi_result result = make_grpc_call(client, event, true /* is_start */);
if (result != TSI_OK) {
gpr_log(GPR_ERROR, "make_grpc_call() failed");
}
return result;
}
/* Create and populate a next handshaker request, then serialize it. */
static grpc_byte_buffer* get_serialized_next(grpc_slice* bytes_received) {
GPR_ASSERT(bytes_received != nullptr);
grpc_gcp_handshaker_req* req = grpc_gcp_handshaker_req_create(NEXT_REQ);
bool ok = grpc_gcp_handshaker_req_set_in_bytes(
req, reinterpret_cast<const char*> GRPC_SLICE_START_PTR(*bytes_received),
GRPC_SLICE_LENGTH(*bytes_received));
grpc_slice req_slice;
ok &= grpc_gcp_handshaker_req_encode(req, &req_slice);
grpc_byte_buffer* buffer = nullptr;
if (ok) {
buffer = grpc_raw_byte_buffer_create(&req_slice, 1 /* number of slices */);
}
grpc_slice_unref(req_slice);
grpc_gcp_handshaker_req_destroy(req);
return buffer;
}
static tsi_result handshaker_client_next(alts_handshaker_client* client,
alts_tsi_event* event,
grpc_slice* bytes_received) {
if (client == nullptr || event == nullptr || bytes_received == nullptr) {
gpr_log(GPR_ERROR,
"Invalid arguments to alts_grpc_handshaker_client_next()");
return TSI_INVALID_ARGUMENT;
}
grpc_byte_buffer* buffer = get_serialized_next(bytes_received);
if (buffer == nullptr) {
gpr_log(GPR_ERROR, "get_serialized_next() failed");
return TSI_INTERNAL_ERROR;
}
event->send_buffer = buffer;
tsi_result result = make_grpc_call(client, event, false /* is_start */);
if (result != TSI_OK) {
gpr_log(GPR_ERROR, "make_grpc_call() failed");
}
return result;
}
static void handshaker_client_destruct(alts_handshaker_client* client) {
if (client == nullptr) {
return;
}
alts_grpc_handshaker_client* grpc_client =
reinterpret_cast<alts_grpc_handshaker_client*>(client);
grpc_call_unref(grpc_client->call);
}
static const alts_handshaker_client_vtable vtable = {
handshaker_client_start_client, handshaker_client_start_server,
handshaker_client_next, handshaker_client_destruct};
alts_handshaker_client* alts_grpc_handshaker_client_create(
grpc_channel* channel, grpc_completion_queue* queue,
const char* handshaker_service_url) {
if (channel == nullptr || queue == nullptr ||
handshaker_service_url == nullptr) {
gpr_log(GPR_ERROR, "Invalid arguments to alts_handshaker_client_create()");
return nullptr;
}
alts_grpc_handshaker_client* client =
static_cast<alts_grpc_handshaker_client*>(gpr_zalloc(sizeof(*client)));
client->grpc_caller = grpc_start_batch;
grpc_slice slice = grpc_slice_from_copied_string(handshaker_service_url);
client->call = grpc_channel_create_call(
channel, nullptr, GRPC_PROPAGATE_DEFAULTS, queue,
grpc_slice_from_static_string(ALTS_SERVICE_METHOD), &slice,
gpr_inf_future(GPR_CLOCK_REALTIME), nullptr);
client->base.vtable = &vtable;
grpc_slice_unref(slice);
return &client->base;
}
namespace grpc_core {
namespace internal {
void alts_handshaker_client_set_grpc_caller_for_testing(
alts_handshaker_client* client, alts_grpc_caller caller) {
GPR_ASSERT(client != nullptr && caller != nullptr);
alts_grpc_handshaker_client* grpc_client =
reinterpret_cast<alts_grpc_handshaker_client*>(client);
grpc_client->grpc_caller = caller;
}
} // namespace internal
} // namespace grpc_core
tsi_result alts_handshaker_client_start_client(alts_handshaker_client* client,
alts_tsi_event* event) {
if (client != nullptr && client->vtable != nullptr &&
client->vtable->client_start != nullptr) {
return client->vtable->client_start(client, event);
}
gpr_log(GPR_ERROR,
"client or client->vtable has not been initialized properly");
return TSI_INVALID_ARGUMENT;
}
tsi_result alts_handshaker_client_start_server(alts_handshaker_client* client,
alts_tsi_event* event,
grpc_slice* bytes_received) {
if (client != nullptr && client->vtable != nullptr &&
client->vtable->server_start != nullptr) {
return client->vtable->server_start(client, event, bytes_received);
}
gpr_log(GPR_ERROR,
"client or client->vtable has not been initialized properly");
return TSI_INVALID_ARGUMENT;
}
tsi_result alts_handshaker_client_next(alts_handshaker_client* client,
alts_tsi_event* event,
grpc_slice* bytes_received) {
if (client != nullptr && client->vtable != nullptr &&
client->vtable->next != nullptr) {
return client->vtable->next(client, event, bytes_received);
}
gpr_log(GPR_ERROR,
"client or client->vtable has not been initialized properly");
return TSI_INVALID_ARGUMENT;
}
void alts_handshaker_client_destroy(alts_handshaker_client* client) {
if (client != nullptr) {
if (client->vtable != nullptr && client->vtable->destruct != nullptr) {
client->vtable->destruct(client);
}
gpr_free(client);
}
}

@ -0,0 +1,137 @@
/*
*
* Copyright 2018 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_CORE_TSI_ALTS_HANDSHAKER_ALTS_HANDSHAKER_CLIENT_H
#define GRPC_CORE_TSI_ALTS_HANDSHAKER_ALTS_HANDSHAKER_CLIENT_H
#include <grpc/support/port_platform.h>
#include <grpc/grpc.h>
#include "src/core/tsi/alts/handshaker/alts_tsi_event.h"
#define ALTS_SERVICE_METHOD "/grpc.gcp.HandshakerService/DoHandshake"
#define ALTS_APPLICATION_PROTOCOL "grpc"
#define ALTS_RECORD_PROTOCOL "ALTSRP_GCM_AES128_REKEY"
const size_t kAltsAes128GcmRekeyKeyLength = 44;
/**
* A ALTS handshaker client interface. It is used to communicate with
* ALTS handshaker service by scheduling a handshaker request that could be one
* of client_start, server_start, and next handshaker requests. All APIs in the
* header are thread-compatible.
*/
typedef struct alts_handshaker_client alts_handshaker_client;
/* A function that makes the grpc call to the handshaker service. */
typedef grpc_call_error (*alts_grpc_caller)(grpc_call* call, const grpc_op* ops,
size_t nops, void* tag);
/* V-table for ALTS handshaker client operations. */
typedef struct alts_handshaker_client_vtable {
tsi_result (*client_start)(alts_handshaker_client* client,
alts_tsi_event* event);
tsi_result (*server_start)(alts_handshaker_client* client,
alts_tsi_event* event, grpc_slice* bytes_received);
tsi_result (*next)(alts_handshaker_client* client, alts_tsi_event* event,
grpc_slice* bytes_received);
void (*destruct)(alts_handshaker_client* client);
} alts_handshaker_client_vtable;
struct alts_handshaker_client {
const alts_handshaker_client_vtable* vtable;
};
/**
* This method schedules a client_start handshaker request to ALTS handshaker
* service.
*
* - client: ALTS handshaker client instance.
* - event: ALTS TSI event instance.
*
* It returns TSI_OK on success and an error status code on failure.
*/
tsi_result alts_handshaker_client_start_client(alts_handshaker_client* client,
alts_tsi_event* event);
/**
* This method schedules a server_start handshaker request to ALTS handshaker
* service.
*
* - client: ALTS handshaker client instance.
* - event: ALTS TSI event instance.
* - bytes_received: bytes in out_frames returned from the peer's handshaker
* response.
*
* It returns TSI_OK on success and an error status code on failure.
*/
tsi_result alts_handshaker_client_start_server(alts_handshaker_client* client,
alts_tsi_event* event,
grpc_slice* bytes_received);
/**
* This method schedules a next handshaker request to ALTS handshaker service.
*
* - client: ALTS handshaker client instance.
* - event: ALTS TSI event instance.
* - bytes_received: bytes in out_frames returned from the peer's handshaker
* response.
*
* It returns TSI_OK on success and an error status code on failure.
*/
tsi_result alts_handshaker_client_next(alts_handshaker_client* client,
alts_tsi_event* event,
grpc_slice* bytes_received);
/**
* This method destroys a ALTS handshaker client.
*
* - client: a ALTS handshaker client instance.
*/
void alts_handshaker_client_destroy(alts_handshaker_client* client);
/**
* This method creates a ALTS handshaker client.
*
* - channel: grpc channel to ALTS handshaker service.
* - queue: grpc completion queue.
* - handshaker_service_url: address of ALTS handshaker service in the format of
* "host:port".
*
* It returns the created ALTS handshaker client on success, and NULL on
* failure.
*/
alts_handshaker_client* alts_grpc_handshaker_client_create(
grpc_channel* channel, grpc_completion_queue* queue,
const char* handshaker_service_url);
namespace grpc_core {
namespace internal {
/**
* Unsafe, use for testing only. It allows the caller to change the way that
* GRPC calls are made to the handshaker service.
*/
void alts_handshaker_client_set_grpc_caller_for_testing(
alts_handshaker_client* client, alts_grpc_caller caller);
} // namespace internal
} // namespace grpc_core
#endif /* GRPC_CORE_TSI_ALTS_HANDSHAKER_ALTS_HANDSHAKER_CLIENT_H */

@ -0,0 +1,520 @@
/*
*
* Copyright 2018 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 <grpc/support/port_platform.h>
#include "src/core/tsi/alts/handshaker/alts_handshaker_service_api.h"
#include <stdio.h>
#include <stdlib.h>
#include "src/core/tsi/alts/handshaker/transport_security_common_api.h"
/* HandshakerReq */
grpc_gcp_handshaker_req* grpc_gcp_handshaker_req_create(
grpc_gcp_handshaker_req_type type) {
grpc_gcp_handshaker_req* req =
static_cast<grpc_gcp_handshaker_req*>(gpr_zalloc(sizeof(*req)));
switch (type) {
case CLIENT_START_REQ:
req->has_client_start = true;
break;
case SERVER_START_REQ:
req->has_server_start = true;
break;
case NEXT_REQ:
req->has_next = true;
break;
}
return req;
}
void grpc_gcp_handshaker_req_destroy(grpc_gcp_handshaker_req* req) {
if (req == nullptr) {
return;
}
if (req->has_client_start) {
/* Destroy client_start request. */
destroy_repeated_field_list_identity(
static_cast<repeated_field*>(req->client_start.target_identities.arg));
destroy_repeated_field_list_string(static_cast<repeated_field*>(
req->client_start.application_protocols.arg));
destroy_repeated_field_list_string(
static_cast<repeated_field*>(req->client_start.record_protocols.arg));
if (req->client_start.has_local_identity) {
destroy_slice(static_cast<grpc_slice*>(
req->client_start.local_identity.hostname.arg));
destroy_slice(static_cast<grpc_slice*>(
req->client_start.local_identity.service_account.arg));
}
if (req->client_start.has_local_endpoint) {
destroy_slice(static_cast<grpc_slice*>(
req->client_start.local_endpoint.ip_address.arg));
}
if (req->client_start.has_remote_endpoint) {
destroy_slice(static_cast<grpc_slice*>(
req->client_start.remote_endpoint.ip_address.arg));
}
destroy_slice(static_cast<grpc_slice*>(req->client_start.target_name.arg));
} else if (req->has_server_start) {
/* Destroy server_start request. */
size_t i = 0;
for (i = 0; i < req->server_start.handshake_parameters_count; i++) {
destroy_repeated_field_list_identity(
static_cast<repeated_field*>(req->server_start.handshake_parameters[i]
.value.local_identities.arg));
destroy_repeated_field_list_string(
static_cast<repeated_field*>(req->server_start.handshake_parameters[i]
.value.record_protocols.arg));
}
destroy_repeated_field_list_string(static_cast<repeated_field*>(
req->server_start.application_protocols.arg));
if (req->server_start.has_local_endpoint) {
destroy_slice(static_cast<grpc_slice*>(
req->server_start.local_endpoint.ip_address.arg));
}
if (req->server_start.has_remote_endpoint) {
destroy_slice(static_cast<grpc_slice*>(
req->server_start.remote_endpoint.ip_address.arg));
}
destroy_slice(static_cast<grpc_slice*>(req->server_start.in_bytes.arg));
} else {
/* Destroy next request. */
destroy_slice(static_cast<grpc_slice*>(req->next.in_bytes.arg));
}
gpr_free(req);
}
bool grpc_gcp_handshaker_req_set_handshake_protocol(
grpc_gcp_handshaker_req* req,
grpc_gcp_handshake_protocol handshake_protocol) {
if (req == nullptr || !req->has_client_start) {
gpr_log(GPR_ERROR,
"Invalid arguments to "
"grpc_gcp_handshaker_req_set_handshake_protocol().");
return false;
}
req->client_start.has_handshake_security_protocol = true;
req->client_start.handshake_security_protocol = handshake_protocol;
return true;
}
bool grpc_gcp_handshaker_req_set_target_name(grpc_gcp_handshaker_req* req,
const char* target_name) {
if (req == nullptr || target_name == nullptr || !req->has_client_start) {
gpr_log(GPR_ERROR,
"Invalid arguments to "
"grpc_gcp_handshaker_req_set_target_name().");
return false;
}
grpc_slice* slice = create_slice(target_name, strlen(target_name));
req->client_start.target_name.arg = slice;
req->client_start.target_name.funcs.encode = encode_string_or_bytes_cb;
return true;
}
bool grpc_gcp_handshaker_req_add_application_protocol(
grpc_gcp_handshaker_req* req, const char* application_protocol) {
if (req == nullptr || application_protocol == nullptr || req->has_next) {
gpr_log(GPR_ERROR,
"Invalid arguments to "
"grpc_gcp_handshaker_req_add_application_protocol().");
return false;
}
grpc_slice* slice =
create_slice(application_protocol, strlen(application_protocol));
if (req->has_client_start) {
add_repeated_field(reinterpret_cast<repeated_field**>(
&req->client_start.application_protocols.arg),
slice);
req->client_start.application_protocols.funcs.encode =
encode_repeated_string_cb;
} else {
add_repeated_field(reinterpret_cast<repeated_field**>(
&req->server_start.application_protocols.arg),
slice);
req->server_start.application_protocols.funcs.encode =
encode_repeated_string_cb;
}
return true;
}
bool grpc_gcp_handshaker_req_add_record_protocol(grpc_gcp_handshaker_req* req,
const char* record_protocol) {
if (req == nullptr || record_protocol == nullptr || !req->has_client_start) {
gpr_log(GPR_ERROR,
"Invalid arguments to "
"grpc_gcp_handshaker_req_add_record_protocol().");
return false;
}
grpc_slice* slice = create_slice(record_protocol, strlen(record_protocol));
add_repeated_field(reinterpret_cast<repeated_field**>(
&req->client_start.record_protocols.arg),
slice);
req->client_start.record_protocols.funcs.encode = encode_repeated_string_cb;
return true;
}
static void set_identity_hostname(grpc_gcp_identity* identity,
const char* hostname) {
grpc_slice* slice = create_slice(hostname, strlen(hostname));
identity->hostname.arg = slice;
identity->hostname.funcs.encode = encode_string_or_bytes_cb;
}
static void set_identity_service_account(grpc_gcp_identity* identity,
const char* service_account) {
grpc_slice* slice = create_slice(service_account, strlen(service_account));
identity->service_account.arg = slice;
identity->service_account.funcs.encode = encode_string_or_bytes_cb;
}
bool grpc_gcp_handshaker_req_add_target_identity_hostname(
grpc_gcp_handshaker_req* req, const char* hostname) {
if (req == nullptr || hostname == nullptr || !req->has_client_start) {
gpr_log(GPR_ERROR,
"Invalid nullptr arguments to "
"grpc_gcp_handshaker_req_add_target_identity_hostname().");
return false;
}
grpc_gcp_identity* target_identity =
static_cast<grpc_gcp_identity*>(gpr_zalloc(sizeof(*target_identity)));
set_identity_hostname(target_identity, hostname);
req->client_start.target_identities.funcs.encode =
encode_repeated_identity_cb;
add_repeated_field(reinterpret_cast<repeated_field**>(
&req->client_start.target_identities.arg),
target_identity);
return true;
}
bool grpc_gcp_handshaker_req_add_target_identity_service_account(
grpc_gcp_handshaker_req* req, const char* service_account) {
if (req == nullptr || service_account == nullptr || !req->has_client_start) {
gpr_log(GPR_ERROR,
"Invalid nullptr arguments to "
"grpc_gcp_handshaker_req_add_target_identity_service_account().");
return false;
}
grpc_gcp_identity* target_identity =
static_cast<grpc_gcp_identity*>(gpr_zalloc(sizeof(*target_identity)));
set_identity_service_account(target_identity, service_account);
req->client_start.target_identities.funcs.encode =
encode_repeated_identity_cb;
add_repeated_field(reinterpret_cast<repeated_field**>(
&req->client_start.target_identities.arg),
target_identity);
return true;
}
bool grpc_gcp_handshaker_req_set_local_identity_hostname(
grpc_gcp_handshaker_req* req, const char* hostname) {
if (req == nullptr || hostname == nullptr || !req->has_client_start) {
gpr_log(GPR_ERROR,
"Invalid nullptr arguments to "
"grpc_gcp_handshaker_req_set_local_identity_hostname().");
return false;
}
req->client_start.has_local_identity = true;
set_identity_hostname(&req->client_start.local_identity, hostname);
return true;
}
bool grpc_gcp_handshaker_req_set_local_identity_service_account(
grpc_gcp_handshaker_req* req, const char* service_account) {
if (req == nullptr || service_account == nullptr || !req->has_client_start) {
gpr_log(GPR_ERROR,
"Invalid nullptr arguments to "
"grpc_gcp_handshaker_req_set_local_identity_service_account().");
return false;
}
req->client_start.has_local_identity = true;
set_identity_service_account(&req->client_start.local_identity,
service_account);
return true;
}
static void set_endpoint(grpc_gcp_endpoint* endpoint, const char* ip_address,
size_t port, grpc_gcp_network_protocol protocol) {
grpc_slice* slice = create_slice(ip_address, strlen(ip_address));
endpoint->ip_address.arg = slice;
endpoint->ip_address.funcs.encode = encode_string_or_bytes_cb;
endpoint->has_port = true;
endpoint->port = static_cast<int32_t>(port);
endpoint->has_protocol = true;
endpoint->protocol = protocol;
}
bool grpc_gcp_handshaker_req_set_rpc_versions(grpc_gcp_handshaker_req* req,
uint32_t max_major,
uint32_t max_minor,
uint32_t min_major,
uint32_t min_minor) {
if (req == nullptr || req->has_next) {
gpr_log(GPR_ERROR,
"Invalid arguments to "
"grpc_gcp_handshaker_req_set_rpc_versions().");
return false;
}
if (req->has_client_start) {
req->client_start.has_rpc_versions = true;
grpc_gcp_rpc_protocol_versions_set_max(&req->client_start.rpc_versions,
max_major, max_minor);
grpc_gcp_rpc_protocol_versions_set_min(&req->client_start.rpc_versions,
min_major, min_minor);
} else {
req->server_start.has_rpc_versions = true;
grpc_gcp_rpc_protocol_versions_set_max(&req->server_start.rpc_versions,
max_major, max_minor);
grpc_gcp_rpc_protocol_versions_set_min(&req->server_start.rpc_versions,
min_major, min_minor);
}
return true;
}
bool grpc_gcp_handshaker_req_set_local_endpoint(
grpc_gcp_handshaker_req* req, const char* ip_address, size_t port,
grpc_gcp_network_protocol protocol) {
if (req == nullptr || ip_address == nullptr || port > 65535 ||
req->has_next) {
gpr_log(GPR_ERROR,
"Invalid arguments to "
"grpc_gcp_handshaker_req_set_local_endpoint().");
return false;
}
if (req->has_client_start) {
req->client_start.has_local_endpoint = true;
set_endpoint(&req->client_start.local_endpoint, ip_address, port, protocol);
} else {
req->server_start.has_local_endpoint = true;
set_endpoint(&req->server_start.local_endpoint, ip_address, port, protocol);
}
return true;
}
bool grpc_gcp_handshaker_req_set_remote_endpoint(
grpc_gcp_handshaker_req* req, const char* ip_address, size_t port,
grpc_gcp_network_protocol protocol) {
if (req == nullptr || ip_address == nullptr || port > 65535 ||
req->has_next) {
gpr_log(GPR_ERROR,
"Invalid arguments to "
"grpc_gcp_handshaker_req_set_remote_endpoint().");
return false;
}
if (req->has_client_start) {
req->client_start.has_remote_endpoint = true;
set_endpoint(&req->client_start.remote_endpoint, ip_address, port,
protocol);
} else {
req->server_start.has_remote_endpoint = true;
set_endpoint(&req->server_start.remote_endpoint, ip_address, port,
protocol);
}
return true;
}
bool grpc_gcp_handshaker_req_set_in_bytes(grpc_gcp_handshaker_req* req,
const char* in_bytes, size_t size) {
if (req == nullptr || in_bytes == nullptr || req->has_client_start) {
gpr_log(GPR_ERROR,
"Invalid arguments to "
"grpc_gcp_handshaker_req_set_in_bytes().");
return false;
}
grpc_slice* slice = create_slice(in_bytes, size);
if (req->has_next) {
req->next.in_bytes.arg = slice;
req->next.in_bytes.funcs.encode = &encode_string_or_bytes_cb;
} else {
req->server_start.in_bytes.arg = slice;
req->server_start.in_bytes.funcs.encode = &encode_string_or_bytes_cb;
}
return true;
}
static grpc_gcp_server_handshake_parameters* server_start_find_param(
grpc_gcp_handshaker_req* req, int32_t key) {
size_t i = 0;
for (i = 0; i < req->server_start.handshake_parameters_count; i++) {
if (req->server_start.handshake_parameters[i].key == key) {
return &req->server_start.handshake_parameters[i].value;
}
}
req->server_start
.handshake_parameters[req->server_start.handshake_parameters_count]
.has_key = true;
req->server_start
.handshake_parameters[req->server_start.handshake_parameters_count]
.has_value = true;
req->server_start
.handshake_parameters[req->server_start.handshake_parameters_count++]
.key = key;
return &req->server_start
.handshake_parameters
[req->server_start.handshake_parameters_count - 1]
.value;
}
bool grpc_gcp_handshaker_req_param_add_record_protocol(
grpc_gcp_handshaker_req* req, grpc_gcp_handshake_protocol key,
const char* record_protocol) {
if (req == nullptr || record_protocol == nullptr || !req->has_server_start) {
gpr_log(GPR_ERROR,
"Invalid arguments to "
"grpc_gcp_handshaker_req_param_add_record_protocol().");
return false;
}
grpc_gcp_server_handshake_parameters* param =
server_start_find_param(req, key);
grpc_slice* slice = create_slice(record_protocol, strlen(record_protocol));
add_repeated_field(
reinterpret_cast<repeated_field**>(&param->record_protocols.arg), slice);
param->record_protocols.funcs.encode = &encode_repeated_string_cb;
return true;
}
bool grpc_gcp_handshaker_req_param_add_local_identity_hostname(
grpc_gcp_handshaker_req* req, grpc_gcp_handshake_protocol key,
const char* hostname) {
if (req == nullptr || hostname == nullptr || !req->has_server_start) {
gpr_log(GPR_ERROR,
"Invalid arguments to "
"grpc_gcp_handshaker_req_param_add_local_identity_hostname().");
return false;
}
grpc_gcp_server_handshake_parameters* param =
server_start_find_param(req, key);
grpc_gcp_identity* local_identity =
static_cast<grpc_gcp_identity*>(gpr_zalloc(sizeof(*local_identity)));
set_identity_hostname(local_identity, hostname);
add_repeated_field(
reinterpret_cast<repeated_field**>(&param->local_identities.arg),
local_identity);
param->local_identities.funcs.encode = &encode_repeated_identity_cb;
return true;
}
bool grpc_gcp_handshaker_req_param_add_local_identity_service_account(
grpc_gcp_handshaker_req* req, grpc_gcp_handshake_protocol key,
const char* service_account) {
if (req == nullptr || service_account == nullptr || !req->has_server_start) {
gpr_log(
GPR_ERROR,
"Invalid arguments to "
"grpc_gcp_handshaker_req_param_add_local_identity_service_account().");
return false;
}
grpc_gcp_server_handshake_parameters* param =
server_start_find_param(req, key);
grpc_gcp_identity* local_identity =
static_cast<grpc_gcp_identity*>(gpr_zalloc(sizeof(*local_identity)));
set_identity_service_account(local_identity, service_account);
add_repeated_field(
reinterpret_cast<repeated_field**>(&param->local_identities.arg),
local_identity);
param->local_identities.funcs.encode = &encode_repeated_identity_cb;
return true;
}
bool grpc_gcp_handshaker_req_encode(grpc_gcp_handshaker_req* req,
grpc_slice* slice) {
if (req == nullptr || slice == nullptr) {
gpr_log(GPR_ERROR,
"Invalid nullptr arguments to grpc_gcp_handshaker_req_encode().");
return false;
}
pb_ostream_t size_stream;
memset(&size_stream, 0, sizeof(pb_ostream_t));
if (!pb_encode(&size_stream, grpc_gcp_HandshakerReq_fields, req)) {
gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(&size_stream));
return false;
}
size_t encoded_length = size_stream.bytes_written;
*slice = grpc_slice_malloc(encoded_length);
pb_ostream_t output_stream =
pb_ostream_from_buffer(GRPC_SLICE_START_PTR(*slice), encoded_length);
if (!pb_encode(&output_stream, grpc_gcp_HandshakerReq_fields, req) != 0) {
gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(&output_stream));
return false;
}
return true;
}
/* HandshakerResp. */
grpc_gcp_handshaker_resp* grpc_gcp_handshaker_resp_create(void) {
grpc_gcp_handshaker_resp* resp =
static_cast<grpc_gcp_handshaker_resp*>(gpr_zalloc(sizeof(*resp)));
return resp;
}
void grpc_gcp_handshaker_resp_destroy(grpc_gcp_handshaker_resp* resp) {
if (resp != nullptr) {
destroy_slice(static_cast<grpc_slice*>(resp->out_frames.arg));
if (resp->has_status) {
destroy_slice(static_cast<grpc_slice*>(resp->status.details.arg));
}
if (resp->has_result) {
destroy_slice(
static_cast<grpc_slice*>(resp->result.application_protocol.arg));
destroy_slice(static_cast<grpc_slice*>(resp->result.record_protocol.arg));
destroy_slice(static_cast<grpc_slice*>(resp->result.key_data.arg));
if (resp->result.has_local_identity) {
destroy_slice(
static_cast<grpc_slice*>(resp->result.local_identity.hostname.arg));
destroy_slice(static_cast<grpc_slice*>(
resp->result.local_identity.service_account.arg));
}
if (resp->result.has_peer_identity) {
destroy_slice(
static_cast<grpc_slice*>(resp->result.peer_identity.hostname.arg));
destroy_slice(static_cast<grpc_slice*>(
resp->result.peer_identity.service_account.arg));
}
}
gpr_free(resp);
}
}
bool grpc_gcp_handshaker_resp_decode(grpc_slice encoded_handshaker_resp,
grpc_gcp_handshaker_resp* resp) {
if (resp == nullptr) {
gpr_log(GPR_ERROR,
"Invalid nullptr argument to grpc_gcp_handshaker_resp_decode().");
return false;
}
pb_istream_t stream =
pb_istream_from_buffer(GRPC_SLICE_START_PTR(encoded_handshaker_resp),
GRPC_SLICE_LENGTH(encoded_handshaker_resp));
resp->out_frames.funcs.decode = decode_string_or_bytes_cb;
resp->status.details.funcs.decode = decode_string_or_bytes_cb;
resp->result.application_protocol.funcs.decode = decode_string_or_bytes_cb;
resp->result.record_protocol.funcs.decode = decode_string_or_bytes_cb;
resp->result.key_data.funcs.decode = decode_string_or_bytes_cb;
resp->result.peer_identity.hostname.funcs.decode = decode_string_or_bytes_cb;
resp->result.peer_identity.service_account.funcs.decode =
decode_string_or_bytes_cb;
resp->result.local_identity.hostname.funcs.decode = decode_string_or_bytes_cb;
resp->result.local_identity.service_account.funcs.decode =
decode_string_or_bytes_cb;
if (!pb_decode(&stream, grpc_gcp_HandshakerResp_fields, resp)) {
gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(&stream));
return false;
}
return true;
}

@ -0,0 +1,323 @@
/*
*
* Copyright 2018 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_CORE_TSI_ALTS_HANDSHAKER_ALTS_HANDSHAKER_SERVICE_API_H
#define GRPC_CORE_TSI_ALTS_HANDSHAKER_ALTS_HANDSHAKER_SERVICE_API_H
#include <grpc/support/port_platform.h>
#include "src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.h"
/**
* An implementation of nanopb thin wrapper used to set/get and
* serialize/de-serialize of ALTS handshake requests and responses.
*
* All APIs in the header are thread-compatible. A typical usage of this API at
* the client side is as follows:
*
* -----------------------------------------------------------------------------
* // Create, populate, and serialize an ALTS client_start handshake request to
* // send to the server.
* grpc_gcp_handshaker_req* req =
* grpc_gcp_handshaker_req_create(CLIENT_START_REQ);
* grpc_gcp_handshaker_req_set_handshake_protocol(
req, grpc_gcp_HandshakeProtocol_ALTS);
* grpc_gcp_handshaker_req_add_application_protocol(req, "grpc");
* grpc_gcp_handshaker_req_add_record_protocol(req, "ALTSRP_GCM_AES128");
* grpc_slice client_slice;
* if (!grpc_gcp_handshaker_req_encode(req, &client_slice)) {
* fprintf(stderr, "ALTS handshake request encoding failed.";
* }
*
* // De-serialize a data stream received from the server, and store the result
* // at ALTS handshake response.
* grpc_gcp_handshaker_resp* resp = grpc_gcp_handshaker_resp_create();
* if (!grpc_gcp_handshaker_resp_decode(server_slice, resp)) {
* fprintf(stderr, "ALTS handshake response decoding failed.");
* }
* // To access a variable-length datatype field (i.e., pb_callback_t),
* // access its "arg" subfield (if it has been set).
* if (resp->out_frames.arg != nullptr) {
* grpc_slice* slice = resp->out_frames.arg;
* }
* // To access a fixed-length datatype field (i.e., not pb_calback_t),
* // access the field directly (if it has been set).
* if (resp->has_status && resp->status->has_code) {
* uint32_t code = resp->status->code;
* }
*------------------------------------------------------------------------------
*/
/**
* This method creates an ALTS handshake request.
*
* - type: an enum type value that can be either CLIENT_START_REQ,
* SERVER_START_REQ, or NEXT_REQ to indicate the created instance will be
* client_start, server_start, and next handshake request message
* respectively.
*
* The method returns a pointer to the created instance.
*/
grpc_gcp_handshaker_req* grpc_gcp_handshaker_req_create(
grpc_gcp_handshaker_req_type type);
/**
* This method sets the value for handshake_security_protocol field of ALTS
* client_start handshake request.
*
* - req: an ALTS handshake request.
* - handshake_protocol: a enum type value representing the handshake security
* protocol.
*
* The method returns true on success and false otherwise.
*/
bool grpc_gcp_handshaker_req_set_handshake_protocol(
grpc_gcp_handshaker_req* req,
grpc_gcp_handshake_protocol handshake_protocol);
/**
* This method sets the value for target_name field of ALTS client_start
* handshake request.
*
* - req: an ALTS handshake request.
* - target_name: a target name to be set.
*
* The method returns true on success and false otherwise.
*/
bool grpc_gcp_handshaker_req_set_target_name(grpc_gcp_handshaker_req* req,
const char* target_name);
/**
* This method adds an application protocol supported by the server (or
* client) to ALTS server_start (or client_start) handshake request.
*
* - req: an ALTS handshake request.
* - application_protocol: an application protocol (e.g., grpc) to be added.
*
* The method returns true on success and false otherwise.
*/
bool grpc_gcp_handshaker_req_add_application_protocol(
grpc_gcp_handshaker_req* req, const char* application_protocol);
/**
* This method adds a record protocol supported by the client to ALTS
* client_start handshake request.
*
* - req: an ALTS handshake request.
* - record_protocol: a record protocol (e.g., ALTSRP_GCM_AES128) to be
* added.
*
* The method returns true on success and false otherwise.
*/
bool grpc_gcp_handshaker_req_add_record_protocol(grpc_gcp_handshaker_req* req,
const char* record_protocol);
/**
* This method adds a target server identity represented as hostname and
* acceptable by a client to ALTS client_start handshake request.
*
* - req: an ALTS handshake request.
* - hostname: a string representation of hostname at the connection
* endpoint to be added.
*
* The method returns true on success and false otherwise.
*/
bool grpc_gcp_handshaker_req_add_target_identity_hostname(
grpc_gcp_handshaker_req* req, const char* hostname);
/**
* This method adds a target server identity represented as service account and
* acceptable by a client to ALTS client_start handshake request.
*
* - req: an ALTS handshake request.
* - service_account: a string representation of service account at the
* connection endpoint to be added.
*
* The method returns true on success and false otherwise.
*/
bool grpc_gcp_handshaker_req_add_target_identity_service_account(
grpc_gcp_handshaker_req* req, const char* service_account);
/**
* This method sets the hostname for local_identity field of ALTS client_start
* handshake request.
*
* - req: an ALTS handshake request.
* - hostname: a string representation of hostname.
*
* The method returns true on success and false otherwise.
*/
bool grpc_gcp_handshaker_req_set_local_identity_hostname(
grpc_gcp_handshaker_req* req, const char* hostname);
/**
* This method sets the service account for local_identity field of ALTS
* client_start handshake request.
*
* - req: an ALTS handshake request.
* - service_account: a string representation of service account.
*
* The method returns true on success and false otherwise.
*/
bool grpc_gcp_handshaker_req_set_local_identity_service_account(
grpc_gcp_handshaker_req* req, const char* service_account);
/**
* This method sets the value for local_endpoint field of either ALTS
* client_start or server_start handshake request.
*
* - req: an ALTS handshake request.
* - ip_address: a string representation of ip address associated with the
* local endpoint, that could be either IPv4 or IPv6.
* - port: a port number associated with the local endpoint.
* - protocol: a network protocol (e.g., TCP or UDP) associated with the
* local endpoint.
*
* The method returns true on success and false otherwise.
*/
bool grpc_gcp_handshaker_req_set_local_endpoint(
grpc_gcp_handshaker_req* req, const char* ip_address, size_t port,
grpc_gcp_network_protocol protocol);
/**
* This method sets the value for remote_endpoint field of either ALTS
* client_start or server_start handshake request.
*
* - req: an ALTS handshake request.
* - ip_address: a string representation of ip address associated with the
* remote endpoint, that could be either IPv4 or IPv6.
* - port: a port number associated with the remote endpoint.
* - protocol: a network protocol (e.g., TCP or UDP) associated with the
* remote endpoint.
*
* The method returns true on success and false otherwise.
*/
bool grpc_gcp_handshaker_req_set_remote_endpoint(
grpc_gcp_handshaker_req* req, const char* ip_address, size_t port,
grpc_gcp_network_protocol protocol);
/**
* This method sets the value for in_bytes field of either ALTS server_start or
* next handshake request.
*
* - req: an ALTS handshake request.
* - in_bytes: a buffer containing bytes taken from out_frames of the peer's
* ALTS handshake response. It is possible that the peer's out_frames are
* split into multiple handshake request messages.
* - size: size of in_bytes buffer.
*
* The method returns true on success and false otherwise.
*/
bool grpc_gcp_handshaker_req_set_in_bytes(grpc_gcp_handshaker_req* req,
const char* in_bytes, size_t size);
/**
* This method adds a record protocol to handshake parameters mapped by the
* handshake protocol for ALTS server_start handshake request.
*
* - req: an ALTS handshake request.
* - key: an enum type value representing a handshake security protocol.
* - record_protocol: a record protocol to be added.
*
* The method returns true on success and false otherwise.
*/
bool grpc_gcp_handshaker_req_param_add_record_protocol(
grpc_gcp_handshaker_req* req, grpc_gcp_handshake_protocol key,
const char* record_protocol);
/**
* This method adds a local identity represented as hostname to handshake
* parameters mapped by the handshake protocol for ALTS server_start handshake
* request.
*
* - req: an ALTS handshake request.
* - key: an enum type value representing a handshake security protocol.
* - hostname: a string representation of hostname to be added.
*
* The method returns true on success and false otherwise.
*/
bool grpc_gcp_handshaker_req_param_add_local_identity_hostname(
grpc_gcp_handshaker_req* req, grpc_gcp_handshake_protocol key,
const char* hostname);
/**
* This method adds a local identity represented as service account to handshake
* parameters mapped by the handshake protocol for ALTS server_start handshake
* request.
*
* - req: an ALTS handshake request.
* - key: an enum type value representing a handshake security protocol.
* - service_account: a string representation of service account to be added.
*
* The method returns true on success and false otherwise.
*/
bool grpc_gcp_handshaker_req_param_add_local_identity_service_account(
grpc_gcp_handshaker_req* req, grpc_gcp_handshake_protocol key,
const char* service_account);
/**
* This method sets the value for rpc_versions field of either ALTS
* client_start or server_start handshake request.
*
* - req: an ALTS handshake request.
* - max_major: a major version of maximum supported RPC version.
* - max_minor: a minor version of maximum supported RPC version.
* - min_major: a major version of minimum supported RPC version.
* - min_minor: a minor version of minimum supported RPC version.
*
* The method returns true on success and false otherwise.
*/
bool grpc_gcp_handshaker_req_set_rpc_versions(grpc_gcp_handshaker_req* req,
uint32_t max_major,
uint32_t max_minor,
uint32_t min_major,
uint32_t min_minor);
/**
* This method serializes an ALTS handshake request and returns a data stream.
*
* - req: an ALTS handshake request.
* - slice: a data stream where the serialized result will be written.
*
* The method returns true on success and false otherwise.
*/
bool grpc_gcp_handshaker_req_encode(grpc_gcp_handshaker_req* req,
grpc_slice* slice);
/* This method destroys an ALTS handshake request. */
void grpc_gcp_handshaker_req_destroy(grpc_gcp_handshaker_req* req);
/* This method creates an ALTS handshake response. */
grpc_gcp_handshaker_resp* grpc_gcp_handshaker_resp_create(void);
/**
* This method de-serializes a data stream and stores the result
* in an ALTS handshake response.
*
* - slice: a data stream containing a serialized ALTS handshake response.
* - resp: an ALTS handshake response used to hold de-serialized result.
*
* The method returns true on success and false otherwise.
*/
bool grpc_gcp_handshaker_resp_decode(grpc_slice slice,
grpc_gcp_handshaker_resp* resp);
/* This method destroys an ALTS handshake response. */
void grpc_gcp_handshaker_resp_destroy(grpc_gcp_handshaker_resp* resp);
#endif /* GRPC_CORE_TSI_ALTS_HANDSHAKER_ALTS_HANDSHAKER_SERVICE_API_H */

@ -0,0 +1,143 @@
/*
*
* Copyright 2018 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 <grpc/support/port_platform.h>
#include "src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.h"
void add_repeated_field(repeated_field** head, const void* data) {
repeated_field* field =
static_cast<repeated_field*>(gpr_zalloc(sizeof(*field)));
field->data = data;
if (*head == nullptr) {
*head = field;
(*head)->next = nullptr;
} else {
field->next = *head;
*head = field;
}
}
void destroy_repeated_field_list_identity(repeated_field* head) {
repeated_field* field = head;
while (field != nullptr) {
repeated_field* next_field = field->next;
const grpc_gcp_identity* identity =
static_cast<const grpc_gcp_identity*>(field->data);
destroy_slice(static_cast<grpc_slice*>(identity->hostname.arg));
destroy_slice(static_cast<grpc_slice*>(identity->service_account.arg));
gpr_free((void*)identity);
gpr_free(field);
field = next_field;
}
}
void destroy_repeated_field_list_string(repeated_field* head) {
repeated_field* field = head;
while (field != nullptr) {
repeated_field* next_field = field->next;
destroy_slice((grpc_slice*)field->data);
gpr_free(field);
field = next_field;
}
}
grpc_slice* create_slice(const char* data, size_t size) {
grpc_slice slice = grpc_slice_from_copied_buffer(data, size);
grpc_slice* cb_slice =
static_cast<grpc_slice*>(gpr_zalloc(sizeof(*cb_slice)));
memcpy(cb_slice, &slice, sizeof(*cb_slice));
return cb_slice;
}
void destroy_slice(grpc_slice* slice) {
if (slice != nullptr) {
grpc_slice_unref(*slice);
gpr_free(slice);
}
}
bool encode_string_or_bytes_cb(pb_ostream_t* stream, const pb_field_t* field,
void* const* arg) {
grpc_slice* slice = static_cast<grpc_slice*>(*arg);
if (!pb_encode_tag_for_field(stream, field)) return false;
return pb_encode_string(stream, GRPC_SLICE_START_PTR(*slice),
GRPC_SLICE_LENGTH(*slice));
}
bool encode_repeated_identity_cb(pb_ostream_t* stream, const pb_field_t* field,
void* const* arg) {
repeated_field* var = static_cast<repeated_field*>(*arg);
while (var != nullptr) {
if (!pb_encode_tag_for_field(stream, field)) return false;
if (!pb_encode_submessage(stream, grpc_gcp_Identity_fields,
(grpc_gcp_identity*)var->data))
return false;
var = var->next;
}
return true;
}
bool encode_repeated_string_cb(pb_ostream_t* stream, const pb_field_t* field,
void* const* arg) {
repeated_field* var = static_cast<repeated_field*>(*arg);
while (var != nullptr) {
if (!pb_encode_tag_for_field(stream, field)) return false;
const grpc_slice* slice = static_cast<const grpc_slice*>(var->data);
if (!pb_encode_string(stream, GRPC_SLICE_START_PTR(*slice),
GRPC_SLICE_LENGTH(*slice)))
return false;
var = var->next;
}
return true;
}
bool decode_string_or_bytes_cb(pb_istream_t* stream, const pb_field_t* field,
void** arg) {
grpc_slice slice = grpc_slice_malloc(stream->bytes_left);
grpc_slice* cb_slice =
static_cast<grpc_slice*>(gpr_zalloc(sizeof(*cb_slice)));
memcpy(cb_slice, &slice, sizeof(*cb_slice));
if (!pb_read(stream, GRPC_SLICE_START_PTR(*cb_slice), stream->bytes_left))
return false;
*arg = cb_slice;
return true;
}
bool decode_repeated_identity_cb(pb_istream_t* stream, const pb_field_t* field,
void** arg) {
grpc_gcp_identity* identity =
static_cast<grpc_gcp_identity*>(gpr_zalloc(sizeof(*identity)));
identity->hostname.funcs.decode = decode_string_or_bytes_cb;
identity->service_account.funcs.decode = decode_string_or_bytes_cb;
add_repeated_field(reinterpret_cast<repeated_field**>(arg), identity);
if (!pb_decode(stream, grpc_gcp_Identity_fields, identity)) return false;
return true;
}
bool decode_repeated_string_cb(pb_istream_t* stream, const pb_field_t* field,
void** arg) {
grpc_slice slice = grpc_slice_malloc(stream->bytes_left);
grpc_slice* cb_slice =
static_cast<grpc_slice*>(gpr_zalloc(sizeof(*cb_slice)));
memcpy(cb_slice, &slice, sizeof(grpc_slice));
if (!pb_read(stream, GRPC_SLICE_START_PTR(*cb_slice), stream->bytes_left))
return false;
add_repeated_field(reinterpret_cast<repeated_field**>(arg), cb_slice);
return true;
}

@ -0,0 +1,149 @@
/*
*
* Copyright 2018 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_CORE_TSI_ALTS_HANDSHAKER_ALTS_HANDSHAKER_SERVICE_API_UTIL_H
#define GRPC_CORE_TSI_ALTS_HANDSHAKER_ALTS_HANDSHAKER_SERVICE_API_UTIL_H
#include <grpc/support/port_platform.h>
#include "third_party/nanopb/pb_decode.h"
#include "third_party/nanopb/pb_encode.h"
#include <grpc/slice.h>
#include <grpc/slice_buffer.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "src/core/tsi/alts/handshaker/handshaker.pb.h"
/**
* An implementation of utility functions used to serialize/
* de-serialize ALTS handshake requests/responses. All APIs in the header
* are thread-compatible.
*/
/* Renaming of message/field structs generated by nanopb compiler. */
typedef grpc_gcp_HandshakeProtocol grpc_gcp_handshake_protocol;
typedef grpc_gcp_NetworkProtocol grpc_gcp_network_protocol;
typedef grpc_gcp_Identity grpc_gcp_identity;
typedef grpc_gcp_NextHandshakeMessageReq grpc_gcp_next_handshake_message_req;
typedef grpc_gcp_ServerHandshakeParameters grpc_gcp_server_handshake_parameters;
typedef grpc_gcp_Endpoint grpc_gcp_endpoint;
typedef grpc_gcp_StartServerHandshakeReq_HandshakeParametersEntry
grpc_gcp_handshake_parameters_entry;
typedef grpc_gcp_StartClientHandshakeReq grpc_gcp_start_client_handshake_req;
typedef grpc_gcp_StartServerHandshakeReq grpc_gcp_start_server_handshake_req;
typedef grpc_gcp_HandshakerReq grpc_gcp_handshaker_req;
typedef grpc_gcp_HandshakerResult grpc_gcp_handshaker_result;
typedef grpc_gcp_HandshakerStatus grpc_gcp_handshaker_status;
typedef grpc_gcp_HandshakerResp grpc_gcp_handshaker_resp;
typedef enum {
CLIENT_START_REQ = 0, /* StartClientHandshakeReq. */
SERVER_START_REQ = 1, /* StartServerHandshakeReq. */
NEXT_REQ = 2, /* NextHandshakeMessageReq. */
} grpc_gcp_handshaker_req_type;
/**
* A struct representing a repeated field. The struct is used to organize all
* instances of a specific repeated field into a linked list, which then will
* be used at encode/decode phase. For instance at the encode phase, the encode
* function will iterate through the list, encode each field, and then output
* the result to the stream.
*/
typedef struct repeated_field_ {
struct repeated_field_* next;
const void* data;
} repeated_field;
/**
* This method adds a repeated field to the head of repeated field list.
*
* - head: a head of repeated field list.
* - field: a repeated field to be added to the list.
*/
void add_repeated_field(repeated_field** head, const void* field);
/**
* This method destroys a repeated field list that consists of string type
* fields.
*
* - head: a head of repeated field list.
*/
void destroy_repeated_field_list_string(repeated_field* head);
/**
* This method destroys a repeated field list that consists of
* grpc_gcp_identity type fields.
*
* - head: a head of repeated field list.
*/
void destroy_repeated_field_list_identity(repeated_field* head);
/**
* This method creates a grpc_slice instance by copying a data buffer. It is
* similar to grpc_slice_from_copied_buffer() except that it returns an instance
* allocated from the heap.
*
* - data: a data buffer to be copied to grpc_slice instance.
* - size: size of data buffer.
*/
grpc_slice* create_slice(const char* data, size_t size);
/* This method destroys a grpc_slice instance. */
void destroy_slice(grpc_slice* slice);
/**
* The following encode/decode functions will be assigned to encode/decode
* function pointers of pb_callback_t struct (defined in
* //third_party/nanopb/pb.h), that represent a repeated field with a dynamic
* length (e.g., a string type or repeated field).
*/
/* This method is an encode callback function for a string or byte array. */
bool encode_string_or_bytes_cb(pb_ostream_t* stream, const pb_field_t* field,
void* const* arg);
/**
* This method is an encode callback function for a repeated grpc_gcp_identity
* field.
*/
bool encode_repeated_identity_cb(pb_ostream_t* stream, const pb_field_t* field,
void* const* arg);
/* This method is an encode callback function for a repeated string field. */
bool encode_repeated_string_cb(pb_ostream_t* stream, const pb_field_t* field,
void* const* arg);
/**
* This method is a decode callback function for a string or byte array field.
*/
bool decode_string_or_bytes_cb(pb_istream_t* stream, const pb_field_t* field,
void** arg);
/**
* This method is a decode callback function for a repeated grpc_gcp_identity
* field.
*/
bool decode_repeated_identity_cb(pb_istream_t* stream, const pb_field_t* field,
void** arg);
/* This method is a decode callback function for a repeated string field. */
bool decode_repeated_string_cb(pb_istream_t* stream, const pb_field_t* field,
void** arg);
#endif /* GRPC_CORE_TSI_ALTS_HANDSHAKER_ALTS_HANDSHAKER_SERVICE_API_UTIL_H */

@ -0,0 +1,73 @@
/*
*
* Copyright 2018 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 <grpc/support/port_platform.h>
#include "src/core/tsi/alts/handshaker/alts_tsi_event.h"
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
tsi_result alts_tsi_event_create(alts_tsi_handshaker* handshaker,
tsi_handshaker_on_next_done_cb cb,
void* user_data,
grpc_alts_credentials_options* options,
grpc_slice target_name,
alts_tsi_event** event) {
if (event == nullptr || handshaker == nullptr || cb == nullptr) {
gpr_log(GPR_ERROR, "Invalid arguments to alts_tsi_event_create()");
return TSI_INVALID_ARGUMENT;
}
alts_tsi_event* e = static_cast<alts_tsi_event*>(gpr_zalloc(sizeof(*e)));
e->handshaker = handshaker;
e->cb = cb;
e->user_data = user_data;
e->options = grpc_alts_credentials_options_copy(options);
e->target_name = grpc_slice_copy(target_name);
grpc_metadata_array_init(&e->initial_metadata);
grpc_metadata_array_init(&e->trailing_metadata);
*event = e;
return TSI_OK;
}
void alts_tsi_event_dispatch_to_handshaker(alts_tsi_event* event, bool is_ok) {
if (event == nullptr) {
gpr_log(
GPR_ERROR,
"ALTS TSI event is nullptr in alts_tsi_event_dispatch_to_handshaker()");
return;
}
alts_tsi_handshaker_handle_response(event->handshaker, event->recv_buffer,
event->status, &event->details, event->cb,
event->user_data, is_ok);
}
void alts_tsi_event_destroy(alts_tsi_event* event) {
if (event == nullptr) {
return;
}
grpc_byte_buffer_destroy(event->send_buffer);
grpc_byte_buffer_destroy(event->recv_buffer);
grpc_metadata_array_destroy(&event->initial_metadata);
grpc_metadata_array_destroy(&event->trailing_metadata);
grpc_slice_unref(event->details);
grpc_slice_unref(event->target_name);
grpc_alts_credentials_options_destroy(event->options);
gpr_free(event);
}

@ -0,0 +1,93 @@
/*
*
* Copyright 2018 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_CORE_TSI_ALTS_HANDSHAKER_ALTS_TSI_EVENT_H
#define GRPC_CORE_TSI_ALTS_HANDSHAKER_ALTS_TSI_EVENT_H
#include <grpc/support/port_platform.h>
#include <grpc/byte_buffer.h>
#include <grpc/byte_buffer_reader.h>
#include "src/core/tsi/alts/handshaker/alts_tsi_handshaker.h"
#include "src/core/tsi/transport_security_interface.h"
/**
* A ALTS TSI event interface. In asynchronous implementation of
* tsi_handshaker_next(), the function will exit after scheduling a handshaker
* request to ALTS handshaker service without waiting for response to return.
* The event is used to link the scheduled handshaker request with the
* corresponding response so that enough context information can be inferred
* from it to handle the response. All APIs in the header are thread-compatible.
*/
/**
* Main struct for ALTS TSI event. It retains ownership on send_buffer and
* recv_buffer, but not on handshaker.
*/
typedef struct alts_tsi_event {
alts_tsi_handshaker* handshaker;
grpc_byte_buffer* send_buffer;
grpc_byte_buffer* recv_buffer;
grpc_status_code status;
grpc_slice details;
grpc_metadata_array initial_metadata;
grpc_metadata_array trailing_metadata;
tsi_handshaker_on_next_done_cb cb;
void* user_data;
grpc_alts_credentials_options* options;
grpc_slice target_name;
} alts_tsi_event;
/**
* This method creates a ALTS TSI event.
*
* - handshaker: ALTS TSI handshaker instance associated with the event to be
* created. The created event does not own the handshaker instance.
* - cb: callback function to be called when handling data received from ALTS
* handshaker service.
* - user_data: argument to callback function.
* - options: ALTS credentials options.
* - target_name: name of endpoint used for secure naming check.
* - event: address of ALTS TSI event instance to be returned from the method.
*
* It returns TSI_OK on success and an error status code on failure.
*/
tsi_result alts_tsi_event_create(alts_tsi_handshaker* handshaker,
tsi_handshaker_on_next_done_cb cb,
void* user_data,
grpc_alts_credentials_options* options,
grpc_slice target_name,
alts_tsi_event** event);
/**
* This method dispatches a ALTS TSI event received from the handshaker service,
* and a boolean flag indicating if the event is valid to read to ALTS TSI
* handshaker to process. It is called by TSI thread.
*
* - event: ALTS TSI event instance.
* - is_ok: a boolean value indicating if the event is valid to read.
*/
void alts_tsi_event_dispatch_to_handshaker(alts_tsi_event* event, bool is_ok);
/**
* This method destroys the ALTS TSI event.
*/
void alts_tsi_event_destroy(alts_tsi_event* event);
#endif /* GRPC_CORE_TSI_ALTS_HANDSHAKER_ALTS_TSI_EVENT_H */

@ -0,0 +1,483 @@
/*
*
* Copyright 2018 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 <grpc/support/port_platform.h>
#include "src/core/tsi/alts/handshaker/alts_tsi_handshaker.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/sync.h>
#include <grpc/support/thd_id.h>
#include "src/core/lib/gpr/host_port.h"
#include "src/core/lib/gprpp/thd.h"
#include "src/core/tsi/alts/frame_protector/alts_frame_protector.h"
#include "src/core/tsi/alts/handshaker/alts_handshaker_client.h"
#include "src/core/tsi/alts/handshaker/alts_tsi_utils.h"
#include "src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.h"
#include "src/core/tsi/alts_transport_security.h"
#define TSI_ALTS_INITIAL_BUFFER_SIZE 256
static alts_shared_resource* kSharedResource = alts_get_shared_resource();
/* Main struct for ALTS TSI handshaker. */
typedef struct alts_tsi_handshaker {
tsi_handshaker base;
alts_handshaker_client* client;
grpc_slice recv_bytes;
grpc_slice target_name;
unsigned char* buffer;
size_t buffer_size;
bool is_client;
bool has_sent_start_message;
grpc_alts_credentials_options* options;
} alts_tsi_handshaker;
/* Main struct for ALTS TSI handshaker result. */
typedef struct alts_tsi_handshaker_result {
tsi_handshaker_result base;
char* peer_identity;
char* key_data;
unsigned char* unused_bytes;
size_t unused_bytes_size;
grpc_slice rpc_versions;
bool is_client;
} alts_tsi_handshaker_result;
static tsi_result handshaker_result_extract_peer(
const tsi_handshaker_result* self, tsi_peer* peer) {
if (self == nullptr || peer == nullptr) {
gpr_log(GPR_ERROR, "Invalid argument to handshaker_result_extract_peer()");
return TSI_INVALID_ARGUMENT;
}
alts_tsi_handshaker_result* result =
reinterpret_cast<alts_tsi_handshaker_result*>(
const_cast<tsi_handshaker_result*>(self));
GPR_ASSERT(kTsiAltsNumOfPeerProperties == 3);
tsi_result ok = tsi_construct_peer(kTsiAltsNumOfPeerProperties, peer);
int index = 0;
if (ok != TSI_OK) {
gpr_log(GPR_ERROR, "Failed to construct tsi peer");
return ok;
}
GPR_ASSERT(&peer->properties[index] != nullptr);
ok = tsi_construct_string_peer_property_from_cstring(
TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_ALTS_CERTIFICATE_TYPE,
&peer->properties[index]);
if (ok != TSI_OK) {
tsi_peer_destruct(peer);
gpr_log(GPR_ERROR, "Failed to set tsi peer property");
return ok;
}
index++;
GPR_ASSERT(&peer->properties[index] != nullptr);
ok = tsi_construct_string_peer_property_from_cstring(
TSI_ALTS_SERVICE_ACCOUNT_PEER_PROPERTY, result->peer_identity,
&peer->properties[index]);
if (ok != TSI_OK) {
tsi_peer_destruct(peer);
gpr_log(GPR_ERROR, "Failed to set tsi peer property");
}
index++;
GPR_ASSERT(&peer->properties[index] != nullptr);
ok = tsi_construct_string_peer_property(
TSI_ALTS_RPC_VERSIONS,
reinterpret_cast<char*>(GRPC_SLICE_START_PTR(result->rpc_versions)),
GRPC_SLICE_LENGTH(result->rpc_versions), &peer->properties[2]);
if (ok != TSI_OK) {
tsi_peer_destruct(peer);
gpr_log(GPR_ERROR, "Failed to set tsi peer property");
}
GPR_ASSERT(++index == kTsiAltsNumOfPeerProperties);
return ok;
}
static tsi_result handshaker_result_create_zero_copy_grpc_protector(
const tsi_handshaker_result* self, size_t* max_output_protected_frame_size,
tsi_zero_copy_grpc_protector** protector) {
if (self == nullptr || protector == nullptr) {
gpr_log(GPR_ERROR,
"Invalid arguments to create_zero_copy_grpc_protector()");
return TSI_INVALID_ARGUMENT;
}
alts_tsi_handshaker_result* result =
reinterpret_cast<alts_tsi_handshaker_result*>(
const_cast<tsi_handshaker_result*>(self));
tsi_result ok = alts_zero_copy_grpc_protector_create(
reinterpret_cast<const uint8_t*>(result->key_data),
kAltsAes128GcmRekeyKeyLength, /*is_rekey=*/true, result->is_client,
/*is_integrity_only=*/false, max_output_protected_frame_size, protector);
if (ok != TSI_OK) {
gpr_log(GPR_ERROR, "Failed to create zero-copy grpc protector");
}
return ok;
}
static tsi_result handshaker_result_create_frame_protector(
const tsi_handshaker_result* self, size_t* max_output_protected_frame_size,
tsi_frame_protector** protector) {
if (self == nullptr || protector == nullptr) {
gpr_log(GPR_ERROR,
"Invalid arguments to handshaker_result_create_frame_protector()");
return TSI_INVALID_ARGUMENT;
}
alts_tsi_handshaker_result* result =
reinterpret_cast<alts_tsi_handshaker_result*>(
const_cast<tsi_handshaker_result*>(self));
tsi_result ok = alts_create_frame_protector(
reinterpret_cast<const uint8_t*>(result->key_data),
kAltsAes128GcmRekeyKeyLength, result->is_client, /*is_rekey=*/true,
max_output_protected_frame_size, protector);
if (ok != TSI_OK) {
gpr_log(GPR_ERROR, "Failed to create frame protector");
}
return ok;
}
static tsi_result handshaker_result_get_unused_bytes(
const tsi_handshaker_result* self, const unsigned char** bytes,
size_t* bytes_size) {
if (self == nullptr || bytes == nullptr || bytes_size == nullptr) {
gpr_log(GPR_ERROR,
"Invalid arguments to handshaker_result_get_unused_bytes()");
return TSI_INVALID_ARGUMENT;
}
alts_tsi_handshaker_result* result =
reinterpret_cast<alts_tsi_handshaker_result*>(
const_cast<tsi_handshaker_result*>(self));
*bytes = result->unused_bytes;
*bytes_size = result->unused_bytes_size;
return TSI_OK;
}
static void handshaker_result_destroy(tsi_handshaker_result* self) {
if (self == nullptr) {
return;
}
alts_tsi_handshaker_result* result =
reinterpret_cast<alts_tsi_handshaker_result*>(
const_cast<tsi_handshaker_result*>(self));
gpr_free(result->peer_identity);
gpr_free(result->key_data);
gpr_free(result->unused_bytes);
grpc_slice_unref(result->rpc_versions);
gpr_free(result);
}
static const tsi_handshaker_result_vtable result_vtable = {
handshaker_result_extract_peer,
handshaker_result_create_zero_copy_grpc_protector,
handshaker_result_create_frame_protector,
handshaker_result_get_unused_bytes, handshaker_result_destroy};
static tsi_result create_handshaker_result(grpc_gcp_handshaker_resp* resp,
bool is_client,
tsi_handshaker_result** self) {
if (self == nullptr || resp == nullptr) {
gpr_log(GPR_ERROR, "Invalid arguments to create_handshaker_result()");
return TSI_INVALID_ARGUMENT;
}
grpc_slice* key = static_cast<grpc_slice*>(resp->result.key_data.arg);
GPR_ASSERT(key != nullptr);
grpc_slice* identity =
static_cast<grpc_slice*>(resp->result.peer_identity.service_account.arg);
if (identity == nullptr) {
gpr_log(GPR_ERROR, "Invalid service account");
return TSI_FAILED_PRECONDITION;
}
if (GRPC_SLICE_LENGTH(*key) < kAltsAes128GcmRekeyKeyLength) {
gpr_log(GPR_ERROR, "Bad key length");
return TSI_FAILED_PRECONDITION;
}
alts_tsi_handshaker_result* result =
static_cast<alts_tsi_handshaker_result*>(gpr_zalloc(sizeof(*result)));
result->key_data =
static_cast<char*>(gpr_zalloc(kAltsAes128GcmRekeyKeyLength));
memcpy(result->key_data, GRPC_SLICE_START_PTR(*key),
kAltsAes128GcmRekeyKeyLength);
result->peer_identity = grpc_slice_to_c_string(*identity);
if (!resp->result.has_peer_rpc_versions) {
gpr_log(GPR_ERROR, "Peer does not set RPC protocol versions.");
return TSI_FAILED_PRECONDITION;
}
if (!grpc_gcp_rpc_protocol_versions_encode(&resp->result.peer_rpc_versions,
&result->rpc_versions)) {
gpr_log(GPR_ERROR, "Failed to serialize peer's RPC protocol versions.");
return TSI_FAILED_PRECONDITION;
}
result->is_client = is_client;
result->base.vtable = &result_vtable;
*self = &result->base;
return TSI_OK;
}
static tsi_result handshaker_next(
tsi_handshaker* self, const unsigned char* received_bytes,
size_t received_bytes_size, const unsigned char** bytes_to_send,
size_t* bytes_to_send_size, tsi_handshaker_result** result,
tsi_handshaker_on_next_done_cb cb, void* user_data) {
if (self == nullptr || cb == nullptr) {
gpr_log(GPR_ERROR, "Invalid arguments to handshaker_next()");
return TSI_INVALID_ARGUMENT;
}
alts_tsi_handshaker* handshaker =
reinterpret_cast<alts_tsi_handshaker*>(self);
tsi_result ok = TSI_OK;
alts_tsi_event* event = nullptr;
ok = alts_tsi_event_create(handshaker, cb, user_data, handshaker->options,
handshaker->target_name, &event);
if (ok != TSI_OK) {
gpr_log(GPR_ERROR, "Failed to create ALTS TSI event");
return ok;
}
grpc_slice slice = (received_bytes == nullptr || received_bytes_size == 0)
? grpc_empty_slice()
: grpc_slice_from_copied_buffer(
reinterpret_cast<const char*>(received_bytes),
received_bytes_size);
if (!handshaker->has_sent_start_message) {
ok = handshaker->is_client
? alts_handshaker_client_start_client(handshaker->client, event)
: alts_handshaker_client_start_server(handshaker->client, event,
&slice);
handshaker->has_sent_start_message = true;
} else {
if (!GRPC_SLICE_IS_EMPTY(handshaker->recv_bytes)) {
grpc_slice_unref(handshaker->recv_bytes);
}
handshaker->recv_bytes = grpc_slice_ref(slice);
ok = alts_handshaker_client_next(handshaker->client, event, &slice);
}
grpc_slice_unref(slice);
if (ok != TSI_OK) {
gpr_log(GPR_ERROR, "Failed to schedule ALTS handshaker requests");
return ok;
}
return TSI_ASYNC;
}
static void handshaker_destroy(tsi_handshaker* self) {
if (self == nullptr) {
return;
}
alts_tsi_handshaker* handshaker =
reinterpret_cast<alts_tsi_handshaker*>(self);
alts_handshaker_client_destroy(handshaker->client);
grpc_slice_unref(handshaker->recv_bytes);
grpc_slice_unref(handshaker->target_name);
grpc_alts_credentials_options_destroy(handshaker->options);
gpr_free(handshaker->buffer);
gpr_free(handshaker);
}
static const tsi_handshaker_vtable handshaker_vtable = {
nullptr, nullptr, nullptr, nullptr, nullptr, handshaker_destroy,
handshaker_next};
static void thread_worker(void* arg) {
while (true) {
grpc_event event = grpc_completion_queue_next(
kSharedResource->cq, gpr_inf_future(GPR_CLOCK_REALTIME), nullptr);
GPR_ASSERT(event.type != GRPC_QUEUE_TIMEOUT);
if (event.type == GRPC_QUEUE_SHUTDOWN) {
/* signal alts_tsi_shutdown() to destroy completion queue. */
grpc_tsi_alts_signal_for_cq_destroy();
break;
}
/* event.type == GRPC_OP_COMPLETE. */
alts_tsi_event* alts_event = static_cast<alts_tsi_event*>(event.tag);
alts_tsi_event_dispatch_to_handshaker(alts_event, event.success);
alts_tsi_event_destroy(alts_event);
}
}
static void init_shared_resources(const char* handshaker_service_url) {
GPR_ASSERT(handshaker_service_url != nullptr);
gpr_mu_lock(&kSharedResource->mu);
if (kSharedResource->channel == nullptr) {
gpr_cv_init(&kSharedResource->cv);
kSharedResource->channel =
grpc_insecure_channel_create(handshaker_service_url, nullptr, nullptr);
kSharedResource->cq = grpc_completion_queue_create_for_next(nullptr);
kSharedResource->thread =
grpc_core::Thread("alts_tsi_handshaker", &thread_worker, nullptr);
kSharedResource->thread.Start();
}
gpr_mu_unlock(&kSharedResource->mu);
}
tsi_result alts_tsi_handshaker_create(
const grpc_alts_credentials_options* options, const char* target_name,
const char* handshaker_service_url, bool is_client, tsi_handshaker** self) {
if (handshaker_service_url == nullptr || self == nullptr ||
options == nullptr || (is_client && target_name == nullptr)) {
gpr_log(GPR_ERROR, "Invalid arguments to alts_tsi_handshaker_create()");
return TSI_INVALID_ARGUMENT;
}
init_shared_resources(handshaker_service_url);
alts_handshaker_client* client = alts_grpc_handshaker_client_create(
kSharedResource->channel, kSharedResource->cq, handshaker_service_url);
if (client == nullptr) {
gpr_log(GPR_ERROR, "Failed to create ALTS handshaker client");
return TSI_FAILED_PRECONDITION;
}
alts_tsi_handshaker* handshaker =
static_cast<alts_tsi_handshaker*>(gpr_zalloc(sizeof(*handshaker)));
handshaker->client = client;
handshaker->buffer_size = TSI_ALTS_INITIAL_BUFFER_SIZE;
handshaker->buffer =
static_cast<unsigned char*>(gpr_zalloc(handshaker->buffer_size));
handshaker->is_client = is_client;
handshaker->has_sent_start_message = false;
handshaker->target_name = target_name == nullptr
? grpc_empty_slice()
: grpc_slice_from_static_string(target_name);
handshaker->options = grpc_alts_credentials_options_copy(options);
handshaker->base.vtable = &handshaker_vtable;
*self = &handshaker->base;
return TSI_OK;
}
static bool is_handshake_finished_properly(grpc_gcp_handshaker_resp* resp) {
GPR_ASSERT(resp != nullptr);
if (resp->has_result) {
return true;
}
return false;
}
static void set_unused_bytes(tsi_handshaker_result* self,
grpc_slice* recv_bytes, size_t bytes_consumed) {
GPR_ASSERT(recv_bytes != nullptr && self != nullptr);
if (GRPC_SLICE_LENGTH(*recv_bytes) == bytes_consumed) {
return;
}
alts_tsi_handshaker_result* result =
reinterpret_cast<alts_tsi_handshaker_result*>(self);
result->unused_bytes_size = GRPC_SLICE_LENGTH(*recv_bytes) - bytes_consumed;
result->unused_bytes =
static_cast<unsigned char*>(gpr_zalloc(result->unused_bytes_size));
memcpy(result->unused_bytes,
GRPC_SLICE_START_PTR(*recv_bytes) + bytes_consumed,
result->unused_bytes_size);
}
void alts_tsi_handshaker_handle_response(alts_tsi_handshaker* handshaker,
grpc_byte_buffer* recv_buffer,
grpc_status_code status,
grpc_slice* details,
tsi_handshaker_on_next_done_cb cb,
void* user_data, bool is_ok) {
/* Invalid input check. */
if (cb == nullptr) {
gpr_log(GPR_ERROR,
"cb is nullptr in alts_tsi_handshaker_handle_response()");
return;
}
if (handshaker == nullptr || recv_buffer == nullptr) {
gpr_log(GPR_ERROR,
"Invalid arguments to alts_tsi_handshaker_handle_response()");
cb(TSI_INTERNAL_ERROR, user_data, nullptr, 0, nullptr);
return;
}
/* Failed grpc call check. */
if (!is_ok || status != GRPC_STATUS_OK) {
gpr_log(GPR_ERROR, "grpc call made to handshaker service failed");
if (details != nullptr) {
char* error_details = grpc_slice_to_c_string(*details);
gpr_log(GPR_ERROR, "error details:%s", error_details);
gpr_free(error_details);
}
cb(TSI_INTERNAL_ERROR, user_data, nullptr, 0, nullptr);
return;
}
grpc_gcp_handshaker_resp* resp =
alts_tsi_utils_deserialize_response(recv_buffer);
/* Invalid handshaker response check. */
if (resp == nullptr) {
gpr_log(GPR_ERROR, "alts_tsi_utils_deserialize_response() failed");
cb(TSI_DATA_CORRUPTED, user_data, nullptr, 0, nullptr);
return;
}
grpc_slice* slice = static_cast<grpc_slice*>(resp->out_frames.arg);
unsigned char* bytes_to_send = nullptr;
size_t bytes_to_send_size = 0;
if (slice != nullptr) {
bytes_to_send_size = GRPC_SLICE_LENGTH(*slice);
while (bytes_to_send_size > handshaker->buffer_size) {
handshaker->buffer_size *= 2;
handshaker->buffer = static_cast<unsigned char*>(
gpr_realloc(handshaker->buffer, handshaker->buffer_size));
}
memcpy(handshaker->buffer, GRPC_SLICE_START_PTR(*slice),
bytes_to_send_size);
bytes_to_send = handshaker->buffer;
}
tsi_handshaker_result* result = nullptr;
if (is_handshake_finished_properly(resp)) {
create_handshaker_result(resp, handshaker->is_client, &result);
set_unused_bytes(result, &handshaker->recv_bytes, resp->bytes_consumed);
}
grpc_status_code code = static_cast<grpc_status_code>(resp->status.code);
grpc_gcp_handshaker_resp_destroy(resp);
cb(alts_tsi_utils_convert_to_tsi_result(code), user_data, bytes_to_send,
bytes_to_send_size, result);
}
namespace grpc_core {
namespace internal {
bool alts_tsi_handshaker_get_has_sent_start_message_for_testing(
alts_tsi_handshaker* handshaker) {
GPR_ASSERT(handshaker != nullptr);
return handshaker->has_sent_start_message;
}
bool alts_tsi_handshaker_get_is_client_for_testing(
alts_tsi_handshaker* handshaker) {
GPR_ASSERT(handshaker != nullptr);
return handshaker->is_client;
}
void alts_tsi_handshaker_set_recv_bytes_for_testing(
alts_tsi_handshaker* handshaker, grpc_slice* slice) {
GPR_ASSERT(handshaker != nullptr && slice != nullptr);
handshaker->recv_bytes = grpc_slice_ref(*slice);
}
grpc_slice alts_tsi_handshaker_get_recv_bytes_for_testing(
alts_tsi_handshaker* handshaker) {
GPR_ASSERT(handshaker != nullptr);
return handshaker->recv_bytes;
}
void alts_tsi_handshaker_set_client_for_testing(
alts_tsi_handshaker* handshaker, alts_handshaker_client* client) {
GPR_ASSERT(handshaker != nullptr && client != nullptr);
alts_handshaker_client_destroy(handshaker->client);
handshaker->client = client;
}
} // namespace internal
} // namespace grpc_core

@ -0,0 +1,83 @@
/*
*
* Copyright 2018 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_CORE_TSI_ALTS_HANDSHAKER_ALTS_TSI_HANDSHAKER_H
#define GRPC_CORE_TSI_ALTS_HANDSHAKER_ALTS_TSI_HANDSHAKER_H
#include <grpc/support/port_platform.h>
#include <grpc/grpc.h>
#include "src/core/lib/security/credentials/alts/grpc_alts_credentials_options.h"
#include "src/core/tsi/alts_transport_security.h"
#include "src/core/tsi/transport_security.h"
#include "src/core/tsi/transport_security_interface.h"
#define TSI_ALTS_SERVICE_ACCOUNT_PEER_PROPERTY "service_accont"
#define TSI_ALTS_CERTIFICATE_TYPE "ALTS"
#define TSI_ALTS_RPC_VERSIONS "rpc_versions"
const size_t kTsiAltsNumOfPeerProperties = 3;
/**
* Main struct for ALTS TSI handshaker. All APIs in the header are
* thread-comptabile.
*/
typedef struct alts_tsi_handshaker alts_tsi_handshaker;
/**
* This method creates a ALTS TSI handshaker instance.
*
* - options: ALTS credentials options containing information passed from TSI
* caller (e.g., rpc protocol versions).
* - target_name: the name of the endpoint that the channel is connecting to,
* and will be used for secure naming check.
* - handshaker_service_url: address of ALTS handshaker service in the format of
* "host:port".
* - is_client: boolean value indicating if the handshaker is used at the client
* (is_client = true) or server (is_client = false) side.
* - self: address of ALTS TSI handshaker instance to be returned from the
* method.
*
* It returns TSI_OK on success and an error status code on failure.
*/
tsi_result alts_tsi_handshaker_create(
const grpc_alts_credentials_options* options, const char* target_name,
const char* handshaker_service_url, bool is_client, tsi_handshaker** self);
/**
* This method handles handshaker response returned from ALTS handshaker
* service.
*
* - handshaker: ALTS TSI handshaker instance.
* - recv_buffer: buffer holding data received from the handshaker service.
* - status: status of the grpc call made to the handshaker service.
* - details: error details of the grpc call made to the handshaker service.
* - cb: callback function of ALTS TSI event.
* - user_data: argument of callback function.
* - is_ok: a boolean value indicating if the handshaker response is ok to read.
*
*/
void alts_tsi_handshaker_handle_response(alts_tsi_handshaker* handshaker,
grpc_byte_buffer* recv_buffer,
grpc_status_code status,
grpc_slice* details,
tsi_handshaker_on_next_done_cb cb,
void* user_data, bool is_ok);
#endif /* GRPC_CORE_TSI_ALTS_HANDSHAKER_ALTS_TSI_HANDSHAKER_H */

@ -0,0 +1,52 @@
/*
*
* Copyright 2018 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_CORE_TSI_ALTS_HANDSHAKER_ALTS_TSI_HANDSHAKER_PRIVATE_H
#define GRPC_CORE_TSI_ALTS_HANDSHAKER_ALTS_TSI_HANDSHAKER_PRIVATE_H
#include <grpc/support/port_platform.h>
#include "src/core/tsi/alts/handshaker/alts_handshaker_client.h"
namespace grpc_core {
namespace internal {
/**
* Unsafe, use for testing only. It allows the caller to change the way the
* ALTS TSI handshaker schedules handshaker requests.
*/
void alts_tsi_handshaker_set_client_for_testing(alts_tsi_handshaker* handshaker,
alts_handshaker_client* client);
/* For testing only. */
bool alts_tsi_handshaker_get_has_sent_start_message_for_testing(
alts_tsi_handshaker* handshaker);
bool alts_tsi_handshaker_get_is_client_for_testing(
alts_tsi_handshaker* handshaker);
void alts_tsi_handshaker_set_recv_bytes_for_testing(
alts_tsi_handshaker* handshaker, grpc_slice* slice);
grpc_slice alts_tsi_handshaker_get_recv_bytes_for_testing(
alts_tsi_handshaker* handshaker);
} // namespace internal
} // namespace grpc_core
#endif /* GRPC_CORE_TSI_ALTS_HANDSHAKER_ALTS_TSI_HANDSHAKER_PRIVATE_H */

@ -0,0 +1,58 @@
/*
*
* Copyright 2018 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 <grpc/support/port_platform.h>
#include "src/core/tsi/alts/handshaker/alts_tsi_utils.h"
#include <grpc/byte_buffer_reader.h>
tsi_result alts_tsi_utils_convert_to_tsi_result(grpc_status_code code) {
switch (code) {
case GRPC_STATUS_OK:
return TSI_OK;
case GRPC_STATUS_UNKNOWN:
return TSI_UNKNOWN_ERROR;
case GRPC_STATUS_INVALID_ARGUMENT:
return TSI_INVALID_ARGUMENT;
case GRPC_STATUS_NOT_FOUND:
return TSI_NOT_FOUND;
case GRPC_STATUS_INTERNAL:
return TSI_INTERNAL_ERROR;
default:
return TSI_UNKNOWN_ERROR;
}
}
grpc_gcp_handshaker_resp* alts_tsi_utils_deserialize_response(
grpc_byte_buffer* resp_buffer) {
GPR_ASSERT(resp_buffer != nullptr);
grpc_byte_buffer_reader bbr;
grpc_byte_buffer_reader_init(&bbr, resp_buffer);
grpc_slice slice = grpc_byte_buffer_reader_readall(&bbr);
grpc_gcp_handshaker_resp* resp = grpc_gcp_handshaker_resp_create();
bool ok = grpc_gcp_handshaker_resp_decode(slice, resp);
grpc_slice_unref(slice);
grpc_byte_buffer_reader_destroy(&bbr);
if (!ok) {
grpc_gcp_handshaker_resp_destroy(resp);
gpr_log(GPR_ERROR, "grpc_gcp_handshaker_resp_decode() failed");
return nullptr;
}
return resp;
}

@ -0,0 +1,52 @@
/*
*
* Copyright 2018 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_CORE_TSI_ALTS_HANDSHAKER_ALTS_TSI_UTILS_H
#define GRPC_CORE_TSI_ALTS_HANDSHAKER_ALTS_TSI_UTILS_H
#include <grpc/support/port_platform.h>
#include <grpc/byte_buffer.h>
#include <grpc/grpc.h>
#include "src/core/tsi/alts/handshaker/alts_handshaker_service_api.h"
#include "src/core/tsi/transport_security_interface.h"
/**
* This method converts grpc_status_code code to the corresponding tsi_result
* code.
*
* - code: grpc_status_code code.
*
* It returns the converted tsi_result code.
*/
tsi_result alts_tsi_utils_convert_to_tsi_result(grpc_status_code code);
/**
* This method deserializes a handshaker response returned from ALTS handshaker
* service.
*
* - bytes_received: data returned from ALTS handshaker service.
*
* It returns a deserialized handshaker response on success and nullptr on
* failure.
*/
grpc_gcp_handshaker_resp* alts_tsi_utils_deserialize_response(
grpc_byte_buffer* resp_buffer);
#endif /* GRPC_CORE_TSI_ALTS_HANDSHAKER_ALTS_TSI_UTILS_H */

@ -0,0 +1,48 @@
/* Automatically generated nanopb constant definitions */
/* Generated by nanopb-0.3.7-dev */
#include "src/core/tsi/alts/handshaker/altscontext.pb.h"
/* @@protoc_insertion_point(includes) */
#if PB_PROTO_HEADER_VERSION != 30
#error Regenerate this file with the current version of nanopb generator.
#endif
const pb_field_t grpc_gcp_AltsContext_fields[7] = {
PB_FIELD( 1, STRING , OPTIONAL, CALLBACK, FIRST, grpc_gcp_AltsContext, application_protocol, application_protocol, 0),
PB_FIELD( 2, STRING , OPTIONAL, CALLBACK, OTHER, grpc_gcp_AltsContext, record_protocol, application_protocol, 0),
PB_FIELD( 3, UENUM , OPTIONAL, STATIC , OTHER, grpc_gcp_AltsContext, security_level, record_protocol, 0),
PB_FIELD( 4, STRING , OPTIONAL, CALLBACK, OTHER, grpc_gcp_AltsContext, peer_service_account, security_level, 0),
PB_FIELD( 5, STRING , OPTIONAL, CALLBACK, OTHER, grpc_gcp_AltsContext, local_service_account, peer_service_account, 0),
PB_FIELD( 6, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_gcp_AltsContext, peer_rpc_versions, local_service_account, &grpc_gcp_RpcProtocolVersions_fields),
PB_LAST_FIELD
};
/* Check that field information fits in pb_field_t */
#if !defined(PB_FIELD_32BIT)
/* If you get an error here, it means that you need to define PB_FIELD_32BIT
* compile-time option. You can do that in pb.h or on compiler command line.
*
* The reason you need to do this is that some of your messages contain tag
* numbers or field sizes that are larger than what can fit in 8 or 16 bit
* field descriptors.
*/
PB_STATIC_ASSERT((pb_membersize(grpc_gcp_AltsContext, peer_rpc_versions) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_grpc_gcp_AltsContext)
#endif
#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT)
/* If you get an error here, it means that you need to define PB_FIELD_16BIT
* compile-time option. You can do that in pb.h or on compiler command line.
*
* The reason you need to do this is that some of your messages contain tag
* numbers or field sizes that are larger than what can fit in the default
* 8 bit descriptors.
*/
PB_STATIC_ASSERT((pb_membersize(grpc_gcp_AltsContext, peer_rpc_versions) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_grpc_gcp_AltsContext)
#endif
/* @@protoc_insertion_point(eof) */

@ -0,0 +1,64 @@
/* Automatically generated nanopb header */
/* Generated by nanopb-0.3.7-dev */
#ifndef PB_GRPC_GCP_ALTSCONTEXT_PB_H_INCLUDED
#define PB_GRPC_GCP_ALTSCONTEXT_PB_H_INCLUDED
#include "third_party/nanopb/pb.h"
#include "src/core/tsi/alts/handshaker/transport_security_common.pb.h"
/* @@protoc_insertion_point(includes) */
#if PB_PROTO_HEADER_VERSION != 30
#error Regenerate this file with the current version of nanopb generator.
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* Struct definitions */
typedef struct _grpc_gcp_AltsContext {
pb_callback_t application_protocol;
pb_callback_t record_protocol;
bool has_security_level;
grpc_gcp_SecurityLevel security_level;
pb_callback_t peer_service_account;
pb_callback_t local_service_account;
bool has_peer_rpc_versions;
grpc_gcp_RpcProtocolVersions peer_rpc_versions;
/* @@protoc_insertion_point(struct:grpc_gcp_AltsContext) */
} grpc_gcp_AltsContext;
/* Default values for struct fields */
/* Initializer values for message structs */
#define grpc_gcp_AltsContext_init_default {{{NULL}, NULL}, {{NULL}, NULL}, false, (grpc_gcp_SecurityLevel)0, {{NULL}, NULL}, {{NULL}, NULL}, false, grpc_gcp_RpcProtocolVersions_init_default}
#define grpc_gcp_AltsContext_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, false, (grpc_gcp_SecurityLevel)0, {{NULL}, NULL}, {{NULL}, NULL}, false, grpc_gcp_RpcProtocolVersions_init_zero}
/* Field tags (for use in manual encoding/decoding) */
#define grpc_gcp_AltsContext_application_protocol_tag 1
#define grpc_gcp_AltsContext_record_protocol_tag 2
#define grpc_gcp_AltsContext_security_level_tag 3
#define grpc_gcp_AltsContext_peer_service_account_tag 4
#define grpc_gcp_AltsContext_local_service_account_tag 5
#define grpc_gcp_AltsContext_peer_rpc_versions_tag 6
/* Struct field encoding specification for nanopb */
extern const pb_field_t grpc_gcp_AltsContext_fields[7];
/* Maximum encoded size of messages (where known) */
/* grpc_gcp_AltsContext_size depends on runtime parameters */
/* Message IDs (where set with "msgid" option) */
#ifdef PB_MSGID
#define ALTSCONTEXT_MESSAGES \
#endif
#ifdef __cplusplus
} /* extern "C" */
#endif
/* @@protoc_insertion_point(eof) */
#endif

@ -0,0 +1,123 @@
/* Automatically generated nanopb constant definitions */
/* Generated by nanopb-0.3.7-dev */
#include "src/core/tsi/alts/handshaker/handshaker.pb.h"
/* @@protoc_insertion_point(includes) */
#if PB_PROTO_HEADER_VERSION != 30
#error Regenerate this file with the current version of nanopb generator.
#endif
const pb_field_t grpc_gcp_Endpoint_fields[4] = {
PB_FIELD( 1, STRING , OPTIONAL, CALLBACK, FIRST, grpc_gcp_Endpoint, ip_address, ip_address, 0),
PB_FIELD( 2, INT32 , OPTIONAL, STATIC , OTHER, grpc_gcp_Endpoint, port, ip_address, 0),
PB_FIELD( 3, UENUM , OPTIONAL, STATIC , OTHER, grpc_gcp_Endpoint, protocol, port, 0),
PB_LAST_FIELD
};
const pb_field_t grpc_gcp_Identity_fields[3] = {
PB_FIELD( 1, STRING , OPTIONAL, CALLBACK, FIRST, grpc_gcp_Identity, service_account, service_account, 0),
PB_FIELD( 2, STRING , OPTIONAL, CALLBACK, OTHER, grpc_gcp_Identity, hostname, service_account, 0),
PB_LAST_FIELD
};
const pb_field_t grpc_gcp_StartClientHandshakeReq_fields[10] = {
PB_FIELD( 1, UENUM , OPTIONAL, STATIC , FIRST, grpc_gcp_StartClientHandshakeReq, handshake_security_protocol, handshake_security_protocol, 0),
PB_FIELD( 2, STRING , REPEATED, CALLBACK, OTHER, grpc_gcp_StartClientHandshakeReq, application_protocols, handshake_security_protocol, 0),
PB_FIELD( 3, STRING , REPEATED, CALLBACK, OTHER, grpc_gcp_StartClientHandshakeReq, record_protocols, application_protocols, 0),
PB_FIELD( 4, MESSAGE , REPEATED, CALLBACK, OTHER, grpc_gcp_StartClientHandshakeReq, target_identities, record_protocols, &grpc_gcp_Identity_fields),
PB_FIELD( 5, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_gcp_StartClientHandshakeReq, local_identity, target_identities, &grpc_gcp_Identity_fields),
PB_FIELD( 6, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_gcp_StartClientHandshakeReq, local_endpoint, local_identity, &grpc_gcp_Endpoint_fields),
PB_FIELD( 7, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_gcp_StartClientHandshakeReq, remote_endpoint, local_endpoint, &grpc_gcp_Endpoint_fields),
PB_FIELD( 8, STRING , OPTIONAL, CALLBACK, OTHER, grpc_gcp_StartClientHandshakeReq, target_name, remote_endpoint, 0),
PB_FIELD( 9, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_gcp_StartClientHandshakeReq, rpc_versions, target_name, &grpc_gcp_RpcProtocolVersions_fields),
PB_LAST_FIELD
};
const pb_field_t grpc_gcp_ServerHandshakeParameters_fields[3] = {
PB_FIELD( 1, STRING , REPEATED, CALLBACK, FIRST, grpc_gcp_ServerHandshakeParameters, record_protocols, record_protocols, 0),
PB_FIELD( 2, MESSAGE , REPEATED, CALLBACK, OTHER, grpc_gcp_ServerHandshakeParameters, local_identities, record_protocols, &grpc_gcp_Identity_fields),
PB_LAST_FIELD
};
const pb_field_t grpc_gcp_StartServerHandshakeReq_fields[7] = {
PB_FIELD( 1, STRING , REPEATED, CALLBACK, FIRST, grpc_gcp_StartServerHandshakeReq, application_protocols, application_protocols, 0),
PB_FIELD( 2, MESSAGE , REPEATED, STATIC , OTHER, grpc_gcp_StartServerHandshakeReq, handshake_parameters, application_protocols, &grpc_gcp_StartServerHandshakeReq_HandshakeParametersEntry_fields),
PB_FIELD( 3, BYTES , OPTIONAL, CALLBACK, OTHER, grpc_gcp_StartServerHandshakeReq, in_bytes, handshake_parameters, 0),
PB_FIELD( 4, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_gcp_StartServerHandshakeReq, local_endpoint, in_bytes, &grpc_gcp_Endpoint_fields),
PB_FIELD( 5, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_gcp_StartServerHandshakeReq, remote_endpoint, local_endpoint, &grpc_gcp_Endpoint_fields),
PB_FIELD( 6, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_gcp_StartServerHandshakeReq, rpc_versions, remote_endpoint, &grpc_gcp_RpcProtocolVersions_fields),
PB_LAST_FIELD
};
const pb_field_t grpc_gcp_StartServerHandshakeReq_HandshakeParametersEntry_fields[3] = {
PB_FIELD( 1, INT32 , OPTIONAL, STATIC , FIRST, grpc_gcp_StartServerHandshakeReq_HandshakeParametersEntry, key, key, 0),
PB_FIELD( 2, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_gcp_StartServerHandshakeReq_HandshakeParametersEntry, value, key, &grpc_gcp_ServerHandshakeParameters_fields),
PB_LAST_FIELD
};
const pb_field_t grpc_gcp_NextHandshakeMessageReq_fields[2] = {
PB_FIELD( 1, BYTES , OPTIONAL, CALLBACK, FIRST, grpc_gcp_NextHandshakeMessageReq, in_bytes, in_bytes, 0),
PB_LAST_FIELD
};
const pb_field_t grpc_gcp_HandshakerReq_fields[4] = {
PB_FIELD( 1, MESSAGE , OPTIONAL, STATIC , FIRST, grpc_gcp_HandshakerReq, client_start, client_start, &grpc_gcp_StartClientHandshakeReq_fields),
PB_FIELD( 2, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_gcp_HandshakerReq, server_start, client_start, &grpc_gcp_StartServerHandshakeReq_fields),
PB_FIELD( 3, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_gcp_HandshakerReq, next, server_start, &grpc_gcp_NextHandshakeMessageReq_fields),
PB_LAST_FIELD
};
const pb_field_t grpc_gcp_HandshakerResult_fields[8] = {
PB_FIELD( 1, STRING , OPTIONAL, CALLBACK, FIRST, grpc_gcp_HandshakerResult, application_protocol, application_protocol, 0),
PB_FIELD( 2, STRING , OPTIONAL, CALLBACK, OTHER, grpc_gcp_HandshakerResult, record_protocol, application_protocol, 0),
PB_FIELD( 3, BYTES , OPTIONAL, CALLBACK, OTHER, grpc_gcp_HandshakerResult, key_data, record_protocol, 0),
PB_FIELD( 4, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_gcp_HandshakerResult, peer_identity, key_data, &grpc_gcp_Identity_fields),
PB_FIELD( 5, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_gcp_HandshakerResult, local_identity, peer_identity, &grpc_gcp_Identity_fields),
PB_FIELD( 6, BOOL , OPTIONAL, STATIC , OTHER, grpc_gcp_HandshakerResult, keep_channel_open, local_identity, 0),
PB_FIELD( 7, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_gcp_HandshakerResult, peer_rpc_versions, keep_channel_open, &grpc_gcp_RpcProtocolVersions_fields),
PB_LAST_FIELD
};
const pb_field_t grpc_gcp_HandshakerStatus_fields[3] = {
PB_FIELD( 1, UINT32 , OPTIONAL, STATIC , FIRST, grpc_gcp_HandshakerStatus, code, code, 0),
PB_FIELD( 2, STRING , OPTIONAL, CALLBACK, OTHER, grpc_gcp_HandshakerStatus, details, code, 0),
PB_LAST_FIELD
};
const pb_field_t grpc_gcp_HandshakerResp_fields[5] = {
PB_FIELD( 1, BYTES , OPTIONAL, CALLBACK, FIRST, grpc_gcp_HandshakerResp, out_frames, out_frames, 0),
PB_FIELD( 2, UINT32 , OPTIONAL, STATIC , OTHER, grpc_gcp_HandshakerResp, bytes_consumed, out_frames, 0),
PB_FIELD( 3, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_gcp_HandshakerResp, result, bytes_consumed, &grpc_gcp_HandshakerResult_fields),
PB_FIELD( 4, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_gcp_HandshakerResp, status, result, &grpc_gcp_HandshakerStatus_fields),
PB_LAST_FIELD
};
/* Check that field information fits in pb_field_t */
#if !defined(PB_FIELD_32BIT)
/* If you get an error here, it means that you need to define PB_FIELD_32BIT
* compile-time option. You can do that in pb.h or on compiler command line.
*
* The reason you need to do this is that some of your messages contain tag
* numbers or field sizes that are larger than what can fit in 8 or 16 bit
* field descriptors.
*/
PB_STATIC_ASSERT((pb_membersize(grpc_gcp_StartClientHandshakeReq, target_identities) < 65536 && pb_membersize(grpc_gcp_StartClientHandshakeReq, local_identity) < 65536 && pb_membersize(grpc_gcp_StartClientHandshakeReq, local_endpoint) < 65536 && pb_membersize(grpc_gcp_StartClientHandshakeReq, remote_endpoint) < 65536 && pb_membersize(grpc_gcp_StartClientHandshakeReq, rpc_versions) < 65536 && pb_membersize(grpc_gcp_ServerHandshakeParameters, local_identities) < 65536 && pb_membersize(grpc_gcp_StartServerHandshakeReq, handshake_parameters[0]) < 65536 && pb_membersize(grpc_gcp_StartServerHandshakeReq, local_endpoint) < 65536 && pb_membersize(grpc_gcp_StartServerHandshakeReq, remote_endpoint) < 65536 && pb_membersize(grpc_gcp_StartServerHandshakeReq, rpc_versions) < 65536 && pb_membersize(grpc_gcp_StartServerHandshakeReq_HandshakeParametersEntry, value) < 65536 && pb_membersize(grpc_gcp_HandshakerReq, client_start) < 65536 && pb_membersize(grpc_gcp_HandshakerReq, server_start) < 65536 && pb_membersize(grpc_gcp_HandshakerReq, next) < 65536 && pb_membersize(grpc_gcp_HandshakerResult, peer_identity) < 65536 && pb_membersize(grpc_gcp_HandshakerResult, local_identity) < 65536 && pb_membersize(grpc_gcp_HandshakerResult, peer_rpc_versions) < 65536 && pb_membersize(grpc_gcp_HandshakerResp, result) < 65536 && pb_membersize(grpc_gcp_HandshakerResp, status) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_grpc_gcp_Endpoint_grpc_gcp_Identity_grpc_gcp_StartClientHandshakeReq_grpc_gcp_ServerHandshakeParameters_grpc_gcp_StartServerHandshakeReq_grpc_gcp_StartServerHandshakeReq_HandshakeParametersEntry_grpc_gcp_NextHandshakeMessageReq_grpc_gcp_HandshakerReq_grpc_gcp_HandshakerResult_grpc_gcp_HandshakerStatus_grpc_gcp_HandshakerResp)
#endif
#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT)
/* If you get an error here, it means that you need to define PB_FIELD_16BIT
* compile-time option. You can do that in pb.h or on compiler command line.
*
* The reason you need to do this is that some of your messages contain tag
* numbers or field sizes that are larger than what can fit in the default
* 8 bit descriptors.
*/
PB_STATIC_ASSERT((pb_membersize(grpc_gcp_StartClientHandshakeReq, target_identities) < 256 && pb_membersize(grpc_gcp_StartClientHandshakeReq, local_identity) < 256 && pb_membersize(grpc_gcp_StartClientHandshakeReq, local_endpoint) < 256 && pb_membersize(grpc_gcp_StartClientHandshakeReq, remote_endpoint) < 256 && pb_membersize(grpc_gcp_StartClientHandshakeReq, rpc_versions) < 256 && pb_membersize(grpc_gcp_ServerHandshakeParameters, local_identities) < 256 && pb_membersize(grpc_gcp_StartServerHandshakeReq, handshake_parameters[0]) < 256 && pb_membersize(grpc_gcp_StartServerHandshakeReq, local_endpoint) < 256 && pb_membersize(grpc_gcp_StartServerHandshakeReq, remote_endpoint) < 256 && pb_membersize(grpc_gcp_StartServerHandshakeReq, rpc_versions) < 256 && pb_membersize(grpc_gcp_StartServerHandshakeReq_HandshakeParametersEntry, value) < 256 && pb_membersize(grpc_gcp_HandshakerReq, client_start) < 256 && pb_membersize(grpc_gcp_HandshakerReq, server_start) < 256 && pb_membersize(grpc_gcp_HandshakerReq, next) < 256 && pb_membersize(grpc_gcp_HandshakerResult, peer_identity) < 256 && pb_membersize(grpc_gcp_HandshakerResult, local_identity) < 256 && pb_membersize(grpc_gcp_HandshakerResult, peer_rpc_versions) < 256 && pb_membersize(grpc_gcp_HandshakerResp, result) < 256 && pb_membersize(grpc_gcp_HandshakerResp, status) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_grpc_gcp_Endpoint_grpc_gcp_Identity_grpc_gcp_StartClientHandshakeReq_grpc_gcp_ServerHandshakeParameters_grpc_gcp_StartServerHandshakeReq_grpc_gcp_StartServerHandshakeReq_HandshakeParametersEntry_grpc_gcp_NextHandshakeMessageReq_grpc_gcp_HandshakerReq_grpc_gcp_HandshakerResult_grpc_gcp_HandshakerStatus_grpc_gcp_HandshakerResp)
#endif
/* @@protoc_insertion_point(eof) */

@ -0,0 +1,255 @@
/* Automatically generated nanopb header */
/* Generated by nanopb-0.3.7-dev */
#ifndef PB_GRPC_GCP_HANDSHAKER_PB_H_INCLUDED
#define PB_GRPC_GCP_HANDSHAKER_PB_H_INCLUDED
#include "third_party/nanopb/pb.h"
#include "src/core/tsi/alts/handshaker/transport_security_common.pb.h"
/* @@protoc_insertion_point(includes) */
#if PB_PROTO_HEADER_VERSION != 30
#error Regenerate this file with the current version of nanopb generator.
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* Enum definitions */
typedef enum _grpc_gcp_HandshakeProtocol {
grpc_gcp_HandshakeProtocol_HANDSHAKE_PROTOCOL_UNSPECIFIED = 0,
grpc_gcp_HandshakeProtocol_TLS = 1,
grpc_gcp_HandshakeProtocol_ALTS = 2
} grpc_gcp_HandshakeProtocol;
#define _grpc_gcp_HandshakeProtocol_MIN grpc_gcp_HandshakeProtocol_HANDSHAKE_PROTOCOL_UNSPECIFIED
#define _grpc_gcp_HandshakeProtocol_MAX grpc_gcp_HandshakeProtocol_ALTS
#define _grpc_gcp_HandshakeProtocol_ARRAYSIZE ((grpc_gcp_HandshakeProtocol)(grpc_gcp_HandshakeProtocol_ALTS+1))
typedef enum _grpc_gcp_NetworkProtocol {
grpc_gcp_NetworkProtocol_NETWORK_PROTOCOL_UNSPECIFIED = 0,
grpc_gcp_NetworkProtocol_TCP = 1,
grpc_gcp_NetworkProtocol_UDP = 2
} grpc_gcp_NetworkProtocol;
#define _grpc_gcp_NetworkProtocol_MIN grpc_gcp_NetworkProtocol_NETWORK_PROTOCOL_UNSPECIFIED
#define _grpc_gcp_NetworkProtocol_MAX grpc_gcp_NetworkProtocol_UDP
#define _grpc_gcp_NetworkProtocol_ARRAYSIZE ((grpc_gcp_NetworkProtocol)(grpc_gcp_NetworkProtocol_UDP+1))
/* Struct definitions */
typedef struct _grpc_gcp_Identity {
pb_callback_t service_account;
pb_callback_t hostname;
/* @@protoc_insertion_point(struct:grpc_gcp_Identity) */
} grpc_gcp_Identity;
typedef struct _grpc_gcp_NextHandshakeMessageReq {
pb_callback_t in_bytes;
/* @@protoc_insertion_point(struct:grpc_gcp_NextHandshakeMessageReq) */
} grpc_gcp_NextHandshakeMessageReq;
typedef struct _grpc_gcp_ServerHandshakeParameters {
pb_callback_t record_protocols;
pb_callback_t local_identities;
/* @@protoc_insertion_point(struct:grpc_gcp_ServerHandshakeParameters) */
} grpc_gcp_ServerHandshakeParameters;
typedef struct _grpc_gcp_Endpoint {
pb_callback_t ip_address;
bool has_port;
int32_t port;
bool has_protocol;
grpc_gcp_NetworkProtocol protocol;
/* @@protoc_insertion_point(struct:grpc_gcp_Endpoint) */
} grpc_gcp_Endpoint;
typedef struct _grpc_gcp_HandshakerResult {
pb_callback_t application_protocol;
pb_callback_t record_protocol;
pb_callback_t key_data;
bool has_peer_identity;
grpc_gcp_Identity peer_identity;
bool has_local_identity;
grpc_gcp_Identity local_identity;
bool has_keep_channel_open;
bool keep_channel_open;
bool has_peer_rpc_versions;
grpc_gcp_RpcProtocolVersions peer_rpc_versions;
/* @@protoc_insertion_point(struct:grpc_gcp_HandshakerResult) */
} grpc_gcp_HandshakerResult;
typedef struct _grpc_gcp_HandshakerStatus {
bool has_code;
uint32_t code;
pb_callback_t details;
/* @@protoc_insertion_point(struct:grpc_gcp_HandshakerStatus) */
} grpc_gcp_HandshakerStatus;
typedef struct _grpc_gcp_StartServerHandshakeReq_HandshakeParametersEntry {
bool has_key;
int32_t key;
bool has_value;
grpc_gcp_ServerHandshakeParameters value;
/* @@protoc_insertion_point(struct:grpc_gcp_StartServerHandshakeReq_HandshakeParametersEntry) */
} grpc_gcp_StartServerHandshakeReq_HandshakeParametersEntry;
typedef struct _grpc_gcp_HandshakerResp {
pb_callback_t out_frames;
bool has_bytes_consumed;
uint32_t bytes_consumed;
bool has_result;
grpc_gcp_HandshakerResult result;
bool has_status;
grpc_gcp_HandshakerStatus status;
/* @@protoc_insertion_point(struct:grpc_gcp_HandshakerResp) */
} grpc_gcp_HandshakerResp;
typedef struct _grpc_gcp_StartClientHandshakeReq {
bool has_handshake_security_protocol;
grpc_gcp_HandshakeProtocol handshake_security_protocol;
pb_callback_t application_protocols;
pb_callback_t record_protocols;
pb_callback_t target_identities;
bool has_local_identity;
grpc_gcp_Identity local_identity;
bool has_local_endpoint;
grpc_gcp_Endpoint local_endpoint;
bool has_remote_endpoint;
grpc_gcp_Endpoint remote_endpoint;
pb_callback_t target_name;
bool has_rpc_versions;
grpc_gcp_RpcProtocolVersions rpc_versions;
/* @@protoc_insertion_point(struct:grpc_gcp_StartClientHandshakeReq) */
} grpc_gcp_StartClientHandshakeReq;
typedef struct _grpc_gcp_StartServerHandshakeReq {
pb_callback_t application_protocols;
pb_size_t handshake_parameters_count;
grpc_gcp_StartServerHandshakeReq_HandshakeParametersEntry handshake_parameters[3];
pb_callback_t in_bytes;
bool has_local_endpoint;
grpc_gcp_Endpoint local_endpoint;
bool has_remote_endpoint;
grpc_gcp_Endpoint remote_endpoint;
bool has_rpc_versions;
grpc_gcp_RpcProtocolVersions rpc_versions;
/* @@protoc_insertion_point(struct:grpc_gcp_StartServerHandshakeReq) */
} grpc_gcp_StartServerHandshakeReq;
typedef struct _grpc_gcp_HandshakerReq {
bool has_client_start;
grpc_gcp_StartClientHandshakeReq client_start;
bool has_server_start;
grpc_gcp_StartServerHandshakeReq server_start;
bool has_next;
grpc_gcp_NextHandshakeMessageReq next;
/* @@protoc_insertion_point(struct:grpc_gcp_HandshakerReq) */
} grpc_gcp_HandshakerReq;
/* Default values for struct fields */
/* Initializer values for message structs */
#define grpc_gcp_Endpoint_init_default {{{NULL}, NULL}, false, 0, false, (grpc_gcp_NetworkProtocol)0}
#define grpc_gcp_Identity_init_default {{{NULL}, NULL}, {{NULL}, NULL}}
#define grpc_gcp_StartClientHandshakeReq_init_default {false, (grpc_gcp_HandshakeProtocol)0, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, false, grpc_gcp_Identity_init_default, false, grpc_gcp_Endpoint_init_default, false, grpc_gcp_Endpoint_init_default, {{NULL}, NULL}, false, grpc_gcp_RpcProtocolVersions_init_default}
#define grpc_gcp_ServerHandshakeParameters_init_default {{{NULL}, NULL}, {{NULL}, NULL}}
#define grpc_gcp_StartServerHandshakeReq_init_default {{{NULL}, NULL}, 0, {grpc_gcp_StartServerHandshakeReq_HandshakeParametersEntry_init_default, grpc_gcp_StartServerHandshakeReq_HandshakeParametersEntry_init_default, grpc_gcp_StartServerHandshakeReq_HandshakeParametersEntry_init_default}, {{NULL}, NULL}, false, grpc_gcp_Endpoint_init_default, false, grpc_gcp_Endpoint_init_default, false, grpc_gcp_RpcProtocolVersions_init_default}
#define grpc_gcp_StartServerHandshakeReq_HandshakeParametersEntry_init_default {false, 0, false, grpc_gcp_ServerHandshakeParameters_init_default}
#define grpc_gcp_NextHandshakeMessageReq_init_default {{{NULL}, NULL}}
#define grpc_gcp_HandshakerReq_init_default {false, grpc_gcp_StartClientHandshakeReq_init_default, false, grpc_gcp_StartServerHandshakeReq_init_default, false, grpc_gcp_NextHandshakeMessageReq_init_default}
#define grpc_gcp_HandshakerResult_init_default {{{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, false, grpc_gcp_Identity_init_default, false, grpc_gcp_Identity_init_default, false, 0, false, grpc_gcp_RpcProtocolVersions_init_default}
#define grpc_gcp_HandshakerStatus_init_default {false, 0, {{NULL}, NULL}}
#define grpc_gcp_HandshakerResp_init_default {{{NULL}, NULL}, false, 0, false, grpc_gcp_HandshakerResult_init_default, false, grpc_gcp_HandshakerStatus_init_default}
#define grpc_gcp_Endpoint_init_zero {{{NULL}, NULL}, false, 0, false, (grpc_gcp_NetworkProtocol)0}
#define grpc_gcp_Identity_init_zero {{{NULL}, NULL}, {{NULL}, NULL}}
#define grpc_gcp_StartClientHandshakeReq_init_zero {false, (grpc_gcp_HandshakeProtocol)0, {{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, false, grpc_gcp_Identity_init_zero, false, grpc_gcp_Endpoint_init_zero, false, grpc_gcp_Endpoint_init_zero, {{NULL}, NULL}, false, grpc_gcp_RpcProtocolVersions_init_zero}
#define grpc_gcp_ServerHandshakeParameters_init_zero {{{NULL}, NULL}, {{NULL}, NULL}}
#define grpc_gcp_StartServerHandshakeReq_init_zero {{{NULL}, NULL}, 0, {grpc_gcp_StartServerHandshakeReq_HandshakeParametersEntry_init_zero, grpc_gcp_StartServerHandshakeReq_HandshakeParametersEntry_init_zero, grpc_gcp_StartServerHandshakeReq_HandshakeParametersEntry_init_zero}, {{NULL}, NULL}, false, grpc_gcp_Endpoint_init_zero, false, grpc_gcp_Endpoint_init_zero, false, grpc_gcp_RpcProtocolVersions_init_zero}
#define grpc_gcp_StartServerHandshakeReq_HandshakeParametersEntry_init_zero {false, 0, false, grpc_gcp_ServerHandshakeParameters_init_zero}
#define grpc_gcp_NextHandshakeMessageReq_init_zero {{{NULL}, NULL}}
#define grpc_gcp_HandshakerReq_init_zero {false, grpc_gcp_StartClientHandshakeReq_init_zero, false, grpc_gcp_StartServerHandshakeReq_init_zero, false, grpc_gcp_NextHandshakeMessageReq_init_zero}
#define grpc_gcp_HandshakerResult_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}, false, grpc_gcp_Identity_init_zero, false, grpc_gcp_Identity_init_zero, false, 0, false, grpc_gcp_RpcProtocolVersions_init_zero}
#define grpc_gcp_HandshakerStatus_init_zero {false, 0, {{NULL}, NULL}}
#define grpc_gcp_HandshakerResp_init_zero {{{NULL}, NULL}, false, 0, false, grpc_gcp_HandshakerResult_init_zero, false, grpc_gcp_HandshakerStatus_init_zero}
/* Field tags (for use in manual encoding/decoding) */
#define grpc_gcp_Identity_service_account_tag 1
#define grpc_gcp_Identity_hostname_tag 2
#define grpc_gcp_NextHandshakeMessageReq_in_bytes_tag 1
#define grpc_gcp_ServerHandshakeParameters_record_protocols_tag 1
#define grpc_gcp_ServerHandshakeParameters_local_identities_tag 2
#define grpc_gcp_Endpoint_ip_address_tag 1
#define grpc_gcp_Endpoint_port_tag 2
#define grpc_gcp_Endpoint_protocol_tag 3
#define grpc_gcp_HandshakerResult_application_protocol_tag 1
#define grpc_gcp_HandshakerResult_record_protocol_tag 2
#define grpc_gcp_HandshakerResult_key_data_tag 3
#define grpc_gcp_HandshakerResult_peer_identity_tag 4
#define grpc_gcp_HandshakerResult_local_identity_tag 5
#define grpc_gcp_HandshakerResult_keep_channel_open_tag 6
#define grpc_gcp_HandshakerResult_peer_rpc_versions_tag 7
#define grpc_gcp_HandshakerStatus_code_tag 1
#define grpc_gcp_HandshakerStatus_details_tag 2
#define grpc_gcp_StartServerHandshakeReq_HandshakeParametersEntry_key_tag 1
#define grpc_gcp_StartServerHandshakeReq_HandshakeParametersEntry_value_tag 2
#define grpc_gcp_HandshakerResp_out_frames_tag 1
#define grpc_gcp_HandshakerResp_bytes_consumed_tag 2
#define grpc_gcp_HandshakerResp_result_tag 3
#define grpc_gcp_HandshakerResp_status_tag 4
#define grpc_gcp_StartClientHandshakeReq_handshake_security_protocol_tag 1
#define grpc_gcp_StartClientHandshakeReq_application_protocols_tag 2
#define grpc_gcp_StartClientHandshakeReq_record_protocols_tag 3
#define grpc_gcp_StartClientHandshakeReq_target_identities_tag 4
#define grpc_gcp_StartClientHandshakeReq_local_identity_tag 5
#define grpc_gcp_StartClientHandshakeReq_local_endpoint_tag 6
#define grpc_gcp_StartClientHandshakeReq_remote_endpoint_tag 7
#define grpc_gcp_StartClientHandshakeReq_target_name_tag 8
#define grpc_gcp_StartClientHandshakeReq_rpc_versions_tag 9
#define grpc_gcp_StartServerHandshakeReq_application_protocols_tag 1
#define grpc_gcp_StartServerHandshakeReq_handshake_parameters_tag 2
#define grpc_gcp_StartServerHandshakeReq_in_bytes_tag 3
#define grpc_gcp_StartServerHandshakeReq_local_endpoint_tag 4
#define grpc_gcp_StartServerHandshakeReq_remote_endpoint_tag 5
#define grpc_gcp_StartServerHandshakeReq_rpc_versions_tag 6
#define grpc_gcp_HandshakerReq_client_start_tag 1
#define grpc_gcp_HandshakerReq_server_start_tag 2
#define grpc_gcp_HandshakerReq_next_tag 3
/* Struct field encoding specification for nanopb */
extern const pb_field_t grpc_gcp_Endpoint_fields[4];
extern const pb_field_t grpc_gcp_Identity_fields[3];
extern const pb_field_t grpc_gcp_StartClientHandshakeReq_fields[10];
extern const pb_field_t grpc_gcp_ServerHandshakeParameters_fields[3];
extern const pb_field_t grpc_gcp_StartServerHandshakeReq_fields[7];
extern const pb_field_t grpc_gcp_StartServerHandshakeReq_HandshakeParametersEntry_fields[3];
extern const pb_field_t grpc_gcp_NextHandshakeMessageReq_fields[2];
extern const pb_field_t grpc_gcp_HandshakerReq_fields[4];
extern const pb_field_t grpc_gcp_HandshakerResult_fields[8];
extern const pb_field_t grpc_gcp_HandshakerStatus_fields[3];
extern const pb_field_t grpc_gcp_HandshakerResp_fields[5];
/* Maximum encoded size of messages (where known) */
/* grpc_gcp_Endpoint_size depends on runtime parameters */
/* grpc_gcp_Identity_size depends on runtime parameters */
/* grpc_gcp_StartClientHandshakeReq_size depends on runtime parameters */
/* grpc_gcp_ServerHandshakeParameters_size depends on runtime parameters */
/* grpc_gcp_StartServerHandshakeReq_size depends on runtime parameters */
#define grpc_gcp_StartServerHandshakeReq_HandshakeParametersEntry_size (17 + grpc_gcp_ServerHandshakeParameters_size)
/* grpc_gcp_NextHandshakeMessageReq_size depends on runtime parameters */
#define grpc_gcp_HandshakerReq_size (18 + grpc_gcp_StartClientHandshakeReq_size + grpc_gcp_StartServerHandshakeReq_size + grpc_gcp_NextHandshakeMessageReq_size)
/* grpc_gcp_HandshakerResult_size depends on runtime parameters */
/* grpc_gcp_HandshakerStatus_size depends on runtime parameters */
/* grpc_gcp_HandshakerResp_size depends on runtime parameters */
/* Message IDs (where set with "msgid" option) */
#ifdef PB_MSGID
#define HANDSHAKER_MESSAGES \
#endif
#ifdef __cplusplus
} /* extern "C" */
#endif
/* @@protoc_insertion_point(eof) */
#endif

@ -0,0 +1,41 @@
// Copyright 2018 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.
syntax = "proto3";
import "transport_security_common.proto";
package grpc.gcp;
option java_package = "io.grpc.alts";
message AltsContext {
// The application protocol negotiated for this connection.
string application_protocol = 1;
// The record protocol negotiated for this connection.
string record_protocol = 2;
// The security level of the created secure channel.
SecurityLevel security_level = 3;
// The peer service account.
string peer_service_account = 4;
// The local service account.
string local_service_account = 5;
// The RPC protocol versions supported by the peer.
RpcProtocolVersions peer_rpc_versions = 6;
}

@ -0,0 +1,2 @@
handshaker.proto no_unions:true
grpc.gcp.StartServerHandshakeReq.handshake_parameters max_count:3

@ -0,0 +1,220 @@
// Copyright 2018 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.
syntax = "proto3";
import "transport_security_common.proto";
package grpc.gcp;
option java_package = "io.grpc.alts";
enum HandshakeProtocol {
// Default value.
HANDSHAKE_PROTOCOL_UNSPECIFIED = 0;
// TLS handshake protocol.
TLS = 1;
// Application Layer Transport Security handshake protocol.
ALTS = 2;
}
enum NetworkProtocol {
NETWORK_PROTOCOL_UNSPECIFIED = 0;
TCP = 1;
UDP = 2;
}
message Endpoint {
// IP address. It should contain an IPv4 or IPv6 string literal, e.g.
// "192.168.0.1" or "2001:db8::1".
string ip_address = 1;
// Port number.
int32 port = 2;
// Network protocol (e.g., TCP, UDP) associated with this endpoint.
NetworkProtocol protocol = 3;
}
message Identity {
oneof identity_oneof {
// Service account of a connection endpoint.
string service_account = 1;
// Hostname of a connection endpoint.
string hostname = 2;
}
}
message StartClientHandshakeReq {
// Handshake security protocol requested by the client.
HandshakeProtocol handshake_security_protocol = 1;
// The application protocols supported by the client, e.g., "h2" (for http2),
// "grpc".
repeated string application_protocols = 2;
// The record protocols supported by the client, e.g.,
// "ALTSRP_GCM_AES128".
repeated string record_protocols = 3;
// (Optional) Describes which server identities are acceptable by the client.
// If target identities are provided and none of them matches the peer
// identity of the server, handshake will fail.
repeated Identity target_identities = 4;
// (Optional) Application may specify a local identity. Otherwise, the
// handshaker chooses a default local identity.
Identity local_identity = 5;
// (Optional) Local endpoint information of the connection to the server,
// such as local IP address, port number, and network protocol.
Endpoint local_endpoint = 6;
// (Optional) Endpoint information of the remote server, such as IP address,
// port number, and network protocool.
Endpoint remote_endpoint = 7;
// (Optional) If target name is provided, a secure naming check is performed
// to verify that the peer authenticated identity is indeed authorized to run
// the target name.
string target_name = 8;
// (Optional) RPC protocol versions supported by the client.
RpcProtocolVersions rpc_versions = 9;
}
message ServerHandshakeParameters {
// The record protocols supported by the server, e.g.,
// "ALTSRP_GCM_AES128".
repeated string record_protocols = 1;
// (Optional) A list of local identities supported by the server, if
// specified. Otherwise, the handshaker chooses a default local identity.
repeated Identity local_identities = 2;
}
message StartServerHandshakeReq {
// The application protocols supported by the server, e.g., "h2" (for http2),
// "grpc".
repeated string application_protocols = 1;
// Handshake parameters (record protocols and local identities supported by
// the server) mapped by the handshake protocol. Each handshake security
// protocol (e.g., TLS or ALTS) has its own set of record protocols and local
// identities. Since protobuf does not support enum as key to the map, the key
// to handshake_parameters is the integer value of HandshakeProtocol enum.
map<int32, ServerHandshakeParameters> handshake_parameters = 2;
// Bytes in out_frames returned from the peer's HandshakerResp. It is possible
// that the peer's out_frames are split into multiple HandshakReq messages.
bytes in_bytes = 3;
// (Optional) Local endpoint information of the connection to the client,
// such as local IP address, port number, and network protocol.
Endpoint local_endpoint = 4;
// (Optional) Endpoint information of the remote client, such as IP address,
// port number, and network protocool.
Endpoint remote_endpoint = 5;
// (Optional) RPC protocol versions supported by the server.
RpcProtocolVersions rpc_versions = 6;
}
message NextHandshakeMessageReq {
// Bytes in out_frames returned from the peer's HandshakerResp. It is possible
// that the peer's out_frames are split into multiple NextHandshakerMessageReq
// messages.
bytes in_bytes = 1;
}
message HandshakerReq {
oneof req_oneof {
// The start client handshake request message.
StartClientHandshakeReq client_start = 1;
// The start server handshake request message.
StartServerHandshakeReq server_start = 2;
// The next handshake request message.
NextHandshakeMessageReq next = 3;
}
}
message HandshakerResult {
// The application protocol negotiated for this connection.
string application_protocol = 1;
// The record protocol negotiated for this connection.
string record_protocol = 2;
// Cryptographic key data. The key data may be more than the key length
// required for the record protocol, thus the client of the handshaker
// service needs to truncate the key data into the right key length.
bytes key_data = 3;
// The authenticated identity of the peer.
Identity peer_identity = 4;
// The local identity used in the handshake.
Identity local_identity = 5;
// Indicate whether the handshaker service client should keep the channel
// between the handshaker service open, e.g., in order to handle
// post-handshake messages in the future.
bool keep_channel_open = 6;
// The RPC protocol versions supported by the peer.
RpcProtocolVersions peer_rpc_versions = 7;
}
message HandshakerStatus {
// The status code. This could be the gRPC status code.
uint32 code = 1;
// The status details.
string details = 2;
}
message HandshakerResp {
// Frames to be given to the peer for the NextHandshakeMessageReq. May be
// empty if no out_frames have to be sent to the peer or if in_bytes in the
// HandshakerReq are incomplete. All the non-empty out frames must be sent to
// the peer even if the handshaker status is not OK as these frames may
// contain the alert frames.
bytes out_frames = 1;
// Number of bytes in the in_bytes consumed by the handshaker. It is possible
// that part of in_bytes in HandshakerReq was unrelated to the handshake
// process.
uint32 bytes_consumed = 2;
// This is set iff the handshake was successful. out_frames may still be set
// to frames that needs to be forwarded to the peer.
HandshakerResult result = 3;
// Status of the handshaker.
HandshakerStatus status = 4;
}
service HandshakerService {
// Accepts a stream of handshaker request, returning a stream of handshaker
// response.
rpc DoHandshake(stream HandshakerReq)
returns (stream HandshakerResp) {
}
}

@ -0,0 +1,40 @@
// Copyright 2018 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.
syntax = "proto3";
package grpc.gcp;
option java_package = "io.grpc.alts";
// The security level of the created channel. The list is sorted in increasing
// level of security. This order must always be maintained.
enum SecurityLevel {
SECURITY_NONE = 0;
INTEGRITY_ONLY = 1;
INTEGRITY_AND_PRIVACY = 2;
}
// Max and min supported RPC protocol versions.
message RpcProtocolVersions {
// RPC version contains a major version and a minor version.
message Version {
uint32 major = 1;
uint32 minor = 2;
}
// Maximum supported RPC version.
Version max_rpc_version = 1;
// Minimum supported RPC version.
Version min_rpc_version = 2;
}

@ -0,0 +1,50 @@
/* Automatically generated nanopb constant definitions */
/* Generated by nanopb-0.3.7-dev */
#include "src/core/tsi/alts/handshaker/transport_security_common.pb.h"
/* @@protoc_insertion_point(includes) */
#if PB_PROTO_HEADER_VERSION != 30
#error Regenerate this file with the current version of nanopb generator.
#endif
const pb_field_t grpc_gcp_RpcProtocolVersions_fields[3] = {
PB_FIELD( 1, MESSAGE , OPTIONAL, STATIC , FIRST, grpc_gcp_RpcProtocolVersions, max_rpc_version, max_rpc_version, &grpc_gcp_RpcProtocolVersions_Version_fields),
PB_FIELD( 2, MESSAGE , OPTIONAL, STATIC , OTHER, grpc_gcp_RpcProtocolVersions, min_rpc_version, max_rpc_version, &grpc_gcp_RpcProtocolVersions_Version_fields),
PB_LAST_FIELD
};
const pb_field_t grpc_gcp_RpcProtocolVersions_Version_fields[3] = {
PB_FIELD( 1, UINT32 , OPTIONAL, STATIC , FIRST, grpc_gcp_RpcProtocolVersions_Version, major, major, 0),
PB_FIELD( 2, UINT32 , OPTIONAL, STATIC , OTHER, grpc_gcp_RpcProtocolVersions_Version, minor, major, 0),
PB_LAST_FIELD
};
/* Check that field information fits in pb_field_t */
#if !defined(PB_FIELD_32BIT)
/* If you get an error here, it means that you need to define PB_FIELD_32BIT
* compile-time option. You can do that in pb.h or on compiler command line.
*
* The reason you need to do this is that some of your messages contain tag
* numbers or field sizes that are larger than what can fit in 8 or 16 bit
* field descriptors.
*/
PB_STATIC_ASSERT((pb_membersize(grpc_gcp_RpcProtocolVersions, max_rpc_version) < 65536 && pb_membersize(grpc_gcp_RpcProtocolVersions, min_rpc_version) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_grpc_gcp_RpcProtocolVersions_grpc_gcp_RpcProtocolVersions_Version)
#endif
#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT)
/* If you get an error here, it means that you need to define PB_FIELD_16BIT
* compile-time option. You can do that in pb.h or on compiler command line.
*
* The reason you need to do this is that some of your messages contain tag
* numbers or field sizes that are larger than what can fit in the default
* 8 bit descriptors.
*/
PB_STATIC_ASSERT((pb_membersize(grpc_gcp_RpcProtocolVersions, max_rpc_version) < 256 && pb_membersize(grpc_gcp_RpcProtocolVersions, min_rpc_version) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_grpc_gcp_RpcProtocolVersions_grpc_gcp_RpcProtocolVersions_Version)
#endif
/* @@protoc_insertion_point(eof) */

@ -0,0 +1,78 @@
/* Automatically generated nanopb header */
/* Generated by nanopb-0.3.7-dev */
#ifndef PB_GRPC_GCP_TRANSPORT_SECURITY_COMMON_PB_H_INCLUDED
#define PB_GRPC_GCP_TRANSPORT_SECURITY_COMMON_PB_H_INCLUDED
#include "third_party/nanopb/pb.h"
/* @@protoc_insertion_point(includes) */
#if PB_PROTO_HEADER_VERSION != 30
#error Regenerate this file with the current version of nanopb generator.
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* Enum definitions */
typedef enum _grpc_gcp_SecurityLevel {
grpc_gcp_SecurityLevel_SECURITY_NONE = 0,
grpc_gcp_SecurityLevel_INTEGRITY_ONLY = 1,
grpc_gcp_SecurityLevel_INTEGRITY_AND_PRIVACY = 2
} grpc_gcp_SecurityLevel;
#define _grpc_gcp_SecurityLevel_MIN grpc_gcp_SecurityLevel_SECURITY_NONE
#define _grpc_gcp_SecurityLevel_MAX grpc_gcp_SecurityLevel_INTEGRITY_AND_PRIVACY
#define _grpc_gcp_SecurityLevel_ARRAYSIZE ((grpc_gcp_SecurityLevel)(grpc_gcp_SecurityLevel_INTEGRITY_AND_PRIVACY+1))
/* Struct definitions */
typedef struct _grpc_gcp_RpcProtocolVersions_Version {
bool has_major;
uint32_t major;
bool has_minor;
uint32_t minor;
/* @@protoc_insertion_point(struct:grpc_gcp_RpcProtocolVersions_Version) */
} grpc_gcp_RpcProtocolVersions_Version;
typedef struct _grpc_gcp_RpcProtocolVersions {
bool has_max_rpc_version;
grpc_gcp_RpcProtocolVersions_Version max_rpc_version;
bool has_min_rpc_version;
grpc_gcp_RpcProtocolVersions_Version min_rpc_version;
/* @@protoc_insertion_point(struct:grpc_gcp_RpcProtocolVersions) */
} grpc_gcp_RpcProtocolVersions;
/* Default values for struct fields */
/* Initializer values for message structs */
#define grpc_gcp_RpcProtocolVersions_init_default {false, grpc_gcp_RpcProtocolVersions_Version_init_default, false, grpc_gcp_RpcProtocolVersions_Version_init_default}
#define grpc_gcp_RpcProtocolVersions_Version_init_default {false, 0, false, 0}
#define grpc_gcp_RpcProtocolVersions_init_zero {false, grpc_gcp_RpcProtocolVersions_Version_init_zero, false, grpc_gcp_RpcProtocolVersions_Version_init_zero}
#define grpc_gcp_RpcProtocolVersions_Version_init_zero {false, 0, false, 0}
/* Field tags (for use in manual encoding/decoding) */
#define grpc_gcp_RpcProtocolVersions_Version_major_tag 1
#define grpc_gcp_RpcProtocolVersions_Version_minor_tag 2
#define grpc_gcp_RpcProtocolVersions_max_rpc_version_tag 1
#define grpc_gcp_RpcProtocolVersions_min_rpc_version_tag 2
/* Struct field encoding specification for nanopb */
extern const pb_field_t grpc_gcp_RpcProtocolVersions_fields[3];
extern const pb_field_t grpc_gcp_RpcProtocolVersions_Version_fields[3];
/* Maximum encoded size of messages (where known) */
#define grpc_gcp_RpcProtocolVersions_size 28
#define grpc_gcp_RpcProtocolVersions_Version_size 12
/* Message IDs (where set with "msgid" option) */
#ifdef PB_MSGID
#define TRANSPORT_SECURITY_COMMON_MESSAGES \
#endif
#ifdef __cplusplus
} /* extern "C" */
#endif
/* @@protoc_insertion_point(eof) */
#endif

@ -0,0 +1,196 @@
/*
*
* Copyright 2018 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 <grpc/support/port_platform.h>
#include "src/core/tsi/alts/handshaker/transport_security_common_api.h"
bool grpc_gcp_rpc_protocol_versions_set_max(
grpc_gcp_rpc_protocol_versions* versions, uint32_t max_major,
uint32_t max_minor) {
if (versions == nullptr) {
gpr_log(GPR_ERROR,
"versions is nullptr in "
"grpc_gcp_rpc_protocol_versions_set_max().");
return false;
}
versions->has_max_rpc_version = true;
versions->max_rpc_version.has_major = true;
versions->max_rpc_version.has_minor = true;
versions->max_rpc_version.major = max_major;
versions->max_rpc_version.minor = max_minor;
return true;
}
bool grpc_gcp_rpc_protocol_versions_set_min(
grpc_gcp_rpc_protocol_versions* versions, uint32_t min_major,
uint32_t min_minor) {
if (versions == nullptr) {
gpr_log(GPR_ERROR,
"versions is nullptr in "
"grpc_gcp_rpc_protocol_versions_set_min().");
return false;
}
versions->has_min_rpc_version = true;
versions->min_rpc_version.has_major = true;
versions->min_rpc_version.has_minor = true;
versions->min_rpc_version.major = min_major;
versions->min_rpc_version.minor = min_minor;
return true;
}
size_t grpc_gcp_rpc_protocol_versions_encode_length(
const grpc_gcp_rpc_protocol_versions* versions) {
if (versions == nullptr) {
gpr_log(GPR_ERROR,
"Invalid nullptr arguments to "
"grpc_gcp_rpc_protocol_versions_encode_length().");
return 0;
}
pb_ostream_t size_stream;
memset(&size_stream, 0, sizeof(pb_ostream_t));
if (!pb_encode(&size_stream, grpc_gcp_RpcProtocolVersions_fields, versions)) {
gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(&size_stream));
return 0;
}
return size_stream.bytes_written;
}
bool grpc_gcp_rpc_protocol_versions_encode_to_raw_bytes(
const grpc_gcp_rpc_protocol_versions* versions, uint8_t* bytes,
size_t bytes_length) {
if (versions == nullptr || bytes == nullptr || bytes_length == 0) {
gpr_log(GPR_ERROR,
"Invalid nullptr arguments to "
"grpc_gcp_rpc_protocol_versions_encode_to_raw_bytes().");
return false;
}
pb_ostream_t output_stream = pb_ostream_from_buffer(bytes, bytes_length);
if (!pb_encode(&output_stream, grpc_gcp_RpcProtocolVersions_fields,
versions)) {
gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(&output_stream));
return false;
}
return true;
}
bool grpc_gcp_rpc_protocol_versions_encode(
const grpc_gcp_rpc_protocol_versions* versions, grpc_slice* slice) {
if (versions == nullptr || slice == nullptr) {
gpr_log(GPR_ERROR,
"Invalid nullptr arguments to "
"grpc_gcp_rpc_protocol_versions_encode().");
return false;
}
size_t encoded_length =
grpc_gcp_rpc_protocol_versions_encode_length(versions);
if (encoded_length == 0) return false;
*slice = grpc_slice_malloc(encoded_length);
return grpc_gcp_rpc_protocol_versions_encode_to_raw_bytes(
versions, GRPC_SLICE_START_PTR(*slice), encoded_length);
}
bool grpc_gcp_rpc_protocol_versions_decode(
grpc_slice slice, grpc_gcp_rpc_protocol_versions* versions) {
if (versions == nullptr) {
gpr_log(GPR_ERROR,
"version is nullptr in "
"grpc_gcp_rpc_protocol_versions_decode().");
return false;
}
pb_istream_t stream = pb_istream_from_buffer(GRPC_SLICE_START_PTR(slice),
GRPC_SLICE_LENGTH(slice));
if (!pb_decode(&stream, grpc_gcp_RpcProtocolVersions_fields, versions)) {
gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(&stream));
return false;
}
return true;
}
bool grpc_gcp_rpc_protocol_versions_copy(
const grpc_gcp_rpc_protocol_versions* src,
grpc_gcp_rpc_protocol_versions* dst) {
if ((src == nullptr && dst != nullptr) ||
(src != nullptr && dst == nullptr)) {
gpr_log(GPR_ERROR,
"Invalid arguments to "
"grpc_gcp_rpc_protocol_versions_copy().");
return false;
}
if (src == nullptr) {
return true;
}
grpc_gcp_rpc_protocol_versions_set_max(dst, src->max_rpc_version.major,
src->max_rpc_version.minor);
grpc_gcp_rpc_protocol_versions_set_min(dst, src->min_rpc_version.major,
src->min_rpc_version.minor);
return true;
}
namespace grpc_core {
namespace internal {
int grpc_gcp_rpc_protocol_version_compare(
const grpc_gcp_rpc_protocol_versions_version* v1,
const grpc_gcp_rpc_protocol_versions_version* v2) {
if ((v1->major > v2->major) ||
(v1->major == v2->major && v1->minor > v2->minor)) {
return 1;
}
if ((v1->major < v2->major) ||
(v1->major == v2->major && v1->minor < v2->minor)) {
return -1;
}
return 0;
}
} // namespace internal
} // namespace grpc_core
bool grpc_gcp_rpc_protocol_versions_check(
const grpc_gcp_rpc_protocol_versions* local_versions,
const grpc_gcp_rpc_protocol_versions* peer_versions,
grpc_gcp_rpc_protocol_versions_version* highest_common_version) {
if (local_versions == nullptr || peer_versions == nullptr) {
gpr_log(GPR_ERROR,
"Invalid arguments to "
"grpc_gcp_rpc_protocol_versions_check().");
return false;
}
/* max_common_version is MIN(local.max, peer.max) */
const grpc_gcp_rpc_protocol_versions_version* max_common_version =
grpc_core::internal::grpc_gcp_rpc_protocol_version_compare(
&local_versions->max_rpc_version, &peer_versions->max_rpc_version) > 0
? &peer_versions->max_rpc_version
: &local_versions->max_rpc_version;
/* min_common_version is MAX(local.min, peer.min) */
const grpc_gcp_rpc_protocol_versions_version* min_common_version =
grpc_core::internal::grpc_gcp_rpc_protocol_version_compare(
&local_versions->min_rpc_version, &peer_versions->min_rpc_version) > 0
? &local_versions->min_rpc_version
: &peer_versions->min_rpc_version;
bool result = grpc_core::internal::grpc_gcp_rpc_protocol_version_compare(
max_common_version, min_common_version) >= 0
? true
: false;
if (result && highest_common_version != nullptr) {
memcpy(highest_common_version, max_common_version,
sizeof(grpc_gcp_rpc_protocol_versions_version));
}
return result;
}

@ -0,0 +1,163 @@
/*
*
* Copyright 2018 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_CORE_TSI_ALTS_HANDSHAKER_TRANSPORT_SECURITY_COMMON_API_H
#define GRPC_CORE_TSI_ALTS_HANDSHAKER_TRANSPORT_SECURITY_COMMON_API_H
#include <grpc/support/port_platform.h>
#include "third_party/nanopb/pb_decode.h"
#include "third_party/nanopb/pb_encode.h"
#include <grpc/slice.h>
#include <grpc/slice_buffer.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "src/core/tsi/alts/handshaker/transport_security_common.pb.h"
typedef grpc_gcp_RpcProtocolVersions grpc_gcp_rpc_protocol_versions;
typedef grpc_gcp_RpcProtocolVersions_Version
grpc_gcp_rpc_protocol_versions_version;
/**
* This method sets the value for max_rpc_versions field of rpc protocol
* versions.
*
* - versions: an rpc protocol version instance.
* - max_major: a major version of maximum supported RPC version.
* - max_minor: a minor version of maximum supported RPC version.
*
* The method returns true on success and false otherwise.
*/
bool grpc_gcp_rpc_protocol_versions_set_max(
grpc_gcp_rpc_protocol_versions* versions, uint32_t max_major,
uint32_t max_minor);
/**
* This method sets the value for min_rpc_versions field of rpc protocol
* versions.
*
* - versions: an rpc protocol version instance.
* - min_major: a major version of minimum supported RPC version.
* - min_minor: a minor version of minimum supported RPC version.
*
* The method returns true on success and false otherwise.
*/
bool grpc_gcp_rpc_protocol_versions_set_min(
grpc_gcp_rpc_protocol_versions* versions, uint32_t min_major,
uint32_t min_minor);
/**
* This method computes serialized byte length of rpc protocol versions.
*
* - versions: an rpc protocol versions instance.
*
* The method returns serialized byte length. It returns 0 on failure.
*/
size_t grpc_gcp_rpc_protocol_versions_encode_length(
const grpc_gcp_rpc_protocol_versions* versions);
/**
* This method serializes rpc protocol versions and writes the result to
* the memory buffer provided by the caller. Caller is responsible for
* allocating sufficient memory to store the serialized data.
*
* - versions: an rpc protocol versions instance.
* - bytes: bytes buffer where the result will be written to.
* - bytes_length: length of the bytes buffer.
*
* The method returns true on success and false otherwise.
*/
bool grpc_gcp_rpc_protocol_versions_encode_to_raw_bytes(
const grpc_gcp_rpc_protocol_versions* versions, uint8_t* bytes,
size_t bytes_length);
/**
* This method serializes an rpc protocol version and returns serialized rpc
* versions in grpc slice.
*
* - versions: an rpc protocol versions instance.
* - slice: grpc slice where the serialized result will be written.
*
* The method returns true on success and false otherwise.
*/
bool grpc_gcp_rpc_protocol_versions_encode(
const grpc_gcp_rpc_protocol_versions* versions, grpc_slice* slice);
/**
* This method de-serializes input in grpc slice form and stores the result
* in rpc protocol versions.
*
* - slice: a data stream containing a serialized rpc protocol version.
* - versions: an rpc protocol version instance used to hold de-serialized
* result.
*
* The method returns true on success and false otherwise.
*/
bool grpc_gcp_rpc_protocol_versions_decode(
grpc_slice slice, grpc_gcp_rpc_protocol_versions* versions);
/**
* This method performs a deep copy operation on rpc protocol versions
* instance.
*
* - src: rpc protocol versions instance that needs to be copied.
* - dst: rpc protocol versions instance that stores the copied result.
*
* The method returns true on success and false otherwise.
*/
bool grpc_gcp_rpc_protocol_versions_copy(
const grpc_gcp_rpc_protocol_versions* src,
grpc_gcp_rpc_protocol_versions* dst);
/**
* This method performs a version check between local and peer rpc protocol
* versions.
*
* - local_versions: local rpc protocol versions instance.
* - peer_versions: peer rpc protocol versions instance.
* - highest_common_version: an output parameter that will store the highest
* common rpc protocol version both parties agreed on.
*
* The method returns true if the check passes which means both parties agreed
* on a common rpc protocol to use, and false otherwise.
*/
bool grpc_gcp_rpc_protocol_versions_check(
const grpc_gcp_rpc_protocol_versions* local_versions,
const grpc_gcp_rpc_protocol_versions* peer_versions,
grpc_gcp_rpc_protocol_versions_version* highest_common_version);
namespace grpc_core {
namespace internal {
/**
* Exposed for testing only.
* The method returns 0 if v1 = v2,
* returns 1 if v1 > v2,
* returns -1 if v1 < v2.
*/
int grpc_gcp_rpc_protocol_version_compare(
const grpc_gcp_rpc_protocol_versions_version* v1,
const grpc_gcp_rpc_protocol_versions_version* v2);
} // namespace internal
} // namespace grpc_core
#endif /* GRPC_CORE_TSI_ALTS_HANDSHAKER_TRANSPORT_SECURITY_COMMON_API_H */

@ -0,0 +1,180 @@
/*
*
* Copyright 2018 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 <grpc/support/port_platform.h>
#include "src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.h"
#include "src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.h"
/* Main struct for alts_grpc_integrity_only_record_protocol. */
typedef struct alts_grpc_integrity_only_record_protocol {
alts_grpc_record_protocol base;
grpc_slice_buffer data_sb;
unsigned char* tag_buf;
} alts_grpc_integrity_only_record_protocol;
/* --- alts_grpc_record_protocol methods implementation. --- */
static tsi_result alts_grpc_integrity_only_protect(
alts_grpc_record_protocol* rp, grpc_slice_buffer* unprotected_slices,
grpc_slice_buffer* protected_slices) {
/* Input sanity check. */
if (rp == nullptr || unprotected_slices == nullptr ||
protected_slices == nullptr) {
gpr_log(GPR_ERROR,
"Invalid nullptr arguments to alts_grpc_record_protocol protect.");
return TSI_INVALID_ARGUMENT;
}
/* Allocates memory for header and tag slices. */
grpc_slice header_slice = GRPC_SLICE_MALLOC(rp->header_length);
grpc_slice tag_slice = GRPC_SLICE_MALLOC(rp->tag_length);
/* Calls alts_iovec_record_protocol protect. */
char* error_details = nullptr;
iovec_t header_iovec = {GRPC_SLICE_START_PTR(header_slice),
GRPC_SLICE_LENGTH(header_slice)};
iovec_t tag_iovec = {GRPC_SLICE_START_PTR(tag_slice),
GRPC_SLICE_LENGTH(tag_slice)};
alts_grpc_record_protocol_convert_slice_buffer_to_iovec(rp,
unprotected_slices);
grpc_status_code status = alts_iovec_record_protocol_integrity_only_protect(
rp->iovec_rp, rp->iovec_buf, unprotected_slices->count, header_iovec,
tag_iovec, &error_details);
if (status != GRPC_STATUS_OK) {
gpr_log(GPR_ERROR, "Failed to protect, %s", error_details);
gpr_free(error_details);
return TSI_INTERNAL_ERROR;
}
/* Appends result to protected_slices. */
grpc_slice_buffer_add(protected_slices, header_slice);
grpc_slice_buffer_move_into(unprotected_slices, protected_slices);
grpc_slice_buffer_add(protected_slices, tag_slice);
return TSI_OK;
}
static tsi_result alts_grpc_integrity_only_unprotect(
alts_grpc_record_protocol* rp, grpc_slice_buffer* protected_slices,
grpc_slice_buffer* unprotected_slices) {
/* Input sanity check. */
if (rp == nullptr || protected_slices == nullptr ||
unprotected_slices == nullptr) {
gpr_log(
GPR_ERROR,
"Invalid nullptr arguments to alts_grpc_record_protocol unprotect.");
return TSI_INVALID_ARGUMENT;
}
if (protected_slices->length < rp->header_length + rp->tag_length) {
gpr_log(GPR_ERROR, "Protected slices do not have sufficient data.");
return TSI_INVALID_ARGUMENT;
}
/* In this method, rp points to alts_grpc_record_protocol struct
* and integrity_only_record_protocol points to
* alts_grpc_integrity_only_record_protocol struct. */
alts_grpc_integrity_only_record_protocol* integrity_only_record_protocol =
reinterpret_cast<alts_grpc_integrity_only_record_protocol*>(rp);
/* Strips frame header from protected slices. */
grpc_slice_buffer_reset_and_unref_internal(&rp->header_sb);
grpc_slice_buffer_move_first(protected_slices, rp->header_length,
&rp->header_sb);
GPR_ASSERT(rp->header_sb.length == rp->header_length);
iovec_t header_iovec = alts_grpc_record_protocol_get_header_iovec(rp);
/* Moves protected slices data to data_sb and leaves the remaining tag. */
grpc_slice_buffer_reset_and_unref_internal(
&integrity_only_record_protocol->data_sb);
grpc_slice_buffer_move_first(protected_slices,
protected_slices->length - rp->tag_length,
&integrity_only_record_protocol->data_sb);
GPR_ASSERT(protected_slices->length == rp->tag_length);
iovec_t tag_iovec = {nullptr, rp->tag_length};
if (protected_slices->count == 1) {
tag_iovec.iov_base = GRPC_SLICE_START_PTR(protected_slices->slices[0]);
} else {
/* Frame tag is in multiple slices, copies the tag bytes from slice
* buffer to a single flat buffer. */
alts_grpc_record_protocol_copy_slice_buffer(
protected_slices, integrity_only_record_protocol->tag_buf);
tag_iovec.iov_base = integrity_only_record_protocol->tag_buf;
}
/* Calls alts_iovec_record_protocol unprotect. */
char* error_details = nullptr;
alts_grpc_record_protocol_convert_slice_buffer_to_iovec(
rp, &integrity_only_record_protocol->data_sb);
grpc_status_code status = alts_iovec_record_protocol_integrity_only_unprotect(
rp->iovec_rp, rp->iovec_buf,
integrity_only_record_protocol->data_sb.count, header_iovec, tag_iovec,
&error_details);
if (status != GRPC_STATUS_OK) {
gpr_log(GPR_ERROR, "Failed to unprotect, %s", error_details);
gpr_free(error_details);
return TSI_INTERNAL_ERROR;
}
grpc_slice_buffer_reset_and_unref_internal(&rp->header_sb);
grpc_slice_buffer_reset_and_unref_internal(protected_slices);
grpc_slice_buffer_move_into(&integrity_only_record_protocol->data_sb,
unprotected_slices);
return TSI_OK;
}
static void alts_grpc_integrity_only_destruct(alts_grpc_record_protocol* rp) {
if (rp == nullptr) {
return;
}
alts_grpc_integrity_only_record_protocol* integrity_only_rp =
reinterpret_cast<alts_grpc_integrity_only_record_protocol*>(rp);
grpc_slice_buffer_destroy_internal(&integrity_only_rp->data_sb);
gpr_free(integrity_only_rp->tag_buf);
}
static const alts_grpc_record_protocol_vtable
alts_grpc_integrity_only_record_protocol_vtable = {
alts_grpc_integrity_only_protect, alts_grpc_integrity_only_unprotect,
alts_grpc_integrity_only_destruct};
tsi_result alts_grpc_integrity_only_record_protocol_create(
gsec_aead_crypter* crypter, size_t overflow_size, bool is_client,
bool is_protect, alts_grpc_record_protocol** rp) {
if (crypter == nullptr || rp == nullptr) {
gpr_log(GPR_ERROR,
"Invalid nullptr arguments to alts_grpc_record_protocol create.");
return TSI_INVALID_ARGUMENT;
}
alts_grpc_integrity_only_record_protocol* impl =
static_cast<alts_grpc_integrity_only_record_protocol*>(
gpr_zalloc(sizeof(alts_grpc_integrity_only_record_protocol)));
/* Calls alts_grpc_record_protocol init. */
tsi_result result = alts_grpc_record_protocol_init(
&impl->base, crypter, overflow_size, is_client,
/*is_integrity_only=*/true, is_protect);
if (result != TSI_OK) {
gpr_free(impl);
return result;
}
/* Initializes slice buffer for data_sb. */
grpc_slice_buffer_init(&impl->data_sb);
/* Allocates tag buffer. */
impl->tag_buf =
static_cast<unsigned char*>(gpr_malloc(impl->base.tag_length));
impl->base.vtable = &alts_grpc_integrity_only_record_protocol_vtable;
*rp = &impl->base;
return TSI_OK;
}

@ -0,0 +1,52 @@
/*
*
* Copyright 2018 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_CORE_TSI_ALTS_ZERO_COPY_FRAME_PROTECTOR_ALTS_GRPC_INTEGRITY_ONLY_RECORD_PROTOCOL_H
#define GRPC_CORE_TSI_ALTS_ZERO_COPY_FRAME_PROTECTOR_ALTS_GRPC_INTEGRITY_ONLY_RECORD_PROTOCOL_H
#include <grpc/support/port_platform.h>
#include <stdbool.h>
#include "src/core/tsi/alts/crypt/gsec.h"
#include "src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol.h"
/**
* This method creates an integrity-only alts_grpc_record_protocol instance,
* given a gsec_aead_crypter instance and a flag indicating if the created
* instance will be used at the client or server side. The ownership of
* gsec_aead_crypter instance is transferred to this new object.
*
* - crypter: a gsec_aead_crypter instance used to perform AEAD decryption.
* - overflow_size: overflow size of counter in bytes.
* - is_client: a flag indicating if the alts_grpc_record_protocol instance will
* be used at the client or server side.
* - is_protect: a flag indicating if the alts_grpc_record_protocol instance
* will be used for protect or unprotect.
* - rp: an alts_grpc_record_protocol instance to be returned from
* the method.
*
* This method returns TSI_OK in case of success or a specific error code in
* case of failure.
*/
tsi_result alts_grpc_integrity_only_record_protocol_create(
gsec_aead_crypter* crypter, size_t overflow_size, bool is_client,
bool is_protect, alts_grpc_record_protocol** rp);
#endif /* GRPC_CORE_TSI_ALTS_ZERO_COPY_FRAME_PROTECTOR_ALTS_GRPC_INTEGRITY_ONLY_RECORD_PROTOCOL_H \
*/

@ -0,0 +1,144 @@
/*
*
* Copyright 2018 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 <grpc/support/port_platform.h>
#include "src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.h"
#include "src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.h"
/* Privacy-integrity alts_grpc_record_protocol object uses the same struct
* defined in alts_grpc_record_protocol_common.h. */
/* --- alts_grpc_record_protocol methods implementation. --- */
static tsi_result alts_grpc_privacy_integrity_protect(
alts_grpc_record_protocol* rp, grpc_slice_buffer* unprotected_slices,
grpc_slice_buffer* protected_slices) {
/* Input sanity check. */
if (rp == nullptr || unprotected_slices == nullptr ||
protected_slices == nullptr) {
gpr_log(GPR_ERROR,
"Invalid nullptr arguments to alts_grpc_record_protocol protect.");
return TSI_INVALID_ARGUMENT;
}
/* Allocates memory for output frame. In privacy-integrity protect, the
* protected frame is stored in a newly allocated buffer. */
size_t protected_frame_size =
unprotected_slices->length + rp->header_length +
alts_iovec_record_protocol_get_tag_length(rp->iovec_rp);
grpc_slice protected_slice = GRPC_SLICE_MALLOC(protected_frame_size);
iovec_t protected_iovec = {GRPC_SLICE_START_PTR(protected_slice),
GRPC_SLICE_LENGTH(protected_slice)};
/* Calls alts_iovec_record_protocol protect. */
char* error_details = nullptr;
alts_grpc_record_protocol_convert_slice_buffer_to_iovec(rp,
unprotected_slices);
grpc_status_code status =
alts_iovec_record_protocol_privacy_integrity_protect(
rp->iovec_rp, rp->iovec_buf, unprotected_slices->count,
protected_iovec, &error_details);
if (status != GRPC_STATUS_OK) {
gpr_log(GPR_ERROR, "Failed to protect, %s", error_details);
gpr_free(error_details);
grpc_slice_unref(protected_slice);
return TSI_INTERNAL_ERROR;
}
grpc_slice_buffer_add(protected_slices, protected_slice);
grpc_slice_buffer_reset_and_unref_internal(unprotected_slices);
return TSI_OK;
}
static tsi_result alts_grpc_privacy_integrity_unprotect(
alts_grpc_record_protocol* rp, grpc_slice_buffer* protected_slices,
grpc_slice_buffer* unprotected_slices) {
/* Input sanity check. */
if (rp == nullptr || protected_slices == nullptr ||
unprotected_slices == nullptr) {
gpr_log(
GPR_ERROR,
"Invalid nullptr arguments to alts_grpc_record_protocol unprotect.");
return TSI_INVALID_ARGUMENT;
}
/* Allocates memory for output frame. In privacy-integrity unprotect, the
* unprotected data are stored in a newly allocated buffer. */
if (protected_slices->length < rp->header_length + rp->tag_length) {
gpr_log(GPR_ERROR, "Protected slices do not have sufficient data.");
return TSI_INVALID_ARGUMENT;
}
size_t unprotected_frame_size =
protected_slices->length - rp->header_length - rp->tag_length;
grpc_slice unprotected_slice = GRPC_SLICE_MALLOC(unprotected_frame_size);
iovec_t unprotected_iovec = {GRPC_SLICE_START_PTR(unprotected_slice),
GRPC_SLICE_LENGTH(unprotected_slice)};
/* Strips frame header from protected slices. */
grpc_slice_buffer_reset_and_unref_internal(&rp->header_sb);
grpc_slice_buffer_move_first(protected_slices, rp->header_length,
&rp->header_sb);
iovec_t header_iovec = alts_grpc_record_protocol_get_header_iovec(rp);
/* Calls alts_iovec_record_protocol unprotect. */
char* error_details = nullptr;
alts_grpc_record_protocol_convert_slice_buffer_to_iovec(rp, protected_slices);
grpc_status_code status =
alts_iovec_record_protocol_privacy_integrity_unprotect(
rp->iovec_rp, header_iovec, rp->iovec_buf, protected_slices->count,
unprotected_iovec, &error_details);
if (status != GRPC_STATUS_OK) {
gpr_log(GPR_ERROR, "Failed to unprotect, %s", error_details);
gpr_free(error_details);
grpc_slice_unref(unprotected_slice);
return TSI_INTERNAL_ERROR;
}
grpc_slice_buffer_reset_and_unref_internal(&rp->header_sb);
grpc_slice_buffer_reset_and_unref_internal(protected_slices);
grpc_slice_buffer_add(unprotected_slices, unprotected_slice);
return TSI_OK;
}
static const alts_grpc_record_protocol_vtable
alts_grpc_privacy_integrity_record_protocol_vtable = {
alts_grpc_privacy_integrity_protect,
alts_grpc_privacy_integrity_unprotect, nullptr};
tsi_result alts_grpc_privacy_integrity_record_protocol_create(
gsec_aead_crypter* crypter, size_t overflow_size, bool is_client,
bool is_protect, alts_grpc_record_protocol** rp) {
if (crypter == nullptr || rp == nullptr) {
gpr_log(GPR_ERROR,
"Invalid nullptr arguments to alts_grpc_record_protocol create.");
return TSI_INVALID_ARGUMENT;
}
auto* impl = static_cast<alts_grpc_record_protocol*>(
gpr_zalloc(sizeof(alts_grpc_record_protocol)));
/* Calls alts_grpc_record_protocol init. */
tsi_result result =
alts_grpc_record_protocol_init(impl, crypter, overflow_size, is_client,
/*is_integrity_only=*/false, is_protect);
if (result != TSI_OK) {
gpr_free(impl);
return result;
}
impl->vtable = &alts_grpc_privacy_integrity_record_protocol_vtable;
*rp = impl;
return TSI_OK;
}

@ -0,0 +1,49 @@
/*
*
* Copyright 2018 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_CORE_TSI_ALTS_ZERO_COPY_FRAME_PROTECTOR_ALTS_GRPC_PRIVACY_INTEGRITY_RECORD_PROTOCOL_H
#define GRPC_CORE_TSI_ALTS_ZERO_COPY_FRAME_PROTECTOR_ALTS_GRPC_PRIVACY_INTEGRITY_RECORD_PROTOCOL_H
#include <grpc/support/port_platform.h>
#include <stdbool.h>
#include "src/core/tsi/alts/crypt/gsec.h"
#include "src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol.h"
/**
* This method creates a privacy-integrity alts_grpc_record_protocol instance,
* given a gsec_aead_crypter instance and a flag indicating if the created
* instance will be used at the client or server side. The ownership of
* gsec_aead_crypter instance is transferred to this new object.
*
* - crypter: a gsec_aead_crypter instance used to perform AEAD decryption.
* - is_client: a flag indicating if the alts_grpc_record_protocol instance will
* be used at the client or server side.
* - rp: an alts_grpc_record_protocol instance to be returned from
* the method.
*
* This method returns TSI_OK in case of success or a specific error code in
* case of failure.
*/
tsi_result alts_grpc_privacy_integrity_record_protocol_create(
gsec_aead_crypter* crypter, size_t overflow_size, bool is_client,
bool is_protect, alts_grpc_record_protocol** rp);
#endif /* GRPC_CORE_TSI_ALTS_ZERO_COPY_FRAME_PROTECTOR_ALTS_GRPC_PRIVACY_INTEGRITY_RECORD_PROTOCOL_H \
*/

@ -0,0 +1,91 @@
/*
*
* Copyright 2018 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_CORE_TSI_ALTS_ZERO_COPY_FRAME_PROTECTOR_ALTS_GRPC_RECORD_PROTOCOL_H
#define GRPC_CORE_TSI_ALTS_ZERO_COPY_FRAME_PROTECTOR_ALTS_GRPC_RECORD_PROTOCOL_H
#include <grpc/support/port_platform.h>
#include <grpc/slice_buffer.h>
#include "src/core/tsi/transport_security_interface.h"
/**
* This alts_grpc_record_protocol object protects and unprotects a single frame
* stored in grpc slice buffer with zero or minimized memory copy.
* Implementations of this object must be thread compatible.
*/
typedef struct alts_grpc_record_protocol alts_grpc_record_protocol;
/**
* This methods performs protect operation on unprotected data and appends the
* protected frame to protected_slices. The caller needs to ensure the length
* of unprotected data plus the frame overhead is less than or equal to the
* maximum frame length. The input unprotected data slice buffer will be
* cleared, although the actual unprotected data bytes are not modified.
*
* - self: an alts_grpc_record_protocol instance.
* - unprotected_slices: the unprotected data to be protected.
* - protected_slices: slice buffer where the protected frame is appended.
*
* This method returns TSI_OK in case of success or a specific error code in
* case of failure.
*/
tsi_result alts_grpc_record_protocol_protect(
alts_grpc_record_protocol* self, grpc_slice_buffer* unprotected_slices,
grpc_slice_buffer* protected_slices);
/**
* This methods performs unprotect operation on a full frame of protected data
* and appends unprotected data to unprotected_slices. It is the caller's
* responsibility to prepare a full frame of data before calling this method.
* The input protected frame slice buffer will be cleared, although the actual
* protected data bytes are not modified.
*
* - self: an alts_grpc_record_protocol instance.
* - protected_slices: a full frame of protected data in grpc slices.
* - unprotected_slices: slice buffer where unprotected data is appended.
*
* This method returns TSI_OK in case of success or a specific error code in
* case of failure.
*/
tsi_result alts_grpc_record_protocol_unprotect(
alts_grpc_record_protocol* self, grpc_slice_buffer* protected_slices,
grpc_slice_buffer* unprotected_slices);
/**
* This method returns maximum allowed unprotected data size, given maximum
* protected frame size.
*
* - self: an alts_grpc_record_protocol instance.
* - max_protected_frame_size: maximum protected frame size.
*
* On success, the method returns the maximum allowed unprotected data size.
* Otherwise, it returns zero.
*/
size_t alts_grpc_record_protocol_max_unprotected_data_size(
const alts_grpc_record_protocol* self, size_t max_protected_frame_size);
/**
* This method destroys an alts_grpc_record_protocol instance by de-allocating
* all of its occupied memory.
*/
void alts_grpc_record_protocol_destroy(alts_grpc_record_protocol* self);
#endif /* GRPC_CORE_TSI_ALTS_ZERO_COPY_FRAME_PROTECTOR_ALTS_GRPC_RECORD_PROTOCOL_H \
*/

@ -0,0 +1,173 @@
/*
*
* Copyright 2018 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 <grpc/support/port_platform.h>
#include "src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.h"
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "src/core/lib/gpr/useful.h"
#include "src/core/lib/slice/slice_internal.h"
const size_t kInitialIovecBufferSize = 8;
/* Makes sure iovec_buf in alts_grpc_record_protocol is large enough. */
static void ensure_iovec_buf_size(alts_grpc_record_protocol* rp,
const grpc_slice_buffer* sb) {
GPR_ASSERT(rp != nullptr && sb != nullptr);
if (sb->count <= rp->iovec_buf_length) {
return;
}
/* At least double the iovec buffer size. */
rp->iovec_buf_length = GPR_MAX(sb->count, 2 * rp->iovec_buf_length);
rp->iovec_buf = static_cast<iovec_t*>(
gpr_realloc(rp->iovec_buf, rp->iovec_buf_length * sizeof(iovec_t)));
}
/* --- Implementation of methods defined in tsi_grpc_record_protocol_common.h.
* --- */
void alts_grpc_record_protocol_convert_slice_buffer_to_iovec(
alts_grpc_record_protocol* rp, const grpc_slice_buffer* sb) {
GPR_ASSERT(rp != nullptr && sb != nullptr);
ensure_iovec_buf_size(rp, sb);
for (size_t i = 0; i < sb->count; i++) {
rp->iovec_buf[i].iov_base = GRPC_SLICE_START_PTR(sb->slices[i]);
rp->iovec_buf[i].iov_len = GRPC_SLICE_LENGTH(sb->slices[i]);
}
}
void alts_grpc_record_protocol_copy_slice_buffer(const grpc_slice_buffer* src,
unsigned char* dst) {
GPR_ASSERT(src != nullptr && dst != nullptr);
for (size_t i = 0; i < src->count; i++) {
size_t slice_length = GRPC_SLICE_LENGTH(src->slices[i]);
memcpy(dst, GRPC_SLICE_START_PTR(src->slices[i]), slice_length);
dst += slice_length;
}
}
iovec_t alts_grpc_record_protocol_get_header_iovec(
alts_grpc_record_protocol* rp) {
iovec_t header_iovec = {nullptr, 0};
if (rp == nullptr) {
return header_iovec;
}
header_iovec.iov_len = rp->header_length;
if (rp->header_sb.count == 1) {
header_iovec.iov_base = GRPC_SLICE_START_PTR(rp->header_sb.slices[0]);
} else {
/* Frame header is in multiple slices, copies the header bytes from slice
* buffer to a single flat buffer. */
alts_grpc_record_protocol_copy_slice_buffer(&rp->header_sb, rp->header_buf);
header_iovec.iov_base = rp->header_buf;
}
return header_iovec;
}
tsi_result alts_grpc_record_protocol_init(alts_grpc_record_protocol* rp,
gsec_aead_crypter* crypter,
size_t overflow_size, bool is_client,
bool is_integrity_only,
bool is_protect) {
if (rp == nullptr || crypter == nullptr) {
gpr_log(GPR_ERROR,
"Invalid nullptr arguments to alts_grpc_record_protocol init.");
return TSI_INVALID_ARGUMENT;
}
/* Creates alts_iovec_record_protocol. */
char* error_details = nullptr;
grpc_status_code status = alts_iovec_record_protocol_create(
crypter, overflow_size, is_client, is_integrity_only, is_protect,
&rp->iovec_rp, &error_details);
if (status != GRPC_STATUS_OK) {
gpr_log(GPR_ERROR, "Failed to create alts_iovec_record_protocol, %s.",
error_details);
gpr_free(error_details);
return TSI_INTERNAL_ERROR;
}
/* Allocates header slice buffer. */
grpc_slice_buffer_init(&rp->header_sb);
/* Allocates header buffer. */
rp->header_length = alts_iovec_record_protocol_get_header_length();
rp->header_buf = static_cast<unsigned char*>(gpr_malloc(rp->header_length));
rp->tag_length = alts_iovec_record_protocol_get_tag_length(rp->iovec_rp);
/* Allocates iovec buffer. */
rp->iovec_buf_length = kInitialIovecBufferSize;
rp->iovec_buf =
static_cast<iovec_t*>(gpr_malloc(rp->iovec_buf_length * sizeof(iovec_t)));
return TSI_OK;
}
/* --- Implementation of methods defined in tsi_grpc_record_protocol.h. --- */
tsi_result alts_grpc_record_protocol_protect(
alts_grpc_record_protocol* self, grpc_slice_buffer* unprotected_slices,
grpc_slice_buffer* protected_slices) {
if (grpc_core::ExecCtx::Get() == nullptr || self == nullptr ||
self->vtable == nullptr || unprotected_slices == nullptr ||
protected_slices == nullptr) {
return TSI_INVALID_ARGUMENT;
}
if (self->vtable->protect == nullptr) {
return TSI_UNIMPLEMENTED;
}
return self->vtable->protect(self, unprotected_slices, protected_slices);
}
tsi_result alts_grpc_record_protocol_unprotect(
alts_grpc_record_protocol* self, grpc_slice_buffer* protected_slices,
grpc_slice_buffer* unprotected_slices) {
if (grpc_core::ExecCtx::Get() == nullptr || self == nullptr ||
self->vtable == nullptr || protected_slices == nullptr ||
unprotected_slices == nullptr) {
return TSI_INVALID_ARGUMENT;
}
if (self->vtable->unprotect == nullptr) {
return TSI_UNIMPLEMENTED;
}
return self->vtable->unprotect(self, protected_slices, unprotected_slices);
}
void alts_grpc_record_protocol_destroy(alts_grpc_record_protocol* self) {
if (self == nullptr) {
return;
}
if (self->vtable->destruct != nullptr) {
self->vtable->destruct(self);
}
alts_iovec_record_protocol_destroy(self->iovec_rp);
grpc_slice_buffer_destroy_internal(&self->header_sb);
gpr_free(self->header_buf);
gpr_free(self->iovec_buf);
gpr_free(self);
}
/* Integrity-only and privacy-integrity share the same implementation. No need
* to call vtable. */
size_t alts_grpc_record_protocol_max_unprotected_data_size(
const alts_grpc_record_protocol* self, size_t max_protected_frame_size) {
if (self == nullptr) {
return 0;
}
return alts_iovec_record_protocol_max_unprotected_data_size(
self->iovec_rp, max_protected_frame_size);
}

@ -0,0 +1,100 @@
/*
*
* Copyright 2018 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_CORE_TSI_ALTS_ZERO_COPY_FRAME_PROTECTOR_ALTS_GRPC_RECORD_PROTOCOL_COMMON_H
#define GRPC_CORE_TSI_ALTS_ZERO_COPY_FRAME_PROTECTOR_ALTS_GRPC_RECORD_PROTOCOL_COMMON_H
/**
* this file contains alts_grpc_record_protocol internals and internal-only
* helper functions. The public functions of alts_grpc_record_protocol are
* defined in the alts_grpc_record_protocol.h.
*/
#include <grpc/support/port_platform.h>
#include "src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol.h"
#include "src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.h"
/* V-table for alts_grpc_record_protocol implementations. */
typedef struct {
tsi_result (*protect)(alts_grpc_record_protocol* self,
grpc_slice_buffer* unprotected_slices,
grpc_slice_buffer* protected_slices);
tsi_result (*unprotect)(alts_grpc_record_protocol* self,
grpc_slice_buffer* protected_slices,
grpc_slice_buffer* unprotected_slices);
void (*destruct)(alts_grpc_record_protocol* self);
} alts_grpc_record_protocol_vtable;
/* Main struct for alts_grpc_record_protocol implementation, shared by both
* integrity-only record protocol and privacy-integrity record protocol.
* Integrity-only record protocol has additional data elements.
* Privacy-integrity record protocol uses this struct directly. */
struct alts_grpc_record_protocol {
const alts_grpc_record_protocol_vtable* vtable;
alts_iovec_record_protocol* iovec_rp;
grpc_slice_buffer header_sb;
unsigned char* header_buf;
size_t header_length;
size_t tag_length;
iovec_t* iovec_buf;
size_t iovec_buf_length;
};
/**
* Converts the slices of input sb into iovec_t's and puts the result into
* rp->iovec_buf. Note that the actual data are not copied, only
* pointers and lengths are copied.
*/
void alts_grpc_record_protocol_convert_slice_buffer_to_iovec(
alts_grpc_record_protocol* rp, const grpc_slice_buffer* sb);
/**
* Copies bytes from slice buffer to destination buffer. Caller is responsible
* for allocating enough memory of destination buffer. This method is used for
* copying frame header and tag in case they are stored in multiple slices.
*/
void alts_grpc_record_protocol_copy_slice_buffer(const grpc_slice_buffer* src,
unsigned char* dst);
/**
* This method returns an iovec object pointing to the frame header stored in
* rp->header_sb. If the frame header is stored in multiple slices,
* this method will copy the bytes in rp->header_sb to
* rp->header_buf, and return an iovec object pointing to
* rp->header_buf.
*/
iovec_t alts_grpc_record_protocol_get_header_iovec(
alts_grpc_record_protocol* rp);
/**
* Initializes an alts_grpc_record_protocol object, given a gsec_aead_crypter
* instance, the overflow size of the counter in bytes, a flag indicating if the
* object is used for client or server side, a flag indicating if it is used for
* integrity-only or privacy-integrity mode, and a flag indicating if it is for
* protect or unprotect. The ownership of gsec_aead_crypter object is
* transferred to the alts_grpc_record_protocol object.
*/
tsi_result alts_grpc_record_protocol_init(alts_grpc_record_protocol* rp,
gsec_aead_crypter* crypter,
size_t overflow_size, bool is_client,
bool is_integrity_only,
bool is_protect);
#endif /* GRPC_CORE_TSI_ALTS_ZERO_COPY_FRAME_PROTECTOR_ALTS_GRPC_RECORD_PROTOCOL_COMMON_H \
*/

@ -0,0 +1,476 @@
/*
*
* Copyright 2018 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 <grpc/support/port_platform.h>
#include "src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.h"
#include <stdlib.h>
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "src/core/tsi/alts/frame_protector/alts_counter.h"
struct alts_iovec_record_protocol {
alts_counter* ctr;
gsec_aead_crypter* crypter;
size_t tag_length;
bool is_integrity_only;
bool is_protect;
};
/* Copies error message to destination. */
static void maybe_copy_error_msg(const char* src, char** dst) {
if (dst != nullptr && src != nullptr) {
*dst = static_cast<char*>(gpr_malloc(strlen(src) + 1));
memcpy(*dst, src, strlen(src) + 1);
}
}
/* Appends error message to destination. */
static void maybe_append_error_msg(const char* appendix, char** dst) {
if (dst != nullptr && appendix != nullptr) {
int dst_len = static_cast<int>(strlen(*dst));
*dst = static_cast<char*>(realloc(*dst, dst_len + strlen(appendix) + 1));
assert(*dst != nullptr);
memcpy(*dst + dst_len, appendix, strlen(appendix) + 1);
}
}
/* Use little endian to interpret a string of bytes as uint32_t. */
static uint32_t load_32_le(const unsigned char* buffer) {
return (((uint32_t)buffer[3]) << 24) | (((uint32_t)buffer[2]) << 16) |
(((uint32_t)buffer[1]) << 8) | ((uint32_t)buffer[0]);
}
/* Store uint32_t as a string of little endian bytes. */
static void store_32_le(uint32_t value, unsigned char* buffer) {
buffer[3] = (unsigned char)(value >> 24) & 0xFF;
buffer[2] = (unsigned char)(value >> 16) & 0xFF;
buffer[1] = (unsigned char)(value >> 8) & 0xFF;
buffer[0] = (unsigned char)(value)&0xFF;
}
/* Ensures header and tag iovec have sufficient length. */
static grpc_status_code ensure_header_and_tag_length(
const alts_iovec_record_protocol* rp, iovec_t header, iovec_t tag,
char** error_details) {
if (rp == nullptr) {
return GRPC_STATUS_FAILED_PRECONDITION;
}
if (header.iov_base == nullptr) {
maybe_copy_error_msg("Header is nullptr.", error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
if (header.iov_len != alts_iovec_record_protocol_get_header_length()) {
maybe_copy_error_msg("Header length is incorrect.", error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
if (tag.iov_base == nullptr) {
maybe_copy_error_msg("Tag is nullptr.", error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
if (tag.iov_len != rp->tag_length) {
maybe_copy_error_msg("Tag length is incorrect.", error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
return GRPC_STATUS_OK;
}
/* Increments crypter counter and checks overflow. */
static grpc_status_code increment_counter(alts_counter* counter,
char** error_details) {
if (counter == nullptr) {
return GRPC_STATUS_FAILED_PRECONDITION;
}
bool is_overflow = false;
grpc_status_code status =
alts_counter_increment(counter, &is_overflow, error_details);
if (status != GRPC_STATUS_OK) {
return status;
}
if (is_overflow) {
maybe_copy_error_msg("Crypter counter is overflowed.", error_details);
return GRPC_STATUS_INTERNAL;
}
return GRPC_STATUS_OK;
}
/* Given an array of iovec, computes the total length of buffer. */
static size_t get_total_length(const iovec_t* vec, size_t vec_length) {
size_t total_length = 0;
for (size_t i = 0; i < vec_length; ++i) {
total_length += vec[i].iov_len;
}
return total_length;
}
/* Writes frame header given data and tag length. */
static grpc_status_code write_frame_header(size_t data_length,
unsigned char* header,
char** error_details) {
if (header == nullptr) {
maybe_copy_error_msg("Header is nullptr.", error_details);
return GRPC_STATUS_FAILED_PRECONDITION;
}
size_t frame_length = kZeroCopyFrameMessageTypeFieldSize + data_length;
store_32_le(static_cast<uint32_t>(frame_length), header);
store_32_le(kZeroCopyFrameMessageType,
header + kZeroCopyFrameLengthFieldSize);
return GRPC_STATUS_OK;
}
/* Verifies frame header given protected data length. */
static grpc_status_code verify_frame_header(size_t data_length,
unsigned char* header,
char** error_details) {
if (header == nullptr) {
maybe_copy_error_msg("Header is nullptr.", error_details);
return GRPC_STATUS_FAILED_PRECONDITION;
}
size_t frame_length = load_32_le(header);
if (frame_length != kZeroCopyFrameMessageTypeFieldSize + data_length) {
maybe_copy_error_msg("Bad frame length.", error_details);
return GRPC_STATUS_INTERNAL;
}
size_t message_type = load_32_le(header + kZeroCopyFrameLengthFieldSize);
if (message_type != kZeroCopyFrameMessageType) {
maybe_copy_error_msg("Unsupported message type.", error_details);
return GRPC_STATUS_INTERNAL;
}
return GRPC_STATUS_OK;
}
/* --- alts_iovec_record_protocol methods implementation. --- */
size_t alts_iovec_record_protocol_get_header_length() {
return kZeroCopyFrameHeaderSize;
}
size_t alts_iovec_record_protocol_get_tag_length(
const alts_iovec_record_protocol* rp) {
if (rp != nullptr) {
return rp->tag_length;
}
return 0;
}
size_t alts_iovec_record_protocol_max_unprotected_data_size(
const alts_iovec_record_protocol* rp, size_t max_protected_frame_size) {
if (rp == nullptr) {
return 0;
}
size_t overhead_bytes_size =
kZeroCopyFrameMessageTypeFieldSize + rp->tag_length;
if (max_protected_frame_size <= overhead_bytes_size) return 0;
return max_protected_frame_size - overhead_bytes_size;
}
grpc_status_code alts_iovec_record_protocol_integrity_only_protect(
alts_iovec_record_protocol* rp, const iovec_t* unprotected_vec,
size_t unprotected_vec_length, iovec_t header, iovec_t tag,
char** error_details) {
/* Input sanity checks. */
if (rp == nullptr) {
maybe_copy_error_msg("Input iovec_record_protocol is nullptr.",
error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
if (!rp->is_integrity_only) {
maybe_copy_error_msg(
"Integrity-only operations are not allowed for this object.",
error_details);
return GRPC_STATUS_FAILED_PRECONDITION;
}
if (!rp->is_protect) {
maybe_copy_error_msg("Protect operations are not allowed for this object.",
error_details);
return GRPC_STATUS_FAILED_PRECONDITION;
}
grpc_status_code status =
ensure_header_and_tag_length(rp, header, tag, error_details);
if (status != GRPC_STATUS_OK) {
return status;
}
/* Unprotected data should not be zero length. */
size_t data_length =
get_total_length(unprotected_vec, unprotected_vec_length);
/* Sets frame header. */
status = write_frame_header(data_length + rp->tag_length,
static_cast<unsigned char*>(header.iov_base),
error_details);
if (status != GRPC_STATUS_OK) {
return status;
}
/* Computes frame tag by calling AEAD crypter. */
size_t bytes_written = 0;
status = gsec_aead_crypter_encrypt_iovec(
rp->crypter, alts_counter_get_counter(rp->ctr),
alts_counter_get_size(rp->ctr), unprotected_vec, unprotected_vec_length,
/* plaintext_vec = */ nullptr, /* plaintext_vec_length = */ 0, tag,
&bytes_written, error_details);
if (status != GRPC_STATUS_OK) {
return status;
}
if (bytes_written != rp->tag_length) {
maybe_copy_error_msg("Bytes written expects to be the same as tag length.",
error_details);
return GRPC_STATUS_INTERNAL;
}
/* Increments the crypter counter. */
return increment_counter(rp->ctr, error_details);
}
grpc_status_code alts_iovec_record_protocol_integrity_only_unprotect(
alts_iovec_record_protocol* rp, const iovec_t* protected_vec,
size_t protected_vec_length, iovec_t header, iovec_t tag,
char** error_details) {
/* Input sanity checks. */
if (rp == nullptr) {
maybe_copy_error_msg("Input iovec_record_protocol is nullptr.",
error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
if (!rp->is_integrity_only) {
maybe_copy_error_msg(
"Integrity-only operations are not allowed for this object.",
error_details);
return GRPC_STATUS_FAILED_PRECONDITION;
}
if (rp->is_protect) {
maybe_copy_error_msg(
"Unprotect operations are not allowed for this object.", error_details);
return GRPC_STATUS_FAILED_PRECONDITION;
}
grpc_status_code status =
ensure_header_and_tag_length(rp, header, tag, error_details);
if (status != GRPC_STATUS_OK) return status;
/* Protected data should not be zero length. */
size_t data_length = get_total_length(protected_vec, protected_vec_length);
/* Verifies frame header. */
status = verify_frame_header(data_length + rp->tag_length,
static_cast<unsigned char*>(header.iov_base),
error_details);
if (status != GRPC_STATUS_OK) {
return status;
}
/* Verifies frame tag by calling AEAD crypter. */
iovec_t plaintext = {nullptr, 0};
size_t bytes_written = 0;
status = gsec_aead_crypter_decrypt_iovec(
rp->crypter, alts_counter_get_counter(rp->ctr),
alts_counter_get_size(rp->ctr), protected_vec, protected_vec_length, &tag,
1, plaintext, &bytes_written, error_details);
if (status != GRPC_STATUS_OK || bytes_written != 0) {
maybe_append_error_msg(" Frame tag verification failed.", error_details);
return GRPC_STATUS_INTERNAL;
}
/* Increments the crypter counter. */
return increment_counter(rp->ctr, error_details);
}
grpc_status_code alts_iovec_record_protocol_privacy_integrity_protect(
alts_iovec_record_protocol* rp, const iovec_t* unprotected_vec,
size_t unprotected_vec_length, iovec_t protected_frame,
char** error_details) {
/* Input sanity checks. */
if (rp == nullptr) {
maybe_copy_error_msg("Input iovec_record_protocol is nullptr.",
error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
if (rp->is_integrity_only) {
maybe_copy_error_msg(
"Privacy-integrity operations are not allowed for this object.",
error_details);
return GRPC_STATUS_FAILED_PRECONDITION;
}
if (!rp->is_protect) {
maybe_copy_error_msg("Protect operations are not allowed for this object.",
error_details);
return GRPC_STATUS_FAILED_PRECONDITION;
}
/* Unprotected data should not be zero length. */
size_t data_length =
get_total_length(unprotected_vec, unprotected_vec_length);
/* Ensures protected frame iovec has sufficient size. */
if (protected_frame.iov_base == nullptr) {
maybe_copy_error_msg("Protected frame is nullptr.", error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
if (protected_frame.iov_len !=
alts_iovec_record_protocol_get_header_length() + data_length +
rp->tag_length) {
maybe_copy_error_msg("Protected frame size is incorrect.", error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
/* Writer frame header. */
grpc_status_code status = write_frame_header(
data_length + rp->tag_length,
static_cast<unsigned char*>(protected_frame.iov_base), error_details);
if (status != GRPC_STATUS_OK) {
return status;
}
/* Encrypt unprotected data by calling AEAD crypter. */
unsigned char* ciphertext_buffer =
static_cast<unsigned char*>(protected_frame.iov_base) +
alts_iovec_record_protocol_get_header_length();
iovec_t ciphertext = {ciphertext_buffer, data_length + rp->tag_length};
size_t bytes_written = 0;
status = gsec_aead_crypter_encrypt_iovec(
rp->crypter, alts_counter_get_counter(rp->ctr),
alts_counter_get_size(rp->ctr), /* aad_vec = */ nullptr,
/* aad_vec_length = */ 0, unprotected_vec, unprotected_vec_length,
ciphertext, &bytes_written, error_details);
if (status != GRPC_STATUS_OK) {
return status;
}
if (bytes_written != data_length + rp->tag_length) {
maybe_copy_error_msg(
"Bytes written expects to be data length plus tag length.",
error_details);
return GRPC_STATUS_INTERNAL;
}
/* Increments the crypter counter. */
return increment_counter(rp->ctr, error_details);
}
grpc_status_code alts_iovec_record_protocol_privacy_integrity_unprotect(
alts_iovec_record_protocol* rp, iovec_t header,
const iovec_t* protected_vec, size_t protected_vec_length,
iovec_t unprotected_data, char** error_details) {
/* Input sanity checks. */
if (rp == nullptr) {
maybe_copy_error_msg("Input iovec_record_protocol is nullptr.",
error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
if (rp->is_integrity_only) {
maybe_copy_error_msg(
"Privacy-integrity operations are not allowed for this object.",
error_details);
return GRPC_STATUS_FAILED_PRECONDITION;
}
if (rp->is_protect) {
maybe_copy_error_msg(
"Unprotect operations are not allowed for this object.", error_details);
return GRPC_STATUS_FAILED_PRECONDITION;
}
/* Protected data size should be no less than tag size. */
size_t protected_data_length =
get_total_length(protected_vec, protected_vec_length);
if (protected_data_length < rp->tag_length) {
maybe_copy_error_msg(
"Protected data length should be more than the tag length.",
error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
/* Ensures header has sufficient size. */
if (header.iov_base == nullptr) {
maybe_copy_error_msg("Header is nullptr.", error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
if (header.iov_len != alts_iovec_record_protocol_get_header_length()) {
maybe_copy_error_msg("Header length is incorrect.", error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
/* Ensures unprotected data iovec has sufficient size. */
if (unprotected_data.iov_len != protected_data_length - rp->tag_length) {
maybe_copy_error_msg("Unprotected data size is incorrect.", error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
/* Verify frame header. */
grpc_status_code status = verify_frame_header(
protected_data_length, static_cast<unsigned char*>(header.iov_base),
error_details);
if (status != GRPC_STATUS_OK) {
return status;
}
/* Decrypt protected data by calling AEAD crypter. */
size_t bytes_written = 0;
status = gsec_aead_crypter_decrypt_iovec(
rp->crypter, alts_counter_get_counter(rp->ctr),
alts_counter_get_size(rp->ctr), /* aad_vec = */ nullptr,
/* aad_vec_length = */ 0, protected_vec, protected_vec_length,
unprotected_data, &bytes_written, error_details);
if (status != GRPC_STATUS_OK) {
maybe_append_error_msg(" Frame decryption failed.", error_details);
return GRPC_STATUS_INTERNAL;
}
if (bytes_written != protected_data_length - rp->tag_length) {
maybe_copy_error_msg(
"Bytes written expects to be protected data length minus tag length.",
error_details);
return GRPC_STATUS_INTERNAL;
}
/* Increments the crypter counter. */
return increment_counter(rp->ctr, error_details);
}
grpc_status_code alts_iovec_record_protocol_create(
gsec_aead_crypter* crypter, size_t overflow_size, bool is_client,
bool is_integrity_only, bool is_protect, alts_iovec_record_protocol** rp,
char** error_details) {
if (crypter == nullptr || rp == nullptr) {
maybe_copy_error_msg(
"Invalid nullptr arguments to alts_iovec_record_protocol create.",
error_details);
return GRPC_STATUS_INVALID_ARGUMENT;
}
alts_iovec_record_protocol* impl = static_cast<alts_iovec_record_protocol*>(
gpr_zalloc(sizeof(alts_iovec_record_protocol)));
/* Gets counter length. */
size_t counter_length = 0;
grpc_status_code status =
gsec_aead_crypter_nonce_length(crypter, &counter_length, error_details);
if (status != GRPC_STATUS_OK) {
goto cleanup;
}
/* Creates counters. */
status =
alts_counter_create(is_protect ? !is_client : is_client, counter_length,
overflow_size, &impl->ctr, error_details);
if (status != GRPC_STATUS_OK) {
goto cleanup;
}
/* Gets tag length. */
status =
gsec_aead_crypter_tag_length(crypter, &impl->tag_length, error_details);
if (status != GRPC_STATUS_OK) {
goto cleanup;
}
impl->crypter = crypter;
impl->is_integrity_only = is_integrity_only;
impl->is_protect = is_protect;
*rp = impl;
return GRPC_STATUS_OK;
cleanup:
alts_counter_destroy(impl->ctr);
gpr_free(impl);
return GRPC_STATUS_FAILED_PRECONDITION;
}
void alts_iovec_record_protocol_destroy(alts_iovec_record_protocol* rp) {
if (rp != nullptr) {
alts_counter_destroy(rp->ctr);
gsec_aead_crypter_destroy(rp->crypter);
gpr_free(rp);
}
}

@ -0,0 +1,199 @@
/*
*
* Copyright 2018 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_CORE_TSI_ALTS_ZERO_COPY_FRAME_PROTECTOR_ALTS_IOVEC_RECORD_PROTOCOL_H
#define GRPC_CORE_TSI_ALTS_ZERO_COPY_FRAME_PROTECTOR_ALTS_IOVEC_RECORD_PROTOCOL_H
#include <grpc/support/port_platform.h>
#include <stdbool.h>
#include "src/core/tsi/alts/crypt/gsec.h"
constexpr size_t kZeroCopyFrameMessageType = 0x06;
constexpr size_t kZeroCopyFrameLengthFieldSize = 4;
constexpr size_t kZeroCopyFrameMessageTypeFieldSize = 4;
constexpr size_t kZeroCopyFrameHeaderSize =
kZeroCopyFrameLengthFieldSize + kZeroCopyFrameMessageTypeFieldSize;
// Limit k on number of frames such that at most 2^(8 * k) frames can be sent.
constexpr size_t kAltsRecordProtocolRekeyFrameLimit = 8;
constexpr size_t kAltsRecordProtocolFrameLimit = 5;
/* An implementation of alts record protocol. The API is thread-compatible. */
typedef struct iovec iovec_t;
typedef struct alts_iovec_record_protocol alts_iovec_record_protocol;
/**
* This method gets the length of record protocol frame header.
*/
size_t alts_iovec_record_protocol_get_header_length();
/**
* This method gets the length of record protocol frame tag.
*
* - rp: an alts_iovec_record_protocol instance.
*
* On success, the method returns the length of record protocol frame tag.
* Otherwise, it returns zero.
*/
size_t alts_iovec_record_protocol_get_tag_length(
const alts_iovec_record_protocol* rp);
/**
* This method returns maximum allowed unprotected data size, given maximum
* protected frame size.
*
* - rp: an alts_iovec_record_protocol instance.
* - max_protected_frame_size: maximum protected frame size.
*
* On success, the method returns the maximum allowed unprotected data size.
* Otherwise, it returns zero.
*/
size_t alts_iovec_record_protocol_max_unprotected_data_size(
const alts_iovec_record_protocol* rp, size_t max_protected_frame_size);
/**
* This method performs integrity-only protect operation on a
* alts_iovec_record_protocol instance, i.e., compute frame header and tag. The
* caller needs to allocate the memory for header and tag prior to calling this
* method.
*
* - rp: an alts_iovec_record_protocol instance.
* - unprotected_vec: an iovec array containing unprotected data.
* - unprotected_vec_length: the array length of unprotected_vec.
* - header: an iovec containing the output frame header.
* - tag: an iovec containing the output frame tag.
* - error_details: a buffer containing an error message if the method does not
* function correctly. It is OK to pass nullptr into error_details.
*
* On success, the method returns GRPC_STATUS_OK. Otherwise, it returns an
* error status code along with its details specified in error_details (if
* error_details is not nullptr).
*/
grpc_status_code alts_iovec_record_protocol_integrity_only_protect(
alts_iovec_record_protocol* rp, const iovec_t* unprotected_vec,
size_t unprotected_vec_length, iovec_t header, iovec_t tag,
char** error_details);
/**
* This method performs integrity-only unprotect operation on a
* alts_iovec_record_protocol instance, i.e., verify frame header and tag.
*
* - rp: an alts_iovec_record_protocol instance.
* - protected_vec: an iovec array containing protected data.
* - protected_vec_length: the array length of protected_vec.
* - header: an iovec containing the frame header.
* - tag: an iovec containing the frame tag.
* - error_details: a buffer containing an error message if the method does not
* function correctly. It is OK to pass nullptr into error_details.
*
* On success, the method returns GRPC_STATUS_OK. Otherwise, it returns an
* error status code along with its details specified in error_details (if
* error_details is not nullptr).
*/
grpc_status_code alts_iovec_record_protocol_integrity_only_unprotect(
alts_iovec_record_protocol* rp, const iovec_t* protected_vec,
size_t protected_vec_length, iovec_t header, iovec_t tag,
char** error_details);
/**
* This method performs privacy-integrity protect operation on a
* alts_iovec_record_protocol instance, i.e., compute a protected frame. The
* caller needs to allocate the memory for the protected frame prior to calling
* this method.
*
* - rp: an alts_iovec_record_protocol instance.
* - unprotected_vec: an iovec array containing unprotected data.
* - unprotected_vec_length: the array length of unprotected_vec.
* - protected_frame: an iovec containing the output protected frame.
* - error_details: a buffer containing an error message if the method does not
* function correctly. It is OK to pass nullptr into error_details.
*
* On success, the method returns GRPC_STATUS_OK. Otherwise, it returns an
* error status code along with its details specified in error_details (if
* error_details is not nullptr).
*/
grpc_status_code alts_iovec_record_protocol_privacy_integrity_protect(
alts_iovec_record_protocol* rp, const iovec_t* unprotected_vec,
size_t unprotected_vec_length, iovec_t protected_frame,
char** error_details);
/**
* This method performs privacy-integrity unprotect operation on a
* alts_iovec_record_protocol instance given a full protected frame, i.e.,
* compute the unprotected data. The caller needs to allocated the memory for
* the unprotected data prior to calling this method.
*
* - rp: an alts_iovec_record_protocol instance.
* - header: an iovec containing the frame header.
* - protected_vec: an iovec array containing protected data including the tag.
* - protected_vec_length: the array length of protected_vec.
* - unprotected_data: an iovec containing the output unprotected data.
* - error_details: a buffer containing an error message if the method does not
* function correctly. It is OK to pass nullptr into error_details.
*
* On success, the method returns GRPC_STATUS_OK. Otherwise, it returns an
* error status code along with its details specified in error_details (if
* error_details is not nullptr).
*/
grpc_status_code alts_iovec_record_protocol_privacy_integrity_unprotect(
alts_iovec_record_protocol* rp, iovec_t header,
const iovec_t* protected_vec, size_t protected_vec_length,
iovec_t unprotected_data, char** error_details);
/**
* This method creates an alts_iovec_record_protocol instance, given a
* gsec_aead_crypter instance, a flag indicating if the created instance will be
* used at the client or server side, and a flag indicating if the created
* instance will be used for integrity-only mode or privacy-integrity mode. The
* ownership of gsec_aead_crypter instance is transferred to this new object.
*
* - crypter: a gsec_aead_crypter instance used to perform AEAD decryption.
* - overflow_size: overflow size of counter in bytes.
* - is_client: a flag indicating if the alts_iovec_record_protocol instance
* will be used at the client or server side.
* - is_integrity_only: a flag indicating if the alts_iovec_record_protocol
* instance will be used for integrity-only or privacy-integrity mode.
* - is_protect: a flag indicating if the alts_grpc_record_protocol instance
* will be used for protect or unprotect.
* - rp: an alts_iovec_record_protocol instance to be returned from
* the method.
* - error_details: a buffer containing an error message if the method does not
* function correctly. It is OK to pass nullptr into error_details.
*
* On success, the method returns GRPC_STATUS_OK. Otherwise, it returns an
* error status code along with its details specified in error_details (if
* error_details is not nullptr).
*/
grpc_status_code alts_iovec_record_protocol_create(
gsec_aead_crypter* crypter, size_t overflow_size, bool is_client,
bool is_integrity_only, bool is_protect, alts_iovec_record_protocol** rp,
char** error_details);
/**
* This method destroys an alts_iovec_record_protocol instance by de-allocating
* all of its occupied memory. A gsec_aead_crypter instance passed in at
* gsec_alts_crypter instance creation time will be destroyed in this method.
*/
void alts_iovec_record_protocol_destroy(alts_iovec_record_protocol* rp);
#endif /* GRPC_CORE_TSI_ALTS_ZERO_COPY_FRAME_PROTECTOR_ALTS_IOVEC_RECORD_PROTOCOL_H \
*/

@ -0,0 +1,295 @@
/*
*
* Copyright 2018 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 <grpc/support/port_platform.h>
#include "src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.h"
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "src/core/lib/gpr/useful.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/tsi/alts/crypt/gsec.h"
#include "src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.h"
#include "src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.h"
#include "src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol.h"
#include "src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.h"
#include "src/core/tsi/transport_security_grpc.h"
constexpr size_t kMinFrameLength = 1024;
constexpr size_t kDefaultFrameLength = 16 * 1024;
constexpr size_t kMaxFrameLength = 1024 * 1024;
/**
* Main struct for alts_zero_copy_grpc_protector.
* We choose to have two alts_grpc_record_protocol objects and two sets of slice
* buffers: one for protect and the other for unprotect, so that protect and
* unprotect can be executed in parallel. Implementations of this object must be
* thread compatible.
*/
typedef struct alts_zero_copy_grpc_protector {
tsi_zero_copy_grpc_protector base;
alts_grpc_record_protocol* record_protocol;
alts_grpc_record_protocol* unrecord_protocol;
size_t max_protected_frame_size;
size_t max_unprotected_data_size;
grpc_slice_buffer unprotected_staging_sb;
grpc_slice_buffer protected_sb;
grpc_slice_buffer protected_staging_sb;
uint32_t parsed_frame_size;
} alts_zero_copy_grpc_protector;
/**
* Given a slice buffer, parses the first 4 bytes little-endian unsigned frame
* size and returns the total frame size including the frame field. Caller
* needs to make sure the input slice buffer has at least 4 bytes. Returns true
* on success and false on failure.
*/
static bool read_frame_size(const grpc_slice_buffer* sb,
uint32_t* total_frame_size) {
if (sb == nullptr || sb->length < kZeroCopyFrameLengthFieldSize) {
return false;
}
uint8_t frame_size_buffer[kZeroCopyFrameLengthFieldSize];
uint8_t* buf = frame_size_buffer;
/* Copies the first 4 bytes to a temporary buffer. */
size_t remaining = kZeroCopyFrameLengthFieldSize;
for (size_t i = 0; i < sb->count; i++) {
size_t slice_length = GRPC_SLICE_LENGTH(sb->slices[i]);
if (remaining <= slice_length) {
memcpy(buf, GRPC_SLICE_START_PTR(sb->slices[i]), remaining);
remaining = 0;
break;
} else {
memcpy(buf, GRPC_SLICE_START_PTR(sb->slices[i]), slice_length);
buf += slice_length;
remaining -= slice_length;
}
}
GPR_ASSERT(remaining == 0);
/* Gets little-endian frame size. */
uint32_t frame_size = (((uint32_t)frame_size_buffer[3]) << 24) |
(((uint32_t)frame_size_buffer[2]) << 16) |
(((uint32_t)frame_size_buffer[1]) << 8) |
((uint32_t)frame_size_buffer[0]);
if (frame_size > kMaxFrameLength) {
gpr_log(GPR_ERROR, "Frame size is larger than maximum frame size");
return false;
}
/* Returns frame size including frame length field. */
*total_frame_size =
static_cast<uint32_t>(frame_size + kZeroCopyFrameLengthFieldSize);
return true;
}
/**
* Creates an alts_grpc_record_protocol object, given key, key size, and flags
* to indicate whether the record_protocol object uses the rekeying AEAD,
* whether the object is for client or server, whether the object is for
* integrity-only or privacy-integrity mode, and whether the object is is used
* for protect or unprotect.
*/
static tsi_result create_alts_grpc_record_protocol(
const uint8_t* key, size_t key_size, bool is_rekey, bool is_client,
bool is_integrity_only, bool is_protect,
alts_grpc_record_protocol** record_protocol) {
if (key == nullptr || record_protocol == nullptr) {
return TSI_INVALID_ARGUMENT;
}
grpc_status_code status;
gsec_aead_crypter* crypter = nullptr;
char* error_details = nullptr;
status = gsec_aes_gcm_aead_crypter_create(key, key_size, kAesGcmNonceLength,
kAesGcmTagLength, is_rekey,
&crypter, &error_details);
if (status != GRPC_STATUS_OK) {
gpr_log(GPR_ERROR, "Failed to create AEAD crypter, %s", error_details);
gpr_free(error_details);
return TSI_INTERNAL_ERROR;
}
size_t overflow_limit = is_rekey ? kAltsRecordProtocolRekeyFrameLimit
: kAltsRecordProtocolFrameLimit;
/* Creates alts_grpc_record_protocol with AEAD crypter ownership transferred.
*/
tsi_result result =
is_integrity_only
? alts_grpc_integrity_only_record_protocol_create(
crypter, overflow_limit, is_client, is_protect, record_protocol)
: alts_grpc_privacy_integrity_record_protocol_create(
crypter, overflow_limit, is_client, is_protect,
record_protocol);
if (result != TSI_OK) {
gsec_aead_crypter_destroy(crypter);
return result;
}
return TSI_OK;
}
/* --- tsi_zero_copy_grpc_protector methods implementation. --- */
static tsi_result alts_zero_copy_grpc_protector_protect(
tsi_zero_copy_grpc_protector* self, grpc_slice_buffer* unprotected_slices,
grpc_slice_buffer* protected_slices) {
if (self == nullptr || unprotected_slices == nullptr ||
protected_slices == nullptr) {
gpr_log(GPR_ERROR, "Invalid nullptr arguments to zero-copy grpc protect.");
return TSI_INVALID_ARGUMENT;
}
alts_zero_copy_grpc_protector* protector =
reinterpret_cast<alts_zero_copy_grpc_protector*>(self);
/* Calls alts_grpc_record_protocol protect repeatly. */
while (unprotected_slices->length > protector->max_unprotected_data_size) {
grpc_slice_buffer_move_first(unprotected_slices,
protector->max_unprotected_data_size,
&protector->unprotected_staging_sb);
tsi_result status = alts_grpc_record_protocol_protect(
protector->record_protocol, &protector->unprotected_staging_sb,
protected_slices);
if (status != TSI_OK) {
return status;
}
}
return alts_grpc_record_protocol_protect(
protector->record_protocol, unprotected_slices, protected_slices);
}
static tsi_result alts_zero_copy_grpc_protector_unprotect(
tsi_zero_copy_grpc_protector* self, grpc_slice_buffer* protected_slices,
grpc_slice_buffer* unprotected_slices) {
if (self == nullptr || unprotected_slices == nullptr ||
protected_slices == nullptr) {
gpr_log(GPR_ERROR,
"Invalid nullptr arguments to zero-copy grpc unprotect.");
return TSI_INVALID_ARGUMENT;
}
alts_zero_copy_grpc_protector* protector =
reinterpret_cast<alts_zero_copy_grpc_protector*>(self);
grpc_slice_buffer_move_into(protected_slices, &protector->protected_sb);
/* Keep unprotecting each frame if possible. */
while (protector->protected_sb.length >= kZeroCopyFrameLengthFieldSize) {
if (protector->parsed_frame_size == 0) {
/* We have not parsed frame size yet. Parses frame size. */
if (!read_frame_size(&protector->protected_sb,
&protector->parsed_frame_size)) {
grpc_slice_buffer_reset_and_unref_internal(&protector->protected_sb);
return TSI_DATA_CORRUPTED;
}
}
if (protector->protected_sb.length < protector->parsed_frame_size) break;
/* At this point, protected_sb contains at least one frame of data. */
tsi_result status;
if (protector->protected_sb.length == protector->parsed_frame_size) {
status = alts_grpc_record_protocol_unprotect(protector->unrecord_protocol,
&protector->protected_sb,
unprotected_slices);
} else {
grpc_slice_buffer_move_first(&protector->protected_sb,
protector->parsed_frame_size,
&protector->protected_staging_sb);
status = alts_grpc_record_protocol_unprotect(
protector->unrecord_protocol, &protector->protected_staging_sb,
unprotected_slices);
}
protector->parsed_frame_size = 0;
if (status != TSI_OK) {
grpc_slice_buffer_reset_and_unref_internal(&protector->protected_sb);
return status;
}
}
return TSI_OK;
}
static void alts_zero_copy_grpc_protector_destroy(
tsi_zero_copy_grpc_protector* self) {
if (self == nullptr) {
return;
}
alts_zero_copy_grpc_protector* protector =
reinterpret_cast<alts_zero_copy_grpc_protector*>(self);
alts_grpc_record_protocol_destroy(protector->record_protocol);
alts_grpc_record_protocol_destroy(protector->unrecord_protocol);
grpc_slice_buffer_destroy_internal(&protector->unprotected_staging_sb);
grpc_slice_buffer_destroy_internal(&protector->protected_sb);
grpc_slice_buffer_destroy_internal(&protector->protected_staging_sb);
gpr_free(protector);
}
static const tsi_zero_copy_grpc_protector_vtable
alts_zero_copy_grpc_protector_vtable = {
alts_zero_copy_grpc_protector_protect,
alts_zero_copy_grpc_protector_unprotect,
alts_zero_copy_grpc_protector_destroy};
tsi_result alts_zero_copy_grpc_protector_create(
const uint8_t* key, size_t key_size, bool is_rekey, bool is_client,
bool is_integrity_only, size_t* max_protected_frame_size,
tsi_zero_copy_grpc_protector** protector) {
if (grpc_core::ExecCtx::Get() == nullptr || key == nullptr ||
protector == nullptr) {
gpr_log(
GPR_ERROR,
"Invalid nullptr arguments to alts_zero_copy_grpc_protector create.");
return TSI_INVALID_ARGUMENT;
}
/* Creates alts_zero_copy_protector. */
alts_zero_copy_grpc_protector* impl =
static_cast<alts_zero_copy_grpc_protector*>(
gpr_zalloc(sizeof(alts_zero_copy_grpc_protector)));
/* Creates alts_grpc_record_protocol objects. */
tsi_result status = create_alts_grpc_record_protocol(
key, key_size, is_rekey, is_client, is_integrity_only,
/*is_protect=*/true, &impl->record_protocol);
if (status == TSI_OK) {
status = create_alts_grpc_record_protocol(
key, key_size, is_rekey, is_client, is_integrity_only,
/*is_protect=*/false, &impl->unrecord_protocol);
if (status == TSI_OK) {
/* Sets maximum frame size. */
size_t max_protected_frame_size_to_set = kDefaultFrameLength;
if (max_protected_frame_size != nullptr) {
*max_protected_frame_size =
GPR_MIN(*max_protected_frame_size, kMaxFrameLength);
*max_protected_frame_size =
GPR_MAX(*max_protected_frame_size, kMinFrameLength);
max_protected_frame_size_to_set = *max_protected_frame_size;
}
impl->max_protected_frame_size = max_protected_frame_size_to_set;
impl->max_unprotected_data_size =
alts_grpc_record_protocol_max_unprotected_data_size(
impl->record_protocol, max_protected_frame_size_to_set);
GPR_ASSERT(impl->max_unprotected_data_size > 0);
/* Allocates internal slice buffers. */
grpc_slice_buffer_init(&impl->unprotected_staging_sb);
grpc_slice_buffer_init(&impl->protected_sb);
grpc_slice_buffer_init(&impl->protected_staging_sb);
impl->parsed_frame_size = 0;
impl->base.vtable = &alts_zero_copy_grpc_protector_vtable;
*protector = &impl->base;
return TSI_OK;
}
}
/* Cleanup if create failed. */
alts_grpc_record_protocol_destroy(impl->record_protocol);
alts_grpc_record_protocol_destroy(impl->unrecord_protocol);
gpr_free(impl);
return TSI_INTERNAL_ERROR;
}

@ -0,0 +1,52 @@
/*
*
* Copyright 2018 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_CORE_TSI_ALTS_ZERO_COPY_FRAME_PROTECTOR_ALTS_ZERO_COPY_GRPC_PROTECTOR_H
#define GRPC_CORE_TSI_ALTS_ZERO_COPY_FRAME_PROTECTOR_ALTS_ZERO_COPY_GRPC_PROTECTOR_H
#include <grpc/support/port_platform.h>
#include <stdbool.h>
#include "src/core/tsi/transport_security_grpc.h"
/**
* This method creates an ALTS zero-copy grpc protector.
*
* - key: a symmetric key used to seal/unseal frames.
* - key_size: the size of symmetric key.
* - is_rekey: use rekeying AEAD crypter.
* - is_client: a flag indicating if the protector will be used at client or
* server side.
* - is_integrity_only: a flag indicating if the protector instance will be
* used for integrity-only or privacy-integrity mode.
* - max_protected_frame_size: an in/out parameter indicating max frame size
* to be used by the protector. If it is nullptr, the default frame size will
* be used. Otherwise, the provided frame size will be adjusted (if not
* falling into a valid frame range) and used.
* - protector: a pointer to the zero-copy protector returned from the method.
*
* This method returns TSI_OK on success or a specific error code otherwise.
*/
tsi_result alts_zero_copy_grpc_protector_create(
const uint8_t* key, size_t key_size, bool is_rekey, bool is_client,
bool is_integrity_only, size_t* max_protected_frame_size,
tsi_zero_copy_grpc_protector** protector);
#endif /* GRPC_CORE_TSI_ALTS_ZERO_COPY_FRAME_PROTECTOR_ALTS_ZERO_COPY_GRPC_PROTECTOR_H \
*/

@ -220,6 +220,7 @@ CORE_SOURCE_FILES = [
'src/core/ext/filters/http/server/http_server_filter.cc',
'src/core/lib/http/httpcli_security_connector.cc',
'src/core/lib/security/context/security_context.cc',
'src/core/lib/security/credentials/alts/alts_credentials.cc',
'src/core/lib/security/credentials/composite/composite_credentials.cc',
'src/core/lib/security/credentials/credentials.cc',
'src/core/lib/security/credentials/credentials_metadata.cc',
@ -233,6 +234,7 @@ CORE_SOURCE_FILES = [
'src/core/lib/security/credentials/oauth2/oauth2_credentials.cc',
'src/core/lib/security/credentials/plugin/plugin_credentials.cc',
'src/core/lib/security/credentials/ssl/ssl_credentials.cc',
'src/core/lib/security/security_connector/alts_security_connector.cc',
'src/core/lib/security/security_connector/security_connector.cc',
'src/core/lib/security/transport/client_auth_filter.cc',
'src/core/lib/security/transport/secure_endpoint.cc',
@ -242,14 +244,45 @@ CORE_SOURCE_FILES = [
'src/core/lib/security/transport/tsi_error.cc',
'src/core/lib/security/util/json_util.cc',
'src/core/lib/surface/init_secure.cc',
'src/core/tsi/alts_transport_security.cc',
'src/core/tsi/fake_transport_security.cc',
'src/core/tsi/ssl_transport_security.cc',
'src/core/tsi/transport_security_grpc.cc',
'src/core/tsi/alts/crypt/aes_gcm.cc',
'src/core/tsi/alts/crypt/gsec.cc',
'src/core/tsi/alts/frame_protector/alts_counter.cc',
'src/core/tsi/alts/frame_protector/alts_crypter.cc',
'src/core/tsi/alts/frame_protector/alts_frame_protector.cc',
'src/core/tsi/alts/frame_protector/alts_record_protocol_crypter_common.cc',
'src/core/tsi/alts/frame_protector/alts_seal_privacy_integrity_crypter.cc',
'src/core/tsi/alts/frame_protector/alts_unseal_privacy_integrity_crypter.cc',
'src/core/tsi/alts/frame_protector/frame_handler.cc',
'src/core/tsi/alts/handshaker/alts_handshaker_client.cc',
'src/core/tsi/alts/handshaker/alts_tsi_event.cc',
'src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc',
'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.cc',
'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.cc',
'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.cc',
'src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.cc',
'src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.cc',
'src/core/lib/security/credentials/alts/check_gcp_environment.cc',
'src/core/lib/security/credentials/alts/check_gcp_environment_linux.cc',
'src/core/lib/security/credentials/alts/check_gcp_environment_no_op.cc',
'src/core/lib/security/credentials/alts/check_gcp_environment_windows.cc',
'src/core/lib/security/credentials/alts/grpc_alts_credentials_client_options.cc',
'src/core/lib/security/credentials/alts/grpc_alts_credentials_options.cc',
'src/core/lib/security/credentials/alts/grpc_alts_credentials_server_options.cc',
'src/core/tsi/alts/handshaker/alts_handshaker_service_api.cc',
'src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.cc',
'src/core/tsi/alts/handshaker/alts_tsi_utils.cc',
'src/core/tsi/alts/handshaker/transport_security_common_api.cc',
'src/core/tsi/alts/handshaker/altscontext.pb.c',
'src/core/tsi/alts/handshaker/handshaker.pb.c',
'src/core/tsi/alts/handshaker/transport_security_common.pb.c',
'third_party/nanopb/pb_common.c',
'third_party/nanopb/pb_decode.c',
'third_party/nanopb/pb_encode.c',
'src/core/tsi/transport_security.cc',
'src/core/tsi/transport_security_adapter.cc',
'src/core/ext/transport/chttp2/server/chttp2_server.cc',
'src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc',
'src/core/ext/transport/chttp2/client/insecure/channel_create.cc',
'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc',
'src/core/ext/transport/chttp2/client/chttp2_connector.cc',
'src/core/ext/filters/client_channel/backup_poller.cc',
'src/core/ext/filters/client_channel/channel_connectivity.cc',
'src/core/ext/filters/client_channel/client_channel.cc',
@ -273,11 +306,14 @@ CORE_SOURCE_FILES = [
'src/core/ext/filters/client_channel/subchannel_index.cc',
'src/core/ext/filters/client_channel/uri_parser.cc',
'src/core/ext/filters/deadline/deadline_filter.cc',
'src/core/ext/transport/chttp2/client/chttp2_connector.cc',
'src/core/tsi/alts_transport_security.cc',
'src/core/tsi/fake_transport_security.cc',
'src/core/tsi/ssl_transport_security.cc',
'src/core/tsi/transport_security_grpc.cc',
'src/core/ext/transport/chttp2/server/chttp2_server.cc',
'src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc',
'src/core/ext/transport/chttp2/server/insecure/server_chttp2.cc',
'src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.cc',
'src/core/ext/transport/chttp2/client/insecure/channel_create.cc',
'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc',
'src/core/ext/transport/inproc/inproc_plugin.cc',
'src/core/ext/transport/inproc/inproc_transport.cc',
'src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc',
@ -286,9 +322,6 @@ CORE_SOURCE_FILES = [
'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc',
'src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc',
'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c',
'third_party/nanopb/pb_common.c',
'third_party/nanopb/pb_decode.c',
'third_party/nanopb/pb_encode.c',
'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc',
'src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc',
'src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc',

@ -138,6 +138,8 @@
## Some libraries are shared even with BUILD_SHARED_LIBRARIES=OFF
set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
add_definitions(-DPB_FIELD_16BIT)
if (MSVC)
include(cmake/msvc_static_runtime.cmake)

@ -221,6 +221,8 @@
% endif
% endfor
DEFINES += PB_FIELD_16BIT
CPPFLAGS += $(CPPFLAGS_$(CONFIG))
CFLAGS += $(CFLAGS_$(CONFIG))
CXXFLAGS += $(CXXFLAGS_$(CONFIG))

@ -144,7 +144,7 @@
}
s.default_subspecs = 'Interface', 'Implementation'
s.compiler_flags = '-DGRPC_ARES=0'
s.compiler_flags = '-DGRPC_ARES=0', '-DPB_FIELD_16BIT'
s.libraries = 'c++'
# Like many other C libraries, gRPC-Core has its public headers under `include/<libname>/` and its

@ -60,11 +60,11 @@
% endfor
'cflags_c': [
'-Werror',
'-std=c99'
'-std=c99',
],
'cflags_cc': [
'-Werror',
'-std=c++11'
'-std=c++11',
],
'include_dirs': [
'.',
@ -127,7 +127,7 @@
% endfor
'-stdlib=libc++',
'-std=c++11',
'-Wno-error=deprecated-declarations'
'-Wno-error=deprecated-declarations',
],
% endif
},

@ -161,3 +161,52 @@ grpc_cc_binary(
"//test/core/util:grpc_test_util",
],
)
grpc_cc_test(
name = "check_gcp_environment_linux_test",
srcs = ["check_gcp_environment_linux_test.cc"],
language = "C++",
deps = [
"//:alts_util",
"//:gpr",
"//:gpr_base",
"//:grpc",
],
)
grpc_cc_test(
name = "check_gcp_environment_windows_test",
srcs = ["check_gcp_environment_windows_test.cc"],
language = "C++",
deps = [
"//:alts_util",
"//:gpr",
"//:gpr_base",
"//:grpc",
],
)
grpc_cc_test(
name = "grpc_alts_credentials_options_test",
srcs = ["grpc_alts_credentials_options_test.cc"],
language = "C++",
deps = [
"//:alts_util",
"//:gpr",
"//:grpc",
],
)
grpc_cc_test(
name = "alts_security_connector_test",
srcs = ["alts_security_connector_test.cc"],
language = "C++",
deps = [
"//:gpr",
"//:grpc",
"//:grpc_base_c",
"//:grpc_secure",
"//:tsi",
"//:tsi_interface",
],
)

@ -0,0 +1,166 @@
/*
*
* Copyright 2018 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/security_connector/alts_security_connector.h"
#include "src/core/lib/transport/transport.h"
#include "src/core/tsi/alts/handshaker/alts_tsi_handshaker.h"
#include "src/core/tsi/transport_security.h"
using grpc_core::internal::grpc_alts_auth_context_from_tsi_peer;
/* This file contains unit tests of grpc_alts_auth_context_from_tsi_peer(). */
static void test_invalid_input_failure() {
tsi_peer peer;
grpc_auth_context* ctx;
GPR_ASSERT(grpc_alts_auth_context_from_tsi_peer(nullptr, &ctx) ==
GRPC_SECURITY_ERROR);
GPR_ASSERT(grpc_alts_auth_context_from_tsi_peer(&peer, nullptr) ==
GRPC_SECURITY_ERROR);
}
static void test_empty_certificate_type_failure() {
tsi_peer peer;
grpc_auth_context* ctx = nullptr;
GPR_ASSERT(tsi_construct_peer(0, &peer) == TSI_OK);
GPR_ASSERT(grpc_alts_auth_context_from_tsi_peer(&peer, &ctx) ==
GRPC_SECURITY_ERROR);
GPR_ASSERT(ctx == nullptr);
tsi_peer_destruct(&peer);
}
static void test_empty_peer_property_failure() {
tsi_peer peer;
grpc_auth_context* ctx;
GPR_ASSERT(tsi_construct_peer(1, &peer) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_ALTS_CERTIFICATE_TYPE,
&peer.properties[0]) == TSI_OK);
GPR_ASSERT(grpc_alts_auth_context_from_tsi_peer(&peer, &ctx) ==
GRPC_SECURITY_ERROR);
GPR_ASSERT(ctx == nullptr);
tsi_peer_destruct(&peer);
}
static void test_missing_rpc_protocol_versions_property_failure() {
tsi_peer peer;
grpc_auth_context* ctx;
GPR_ASSERT(tsi_construct_peer(kTsiAltsNumOfPeerProperties, &peer) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_ALTS_CERTIFICATE_TYPE,
&peer.properties[0]) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_ALTS_SERVICE_ACCOUNT_PEER_PROPERTY, "alice",
&peer.properties[1]) == TSI_OK);
GPR_ASSERT(grpc_alts_auth_context_from_tsi_peer(&peer, &ctx) ==
GRPC_SECURITY_ERROR);
GPR_ASSERT(ctx == nullptr);
tsi_peer_destruct(&peer);
}
static void test_unknown_peer_property_failure() {
tsi_peer peer;
grpc_auth_context* ctx;
GPR_ASSERT(tsi_construct_peer(kTsiAltsNumOfPeerProperties, &peer) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_ALTS_CERTIFICATE_TYPE,
&peer.properties[0]) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
"unknown", "alice", &peer.properties[1]) == TSI_OK);
GPR_ASSERT(grpc_alts_auth_context_from_tsi_peer(&peer, &ctx) ==
GRPC_SECURITY_ERROR);
GPR_ASSERT(ctx == nullptr);
tsi_peer_destruct(&peer);
}
static bool test_identity(const grpc_auth_context* ctx,
const char* expected_property_name,
const char* expected_identity) {
grpc_auth_property_iterator it;
const grpc_auth_property* prop;
GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx));
it = grpc_auth_context_peer_identity(ctx);
prop = grpc_auth_property_iterator_next(&it);
GPR_ASSERT(prop != nullptr);
if (strcmp(prop->name, expected_property_name) != 0) {
gpr_log(GPR_ERROR, "Expected peer identity property name %s and got %s.",
expected_property_name, prop->name);
return false;
}
if (strncmp(prop->value, expected_identity, prop->value_length) != 0) {
gpr_log(GPR_ERROR, "Expected peer identity %s and got got %s.",
expected_identity, prop->value);
return false;
}
return true;
}
static void test_alts_peer_to_auth_context_success() {
tsi_peer peer;
grpc_auth_context* ctx;
GPR_ASSERT(tsi_construct_peer(kTsiAltsNumOfPeerProperties, &peer) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_ALTS_CERTIFICATE_TYPE,
&peer.properties[0]) == TSI_OK);
GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
TSI_ALTS_SERVICE_ACCOUNT_PEER_PROPERTY, "alice",
&peer.properties[1]) == TSI_OK);
grpc_gcp_rpc_protocol_versions peer_versions;
grpc_gcp_rpc_protocol_versions_set_max(&peer_versions,
GRPC_PROTOCOL_VERSION_MAX_MAJOR,
GRPC_PROTOCOL_VERSION_MAX_MINOR);
grpc_gcp_rpc_protocol_versions_set_min(&peer_versions,
GRPC_PROTOCOL_VERSION_MIN_MAJOR,
GRPC_PROTOCOL_VERSION_MIN_MINOR);
grpc_slice serialized_peer_versions;
GPR_ASSERT(grpc_gcp_rpc_protocol_versions_encode(&peer_versions,
&serialized_peer_versions));
GPR_ASSERT(tsi_construct_string_peer_property(
TSI_ALTS_RPC_VERSIONS,
reinterpret_cast<char*>(
GRPC_SLICE_START_PTR(serialized_peer_versions)),
GRPC_SLICE_LENGTH(serialized_peer_versions),
&peer.properties[2]) == TSI_OK);
GPR_ASSERT(grpc_alts_auth_context_from_tsi_peer(&peer, &ctx) ==
GRPC_SECURITY_OK);
GPR_ASSERT(
test_identity(ctx, TSI_ALTS_SERVICE_ACCOUNT_PEER_PROPERTY, "alice"));
GRPC_AUTH_CONTEXT_UNREF(ctx, "test");
grpc_slice_unref(serialized_peer_versions);
tsi_peer_destruct(&peer);
}
int main(int argc, char** argv) {
/* Test. */
test_invalid_input_failure();
test_empty_certificate_type_failure();
test_empty_peer_property_failure();
test_unknown_peer_property_failure();
test_missing_rpc_protocol_versions_property_failure();
test_alts_peer_to_auth_context_success();
return 0;
}

@ -0,0 +1,83 @@
/*
*
* Copyright 2018 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 "src/core/lib/security/credentials/alts/check_gcp_environment.h"
#if GPR_LINUX
#include <stdio.h>
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "src/core/lib/gpr/tmpfile.h"
static bool check_bios_data_linux_test(const char* data) {
/* Create a file with contents data. */
char* filename = nullptr;
FILE* fp = gpr_tmpfile("check_gcp_environment_test", &filename);
GPR_ASSERT(filename != nullptr);
GPR_ASSERT(fp != nullptr);
GPR_ASSERT(fwrite(data, 1, strlen(data), fp) == strlen(data));
fclose(fp);
bool result = grpc_core::internal::check_bios_data(
reinterpret_cast<const char*>(filename));
/* Cleanup. */
remove(filename);
gpr_free(filename);
return result;
}
static void test_gcp_environment_check_success() {
/* Exact match. */
GPR_ASSERT(check_bios_data_linux_test("Google"));
GPR_ASSERT(check_bios_data_linux_test("Google Compute Engine"));
/* With leading and trailing whitespaces. */
GPR_ASSERT(check_bios_data_linux_test(" Google "));
GPR_ASSERT(check_bios_data_linux_test("Google "));
GPR_ASSERT(check_bios_data_linux_test(" Google"));
GPR_ASSERT(check_bios_data_linux_test(" Google Compute Engine "));
GPR_ASSERT(check_bios_data_linux_test("Google Compute Engine "));
GPR_ASSERT(check_bios_data_linux_test(" Google Compute Engine"));
/* With leading and trailing \t and \n. */
GPR_ASSERT(check_bios_data_linux_test("\t\tGoogle Compute Engine\t"));
GPR_ASSERT(check_bios_data_linux_test("Google Compute Engine\n"));
GPR_ASSERT(check_bios_data_linux_test("\n\n\tGoogle Compute Engine \n\t\t"));
}
static void test_gcp_environment_check_failure() {
GPR_ASSERT(!check_bios_data_linux_test("non_existing-file"));
GPR_ASSERT(!check_bios_data_linux_test("Google-Chrome"));
GPR_ASSERT(!check_bios_data_linux_test("Amazon"));
GPR_ASSERT(!check_bios_data_linux_test("Google-Chrome\t\t"));
GPR_ASSERT(!check_bios_data_linux_test("Amazon"));
}
int main(int argc, char** argv) {
/* Tests. */
test_gcp_environment_check_success();
test_gcp_environment_check_failure();
return 0;
}
#else // GPR_LINUX
int main(int argc, char** argv) { return 0; }
#endif // GPR_LINUX

@ -0,0 +1,71 @@
/*
*
* Copyright 2018 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 "src/core/lib/security/credentials/alts/check_gcp_environment.h"
#ifdef GPR_WINDOWS
#include <stdio.h>
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "src/core/lib/gpr/tmpfile.h"
static bool check_bios_data_windows_test(const char* data) {
/* Create a file with contents data. */
char* filename = nullptr;
FILE* fp = gpr_tmpfile("check_gcp_environment_test", &filename);
GPR_ASSERT(filename != nullptr);
GPR_ASSERT(fp != nullptr);
GPR_ASSERT(fwrite(data, 1, strlen(data), fp) == strlen(data));
fclose(fp);
bool result = grpc_core::internal::check_bios_data(
reinterpret_cast<const char*>(filename));
/* Cleanup. */
remove(filename);
gpr_free(filename);
return result;
}
static void test_gcp_environment_check_success() {
GPR_ASSERT(check_bios_data_windows_test("Google"));
GPR_ASSERT(check_bios_data_windows_test("Google\n"));
GPR_ASSERT(check_bios_data_windows_test("Google\r"));
GPR_ASSERT(check_bios_data_windows_test("Google\r\n"));
GPR_ASSERT(check_bios_data_windows_test(" Google \r\n"));
GPR_ASSERT(check_bios_data_windows_test(" \t\t Google\r\n"));
GPR_ASSERT(check_bios_data_windows_test(" \t\t Google\t\t \r\n"));
}
static void test_gcp_environment_check_failure() {
GPR_ASSERT(!check_bios_data_windows_test("\t\tAmazon\n"));
GPR_ASSERT(!check_bios_data_windows_test(" Amazon\r\n"));
}
int main(int argc, char** argv) {
/* Tests. */
test_gcp_environment_check_success();
test_gcp_environment_check_failure();
return 0;
}
#else // GPR_WINDOWS
int main(int argc, char** argv) { return 0; }
#endif // GPR_WINDOWS

@ -0,0 +1,118 @@
/*
*
* Copyright 2018 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/log.h>
#include "src/core/lib/security/credentials/alts/grpc_alts_credentials_options.h"
#define ALTS_CLIENT_OPTIONS_TEST_TARGET_SERVICE_ACCOUNT_1 "abc@google.com"
#define ALTS_CLIENT_OPTIONS_TEST_TARGET_SERVICE_ACCOUNT_2 "def@google.com"
const size_t kTargetServiceAccountNum = 2;
static void test_add_target_service_account_failure() {
/* Initialization. */
grpc_alts_credentials_options* options =
grpc_alts_credentials_client_options_create();
auto client_options =
reinterpret_cast<grpc_alts_credentials_client_options*>(options);
/* Test. */
GPR_ASSERT(!grpc_alts_credentials_client_options_add_target_service_account(
client_options, nullptr));
GPR_ASSERT(!grpc_alts_credentials_client_options_add_target_service_account(
nullptr, ALTS_CLIENT_OPTIONS_TEST_TARGET_SERVICE_ACCOUNT_1));
/* Cleanup. */
grpc_alts_credentials_options_destroy(options);
}
static void test_copy_client_options_failure() {
/* Initialization. */
grpc_alts_credentials_options* options =
grpc_alts_credentials_client_options_create();
/* Test. */
GPR_ASSERT(grpc_alts_credentials_options_copy(nullptr) == nullptr);
/* Cleanup. */
grpc_alts_credentials_options_destroy(options);
}
static size_t get_target_service_account_num(
grpc_alts_credentials_client_options* options) {
size_t num = 0;
target_service_account* node = options->target_account_list_head;
while (node != nullptr) {
num++;
node = node->next;
}
return num;
}
static void test_client_options_api_success() {
/* Initialization. */
grpc_alts_credentials_options* options =
grpc_alts_credentials_client_options_create();
auto client_options =
reinterpret_cast<grpc_alts_credentials_client_options*>(options);
/* Set client options fields. */
grpc_alts_credentials_client_options_add_target_service_account(
client_options, ALTS_CLIENT_OPTIONS_TEST_TARGET_SERVICE_ACCOUNT_1);
grpc_alts_credentials_client_options_add_target_service_account(
client_options, ALTS_CLIENT_OPTIONS_TEST_TARGET_SERVICE_ACCOUNT_2);
/* Validate client option fields. */
GPR_ASSERT(get_target_service_account_num(client_options) ==
kTargetServiceAccountNum);
GPR_ASSERT(strcmp(client_options->target_account_list_head->data,
ALTS_CLIENT_OPTIONS_TEST_TARGET_SERVICE_ACCOUNT_2) == 0);
GPR_ASSERT(strcmp(client_options->target_account_list_head->next->data,
ALTS_CLIENT_OPTIONS_TEST_TARGET_SERVICE_ACCOUNT_1) == 0);
/* Perform a copy operation and validate its correctness. */
grpc_alts_credentials_options* new_options =
grpc_alts_credentials_options_copy(options);
auto new_client_options =
reinterpret_cast<grpc_alts_credentials_client_options*>(new_options);
GPR_ASSERT(get_target_service_account_num(new_client_options) ==
kTargetServiceAccountNum);
GPR_ASSERT(strcmp(new_client_options->target_account_list_head->data,
ALTS_CLIENT_OPTIONS_TEST_TARGET_SERVICE_ACCOUNT_2) == 0);
GPR_ASSERT(strcmp(new_client_options->target_account_list_head->next->data,
ALTS_CLIENT_OPTIONS_TEST_TARGET_SERVICE_ACCOUNT_1) == 0);
/* Cleanup.*/
grpc_alts_credentials_options_destroy(options);
grpc_alts_credentials_options_destroy(new_options);
}
int main(int argc, char** argv) {
/* Test. */
test_add_target_service_account_failure();
test_copy_client_options_failure();
test_client_options_api_success();
return 0;
}

@ -16,7 +16,7 @@ load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_c
licenses(["notice"]) # Apache v2
grpc_package(name = "test/core/tsi")
grpc_package(name = "test/core/tsi", visibility = "public")
grpc_cc_library(
name = "transport_security_test_lib",

@ -0,0 +1,42 @@
# Copyright 2018 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.
#
load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_package")
licenses(["notice"]) # Apache v2
grpc_package(name = "crypt", visibility = "public")
grpc_cc_test(
name = "alts_crypt_test",
srcs = ["aes_gcm_test.cc"],
language = "C++",
deps = [
":alts_crypt_test_util",
"//:alts_frame_protector",
"//:gpr",
"//:grpc",
],
)
grpc_cc_library(
name = "alts_crypt_test_util",
srcs = ["gsec_test_util.cc"],
hdrs = ["gsec_test_util.h"],
deps = [
"//:gpr",
"//:grpc",
],
)

File diff suppressed because it is too large Load Diff

@ -0,0 +1,89 @@
/*
*
* Copyright 2018 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 "test/core/tsi/alts/crypt/gsec_test_util.h"
#include <time.h>
#include <grpc/support/alloc.h>
void gsec_test_random_bytes(uint8_t* bytes, size_t length) {
srand(time(nullptr));
size_t ind;
for (ind = 0; ind < length; ind++) {
bytes[ind] = static_cast<uint8_t>(rand() % 255 + 1);
}
}
void gsec_test_random_array(uint8_t** bytes, size_t length) {
if (bytes != nullptr) {
*bytes = static_cast<uint8_t*>(gpr_malloc(length));
gsec_test_random_bytes(*bytes, length);
} else {
fprintf(stderr, "bytes buffer is nullptr in gsec_test_random_array().");
abort();
}
}
uint32_t gsec_test_bias_random_uint32(uint32_t max_length) {
uint32_t value;
gsec_test_random_bytes((uint8_t*)(&value), sizeof(value));
return value % max_length;
}
void gsec_test_copy(const uint8_t* src, uint8_t** des, size_t source_len) {
if (src != nullptr && des != nullptr) {
*des = static_cast<uint8_t*>(gpr_malloc(source_len));
memcpy(*des, src, source_len);
} else {
fprintf(stderr, "Either src or des buffer is nullptr in gsec_test_copy().");
abort();
}
}
void gsec_test_copy_and_alter_random_byte(const uint8_t* src, uint8_t** des,
size_t source_len) {
if (src != nullptr && des != nullptr) {
*des = static_cast<uint8_t*>(gpr_malloc(source_len));
memcpy(*des, src, source_len);
uint32_t offset;
offset = gsec_test_bias_random_uint32(static_cast<uint32_t>(source_len));
(*(*des + offset))++;
} else {
fprintf(stderr,
"Either src or des is nullptr in "
"gsec_test_copy_and_alter_random_byte().");
abort();
}
}
int gsec_test_expect_compare_code_and_substr(grpc_status_code status1,
grpc_status_code status2,
const char* msg1,
const char* msg2) {
int failure = 1;
if (status1 != status2) {
fprintf(stderr, "Status %d does not equal %d.\n", status1, status2);
failure = 0;
}
if (strstr(msg1, msg2) == nullptr) {
fprintf(stderr, "Status message <%s> does not contain <%s>.\n", msg1, msg2);
failure = 0;
}
return failure;
}

@ -0,0 +1,89 @@
/*
*
* Copyright 2018 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_ALTS_CRYPT_GSEC_TEST_UTIL_H_
#define GRPC_TEST_CORE_TSI_ALTS_CRYPT_GSEC_TEST_UTIL_H_
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <grpc/grpc.h>
/**
* This method returns random bytes of certain length.
*
* - bytes: buffer to hold random bytes.
* - length: length of buffer to be populated.
*/
void gsec_test_random_bytes(uint8_t* bytes, size_t length);
/**
* This method returns an array of random bytes.
*
* - bytes: array to hold random bytes.
* - length: length of array to be populated.
*/
void gsec_test_random_array(uint8_t** bytes, size_t length);
/**
* This method returns a uint32 that's not quite uniformly random, but good
* enough for tests.
*
* - max_length: a max value the returned random number can choose.
*/
uint32_t gsec_test_bias_random_uint32(uint32_t max_length);
/**
* This method copies data from a source to a destination buffer.
*
* - src: a source buffer.
* - des: a destination buffer.
* - length: the length of source buffer to be copied from its beginning.
*/
void gsec_test_copy(const uint8_t* src, uint8_t** des, size_t length);
/**
* This method copies data from a source to a destination buffer, and flips one
* byte in the destination buffer randomly.
*
* - src: a source buffer.
* - des: a destination buffer.
* - length: the length of source buffer to be copied from its beginning.
*/
void gsec_test_copy_and_alter_random_byte(const uint8_t* src, uint8_t** des,
size_t source_len);
/**
* This method compares two grpc_status_code values, and verifies if one string
* is a substring of the other.
*
* - status1: the first grpc_status_code to be compared.
* - status2: the second grpc_status_code to be compared.
* - msg1: a string to be scanned.
* - msg2: a small string to be searched within msg1.
*
* If both checks succeed, the method returns 1 and otherwise, it returns 0.
*/
int gsec_test_expect_compare_code_and_substr(grpc_status_code status1,
grpc_status_code status2,
const char* msg1,
const char* msg2);
#endif // GRPC_TEST_CORE_TSI_ALTS_CRYPT_GSEC_TEST_UTIL_H_ */

@ -0,0 +1,71 @@
# Copyright 2018 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.
load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_package")
licenses(["notice"]) # Apache v2
grpc_package(name = "frame_protector")
grpc_cc_test(
name = "alts_counter_test",
srcs = ["alts_counter_test.cc"],
language = "C++",
deps = [
"//:alts_frame_protector",
"//:gpr",
"//:grpc",
"//test/core/tsi/alts/crypt:alts_crypt_test_util",
],
)
grpc_cc_test(
name = "alts_crypter_test",
srcs = ["alts_crypter_test.cc"],
language = "C++",
deps = [
"//:alts_frame_protector",
"//:gpr",
"//:grpc",
"//test/core/tsi/alts/crypt:alts_crypt_test_util",
],
)
grpc_cc_test(
name = "alts_frame_protector_test",
srcs = ["alts_frame_protector_test.cc"],
language = "C++",
deps = [
"//:alts_frame_protector",
"//:gpr",
"//:grpc",
"//:tsi",
"//:tsi_interface",
"//test/core/tsi/alts/crypt:alts_crypt_test_util",
"//test/core/tsi:transport_security_test_lib",
],
)
grpc_cc_test(
name = "frame_handler_test",
srcs = ["frame_handler_test.cc"],
language = "C++",
deps = [
"//:alts_frame_protector",
"//:gpr",
"//:gpr_base",
"//:grpc",
"//test/core/tsi/alts/crypt:alts_crypt_test_util",
],
)

@ -0,0 +1,180 @@
/*
*
* Copyright 2018 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 <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "src/core/tsi/alts/frame_protector/alts_counter.h"
#include "test/core/tsi/alts/crypt/gsec_test_util.h"
const size_t kSmallCounterSize = 4;
const size_t kSmallOverflowSize = 1;
const size_t kGcmCounterSize = 12;
const size_t kGcmOverflowSize = 5;
static bool do_bytes_represent_client(alts_counter* ctr, unsigned char* counter,
size_t size) {
return (ctr->counter[size - 1] & 0x80) == 0x80;
}
static void alts_counter_test_input_sanity_check(size_t counter_size,
size_t overflow_size) {
alts_counter* ctr = nullptr;
char* error_details = nullptr;
/* Input sanity check on alts_counter_create(). */
/* Invalid counter size. */
grpc_status_code status =
alts_counter_create(true, 0, overflow_size, &ctr, &error_details);
GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
status, GRPC_STATUS_INVALID_ARGUMENT, error_details,
"counter_size is invalid."));
gpr_free(error_details);
/* Invalid overflow size. */
status = alts_counter_create(true, counter_size, 0, &ctr, &error_details);
GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
status, GRPC_STATUS_INVALID_ARGUMENT, error_details,
"overflow_size is invalid."));
gpr_free(error_details);
/* alts_counter is nullptr. */
status = alts_counter_create(true, counter_size, overflow_size, nullptr,
&error_details);
GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
status, GRPC_STATUS_INVALID_ARGUMENT, error_details,
"crypter_counter is nullptr."));
gpr_free(error_details);
status = alts_counter_create(true, counter_size, overflow_size, &ctr,
&error_details);
GPR_ASSERT(status == GRPC_STATUS_OK);
/* Input sanity check on alts_counter_increment(). */
/* crypter_counter is nullptr. */
bool is_overflow = false;
status = alts_counter_increment(nullptr, &is_overflow, &error_details);
GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
status, GRPC_STATUS_INVALID_ARGUMENT, error_details,
"crypter_counter is nullptr."));
gpr_free(error_details);
/* is_overflow is nullptr. */
status = alts_counter_increment(ctr, nullptr, &error_details);
GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
status, GRPC_STATUS_INVALID_ARGUMENT, error_details,
"is_overflow is nullptr."));
gpr_free(error_details);
alts_counter_destroy(ctr);
}
static void alts_counter_test_overflow_full_range(bool is_client,
size_t counter_size,
size_t overflow_size) {
alts_counter* ctr = nullptr;
char* error_details = nullptr;
grpc_status_code status = alts_counter_create(
is_client, counter_size, overflow_size, &ctr, &error_details);
GPR_ASSERT(status == GRPC_STATUS_OK);
unsigned char* expected =
static_cast<unsigned char*>(gpr_zalloc(counter_size));
if (is_client) {
expected[counter_size - 1] = 0x80;
}
/* Do a single iteration to ensure the counter is initialized as expected. */
GPR_ASSERT(do_bytes_represent_client(ctr, alts_counter_get_counter(ctr),
counter_size) == is_client);
GPR_ASSERT(memcmp(alts_counter_get_counter(ctr), expected, counter_size) ==
0);
bool is_overflow = false;
GPR_ASSERT(alts_counter_increment(ctr, &is_overflow, &error_details) ==
GRPC_STATUS_OK);
GPR_ASSERT(!is_overflow);
/**
* The counter can return 2^{overflow_size * 8} counters. The
* high-order bit is fixed to the client/server. The last call will yield a
* useable counter, but overflow the counter object.
*/
int iterations = 1 << (overflow_size * 8);
int ind = 1;
for (ind = 1; ind < iterations - 1; ind++) {
GPR_ASSERT(do_bytes_represent_client(ctr, alts_counter_get_counter(ctr),
counter_size) == is_client);
GPR_ASSERT(alts_counter_increment(ctr, &is_overflow, &error_details) ==
GRPC_STATUS_OK);
GPR_ASSERT(!is_overflow);
}
GPR_ASSERT(do_bytes_represent_client(ctr, alts_counter_get_counter(ctr),
counter_size) == is_client);
GPR_ASSERT(alts_counter_increment(ctr, &is_overflow, &error_details) ==
GRPC_STATUS_FAILED_PRECONDITION);
GPR_ASSERT(is_overflow);
gpr_free(expected);
alts_counter_destroy(ctr);
}
/* Set the counter manually and make sure it overflows as expected. */
static void alts_counter_test_overflow_single_increment(bool is_client,
size_t counter_size,
size_t overflow_size) {
alts_counter* ctr = nullptr;
char* error_details = nullptr;
grpc_status_code status = alts_counter_create(
is_client, counter_size, overflow_size, &ctr, &error_details);
GPR_ASSERT(status == GRPC_STATUS_OK);
unsigned char* expected =
static_cast<unsigned char*>(gpr_zalloc(counter_size));
memset(expected, 0xFF, overflow_size);
expected[0] = 0xFE;
if (is_client) {
expected[counter_size - 1] = 0x80;
}
memcpy(ctr->counter, expected, counter_size);
GPR_ASSERT(do_bytes_represent_client(ctr, alts_counter_get_counter(ctr),
counter_size) == is_client);
GPR_ASSERT(memcmp(expected, alts_counter_get_counter(ctr), counter_size) ==
0);
bool is_overflow = false;
GPR_ASSERT(alts_counter_increment(ctr, &is_overflow, &error_details) ==
GRPC_STATUS_OK);
GPR_ASSERT(!is_overflow);
GPR_ASSERT(do_bytes_represent_client(ctr, alts_counter_get_counter(ctr),
counter_size) == is_client);
expected[0] = static_cast<unsigned char>(expected[0] + 1);
GPR_ASSERT(memcmp(expected, alts_counter_get_counter(ctr), counter_size) ==
0);
GPR_ASSERT(alts_counter_increment(ctr, &is_overflow, &error_details) ==
GRPC_STATUS_FAILED_PRECONDITION);
GPR_ASSERT(is_overflow);
gpr_free(expected);
alts_counter_destroy(ctr);
}
int main(int argc, char** argv) {
alts_counter_test_input_sanity_check(kGcmCounterSize, kGcmOverflowSize);
alts_counter_test_overflow_full_range(true, kSmallCounterSize,
kSmallOverflowSize);
alts_counter_test_overflow_full_range(false, kSmallCounterSize,
kSmallOverflowSize);
alts_counter_test_overflow_single_increment(true, kGcmCounterSize,
kGcmOverflowSize);
alts_counter_test_overflow_single_increment(false, kGcmCounterSize,
kGcmOverflowSize);
return 0;
}

@ -0,0 +1,493 @@
/*
*
* Copyright 2018 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/support/alloc.h>
#include <grpc/support/log.h>
#include "src/core/tsi/alts/frame_protector/alts_crypter.h"
#include "test/core/tsi/alts/crypt/gsec_test_util.h"
static void alts_crypter_test_random_seal_unseal(alts_crypter* server_seal,
alts_crypter* server_unseal,
alts_crypter* client_seal,
alts_crypter* client_unseal) {
size_t data_size = gsec_test_bias_random_uint32(1024) + 1;
size_t num_overhead_bytes = alts_crypter_num_overhead_bytes(server_seal);
size_t protected_data_size = data_size + num_overhead_bytes;
uint8_t* data_buffer = static_cast<uint8_t*>(gpr_malloc(protected_data_size));
gsec_test_random_bytes(data_buffer, data_size);
uint8_t* duplicate_buffer = nullptr;
gsec_test_copy(data_buffer, &duplicate_buffer, data_size);
/* Client seal and server unseal */
size_t size = data_size;
grpc_status_code status = alts_crypter_process_in_place(
client_seal, data_buffer, protected_data_size, size, &size, nullptr);
GPR_ASSERT(status == GRPC_STATUS_OK);
GPR_ASSERT(size == protected_data_size);
status = alts_crypter_process_in_place(
server_unseal, data_buffer, protected_data_size, size, &size, nullptr);
GPR_ASSERT(status == GRPC_STATUS_OK);
GPR_ASSERT(memcmp(data_buffer, duplicate_buffer, data_size) == 0);
GPR_ASSERT(size == data_size);
/* Server seal and client unseal */
status = alts_crypter_process_in_place(
server_seal, data_buffer, protected_data_size, size, &size, nullptr);
GPR_ASSERT(status == GRPC_STATUS_OK);
GPR_ASSERT(size == protected_data_size);
status = alts_crypter_process_in_place(
client_unseal, data_buffer, protected_data_size, size, &size, nullptr);
GPR_ASSERT(status == GRPC_STATUS_OK);
GPR_ASSERT(memcmp(data_buffer, duplicate_buffer, data_size) == 0);
GPR_ASSERT(size == data_size);
gpr_free(data_buffer);
gpr_free(duplicate_buffer);
}
static void alts_crypter_test_multiple_random_seal_unseal(
alts_crypter* server_seal, alts_crypter* server_unseal,
alts_crypter* client_seal, alts_crypter* client_unseal) {
size_t data_size = gsec_test_bias_random_uint32(1024) + 1;
size_t num_overhead_bytes = alts_crypter_num_overhead_bytes(server_seal);
size_t protected_data_size = data_size + num_overhead_bytes;
uint8_t* data_buffer1 =
static_cast<uint8_t*>(gpr_malloc(protected_data_size));
uint8_t* data_buffer2 =
static_cast<uint8_t*>(gpr_malloc(protected_data_size));
uint8_t* duplicate_buffer1 = nullptr;
uint8_t* duplicate_buffer2 = nullptr;
gsec_test_random_bytes(data_buffer1, data_size);
gsec_test_random_bytes(data_buffer2, data_size);
gsec_test_copy(data_buffer1, &duplicate_buffer1, data_size);
gsec_test_copy(data_buffer2, &duplicate_buffer2, data_size);
/* Client seal and server unseal */
size_t size1 = data_size, size2 = data_size;
grpc_status_code status = alts_crypter_process_in_place(
client_seal, data_buffer1, protected_data_size, size1, &size1, nullptr);
GPR_ASSERT(status == GRPC_STATUS_OK);
GPR_ASSERT(size1 == protected_data_size);
status = alts_crypter_process_in_place(
client_seal, data_buffer2, protected_data_size, size2, &size2, nullptr);
GPR_ASSERT(status == GRPC_STATUS_OK);
GPR_ASSERT(size2 == protected_data_size);
status = alts_crypter_process_in_place(
server_unseal, data_buffer1, protected_data_size, size1, &size1, nullptr);
GPR_ASSERT(status == GRPC_STATUS_OK);
GPR_ASSERT(memcmp(data_buffer1, duplicate_buffer1, data_size) == 0);
GPR_ASSERT(size1 == data_size);
status = alts_crypter_process_in_place(
server_unseal, data_buffer2, protected_data_size, size2, &size2, nullptr);
GPR_ASSERT(status == GRPC_STATUS_OK);
GPR_ASSERT(memcmp(data_buffer2, duplicate_buffer2, data_size) == 0);
GPR_ASSERT(size2 == data_size);
/* Server seal and client unseal */
status = alts_crypter_process_in_place(
server_seal, data_buffer1, protected_data_size, size1, &size1, nullptr);
GPR_ASSERT(status == GRPC_STATUS_OK);
GPR_ASSERT(size1 == protected_data_size);
status = alts_crypter_process_in_place(
server_seal, data_buffer2, protected_data_size, size2, &size2, nullptr);
GPR_ASSERT(status == GRPC_STATUS_OK);
GPR_ASSERT(size2 == protected_data_size);
status = alts_crypter_process_in_place(
client_unseal, data_buffer1, protected_data_size, size1, &size1, nullptr);
GPR_ASSERT(status == GRPC_STATUS_OK);
GPR_ASSERT(memcmp(data_buffer1, duplicate_buffer1, data_size) == 0);
GPR_ASSERT(size1 == data_size);
status = alts_crypter_process_in_place(
client_unseal, data_buffer2, protected_data_size, size2, &size2, nullptr);
GPR_ASSERT(status == GRPC_STATUS_OK);
GPR_ASSERT(memcmp(data_buffer2, duplicate_buffer2, data_size) == 0);
GPR_ASSERT(size2 == data_size);
gpr_free(data_buffer1);
gpr_free(data_buffer2);
gpr_free(duplicate_buffer1);
gpr_free(duplicate_buffer2);
}
static void alts_crypter_test_corrupted_unseal(alts_crypter* server_seal,
alts_crypter* server_unseal,
alts_crypter* client_seal,
alts_crypter* client_unseal) {
size_t data_size = gsec_test_bias_random_uint32(1024) + 1;
size_t num_overhead_bytes = alts_crypter_num_overhead_bytes(server_seal);
size_t protected_data_size = data_size + num_overhead_bytes;
auto* data_buffer = static_cast<uint8_t*>(gpr_malloc(protected_data_size));
auto* zero_buffer = static_cast<uint8_t*>(gpr_zalloc(data_size));
/* Corrupt a random byte in protected data. */
size_t size = data_size;
gsec_test_random_bytes(data_buffer, data_size);
grpc_status_code status = alts_crypter_process_in_place(
client_seal, data_buffer, protected_data_size, size, &size, nullptr);
GPR_ASSERT(status == GRPC_STATUS_OK);
GPR_ASSERT(size == protected_data_size);
uint8_t* corrupted_data_buffer;
char* error_message = nullptr;
gsec_test_copy_and_alter_random_byte(data_buffer, &corrupted_data_buffer,
protected_data_size);
status = alts_crypter_process_in_place(server_unseal, corrupted_data_buffer,
protected_data_size, size, &size,
&error_message);
GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
status, GRPC_STATUS_FAILED_PRECONDITION, error_message,
"Checking tag failed"));
GPR_ASSERT(memcmp(corrupted_data_buffer, zero_buffer, data_size) == 0);
gpr_free(corrupted_data_buffer);
gpr_free(error_message);
/* Corrupt the beginning of protected data. */
size = data_size;
gsec_test_random_bytes(data_buffer, data_size);
status = alts_crypter_process_in_place(
client_seal, data_buffer, protected_data_size, size, &size, nullptr);
GPR_ASSERT(status == GRPC_STATUS_OK);
GPR_ASSERT(size == protected_data_size);
gsec_test_copy(data_buffer, &corrupted_data_buffer, protected_data_size);
(*corrupted_data_buffer)++;
status = alts_crypter_process_in_place(server_unseal, corrupted_data_buffer,
protected_data_size, size, &size,
&error_message);
GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
status, GRPC_STATUS_FAILED_PRECONDITION, error_message,
"Checking tag failed"));
GPR_ASSERT(memcmp(corrupted_data_buffer, zero_buffer, data_size) == 0);
gpr_free(corrupted_data_buffer);
gpr_free(error_message);
/* Corrupt the end of protected data. */
size = data_size;
gsec_test_random_bytes(data_buffer, data_size);
status = alts_crypter_process_in_place(
client_seal, data_buffer, protected_data_size, size, &size, nullptr);
GPR_ASSERT(status == GRPC_STATUS_OK);
GPR_ASSERT(size == protected_data_size);
gsec_test_copy(data_buffer, &corrupted_data_buffer, protected_data_size);
(*(corrupted_data_buffer + protected_data_size - 1))++;
status = alts_crypter_process_in_place(server_unseal, corrupted_data_buffer,
protected_data_size, size, &size,
&error_message);
GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
status, GRPC_STATUS_FAILED_PRECONDITION, error_message,
"Checking tag failed"));
GPR_ASSERT(memcmp(corrupted_data_buffer, zero_buffer, data_size) == 0);
gpr_free(corrupted_data_buffer);
gpr_free(error_message);
gpr_free(data_buffer);
gpr_free(zero_buffer);
}
static void alts_crypter_test_unsync_seal_unseal(alts_crypter* server_seal,
alts_crypter* server_unseal,
alts_crypter* client_seal,
alts_crypter* client_unseal) {
size_t data_size = gsec_test_bias_random_uint32(1024) + 1;
size_t num_overhead_bytes = alts_crypter_num_overhead_bytes(server_seal);
size_t protected_data_size = data_size + num_overhead_bytes;
auto* data_buffer = static_cast<uint8_t*>(gpr_malloc(protected_data_size));
auto* zero_buffer = static_cast<uint8_t*>(gpr_zalloc(data_size));
/* Perform two seals at client, one unseal at server. */
size_t size = data_size;
gsec_test_random_bytes(data_buffer, data_size);
grpc_status_code status = alts_crypter_process_in_place(
client_seal, data_buffer, protected_data_size, size, &size, nullptr);
GPR_ASSERT(status == GRPC_STATUS_OK);
GPR_ASSERT(size == protected_data_size);
size = data_size;
gsec_test_random_bytes(data_buffer, data_size);
status = alts_crypter_process_in_place(
client_seal, data_buffer, protected_data_size, size, &size, nullptr);
GPR_ASSERT(status == GRPC_STATUS_OK);
GPR_ASSERT(size == protected_data_size);
char* error_message = nullptr;
status = alts_crypter_process_in_place(server_unseal, data_buffer,
protected_data_size, size, &size,
&error_message);
GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
status, GRPC_STATUS_FAILED_PRECONDITION, error_message,
"Checking tag failed"));
GPR_ASSERT(memcmp(data_buffer, zero_buffer, data_size) == 0);
gpr_free(error_message);
/* Perform two seals at server, one unseal at client. */
size = data_size;
gsec_test_random_bytes(data_buffer, data_size);
status = alts_crypter_process_in_place(
server_seal, data_buffer, protected_data_size, size, &size, nullptr);
GPR_ASSERT(status == GRPC_STATUS_OK);
GPR_ASSERT(size == protected_data_size);
size = data_size;
gsec_test_random_bytes(data_buffer, data_size);
status = alts_crypter_process_in_place(
server_seal, data_buffer, protected_data_size, size, &size, nullptr);
GPR_ASSERT(status == GRPC_STATUS_OK);
GPR_ASSERT(size == protected_data_size);
status = alts_crypter_process_in_place(client_unseal, data_buffer,
protected_data_size, size, &size,
&error_message);
GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
status, GRPC_STATUS_FAILED_PRECONDITION, error_message,
"Checking tag failed"));
GPR_ASSERT(memcmp(data_buffer, zero_buffer, data_size) == 0);
gpr_free(error_message);
gpr_free(data_buffer);
gpr_free(zero_buffer);
}
static void alts_crypter_test_input_sanity_check(alts_crypter* crypter_seal,
alts_crypter* crypter_unseal) {
size_t data_size = gsec_test_bias_random_uint32(1024) + 1;
size_t num_overhead_bytes = alts_crypter_num_overhead_bytes(crypter_seal);
size_t protected_data_size = data_size + num_overhead_bytes;
auto* data_buffer = static_cast<uint8_t*>(gpr_malloc(protected_data_size));
gsec_test_random_bytes(data_buffer, data_size);
char* error_message = nullptr;
size_t size = data_size;
/* Crypter is nullptr. */
grpc_status_code status = alts_crypter_process_in_place(
nullptr, data_buffer, protected_data_size, size, &size, &error_message);
GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
status, GRPC_STATUS_INVALID_ARGUMENT, error_message,
"crypter or crypter->vtable has not been initialized properly."));
gpr_free(error_message);
/* Seal data is nullptr. */
size = data_size;
status = alts_crypter_process_in_place(
crypter_seal, nullptr, protected_data_size, size, &size, &error_message);
GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
status, GRPC_STATUS_INVALID_ARGUMENT, error_message, "data is nullptr."));
gpr_free(error_message);
/* Seal data size is 0. */
size = 0;
status = alts_crypter_process_in_place(crypter_seal, data_buffer,
protected_data_size, size, &size,
&error_message);
GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
status, GRPC_STATUS_INVALID_ARGUMENT, error_message,
"data_size is zero."));
gpr_free(error_message);
/* Seal data buffer has a size smaller than the required. */
size = data_size;
status = alts_crypter_process_in_place(crypter_seal, data_buffer,
protected_data_size - 1, size, &size,
&error_message);
GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
status, GRPC_STATUS_INVALID_ARGUMENT, error_message,
"data_allocated_size is smaller than sum of data_size and "
"num_overhead_bytes."));
gpr_free(error_message);
/* Unseal data is nullptr. */
size = data_size;
status = alts_crypter_process_in_place(crypter_unseal, nullptr,
protected_data_size, size, &size,
&error_message);
GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
status, GRPC_STATUS_INVALID_ARGUMENT, error_message, "data is nullptr."));
gpr_free(error_message);
/* Unseal data size is 0. */
size = 0;
status = alts_crypter_process_in_place(crypter_unseal, data_buffer,
protected_data_size, size, &size,
&error_message);
GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
status, GRPC_STATUS_INVALID_ARGUMENT, error_message,
"data_size is smaller than num_overhead_bytes."));
gpr_free(error_message);
/* Unseal data size is smaller than number of overhead bytes. */
size = num_overhead_bytes - 1;
status = alts_crypter_process_in_place(crypter_unseal, data_buffer,
protected_data_size, size, &size,
&error_message);
GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
status, GRPC_STATUS_INVALID_ARGUMENT, error_message,
"data_size is smaller than num_overhead_bytes."));
gpr_free(error_message);
gpr_free(data_buffer);
}
static void create_random_alts_seal_crypter(
alts_crypter** server_seal, alts_crypter** server_unseal,
alts_crypter** client_seal, alts_crypter** client_unseal,
gsec_aead_crypter** server_crypter_seal,
gsec_aead_crypter** server_crypter_unseal,
gsec_aead_crypter** client_crypter_seal,
gsec_aead_crypter** client_crypter_unseal, bool rekey) {
size_t key_length = rekey ? kAes128GcmRekeyKeyLength : kAes128GcmKeyLength;
uint8_t* key;
gsec_test_random_array(&key, key_length);
gsec_aes_gcm_aead_crypter_create(key, key_length, kAesGcmNonceLength,
kAesGcmTagLength, rekey, server_crypter_seal,
nullptr);
gsec_aes_gcm_aead_crypter_create(key, key_length, kAesGcmNonceLength,
kAesGcmTagLength, rekey,
server_crypter_unseal, nullptr);
gsec_aes_gcm_aead_crypter_create(key, key_length, kAesGcmNonceLength,
kAesGcmTagLength, rekey, client_crypter_seal,
nullptr);
gsec_aes_gcm_aead_crypter_create(key, key_length, kAesGcmNonceLength,
kAesGcmTagLength, rekey,
client_crypter_unseal, nullptr);
size_t overflow_size = rekey ? 8 : 5;
alts_seal_crypter_create(*client_crypter_seal, /*is_client=*/true,
overflow_size, client_seal, nullptr);
alts_unseal_crypter_create(*client_crypter_unseal, /*is_client=*/true,
overflow_size, client_unseal, nullptr);
alts_seal_crypter_create(*server_crypter_seal, /*is_client=*/false,
overflow_size, server_seal, nullptr);
alts_unseal_crypter_create(*server_crypter_unseal, /*is_client=*/false,
overflow_size, server_unseal, nullptr);
gpr_free(key);
}
static void destroy_random_alts_seal_crypter(alts_crypter* server_seal,
alts_crypter* server_unseal,
alts_crypter* client_seal,
alts_crypter* client_unseal) {
alts_crypter_destroy(server_seal);
alts_crypter_destroy(server_unseal);
alts_crypter_destroy(client_seal);
alts_crypter_destroy(client_unseal);
}
static void alts_crypter_do_generic_tests() {
alts_crypter *server_seal = nullptr, *server_unseal = nullptr,
*client_seal = nullptr, *client_unseal = nullptr;
gsec_aead_crypter *server_crypter_seal = nullptr,
*server_crypter_unseal = nullptr,
*client_crypter_seal = nullptr,
*client_crypter_unseal = nullptr;
/* Random seal and unseal tests */
create_random_alts_seal_crypter(&server_seal, &server_unseal, &client_seal,
&client_unseal, &server_crypter_seal,
&server_crypter_unseal, &client_crypter_seal,
&client_crypter_unseal, /*rekey=*/false);
alts_crypter_test_random_seal_unseal(server_seal, server_unseal, client_seal,
client_unseal);
destroy_random_alts_seal_crypter(server_seal, server_unseal, client_seal,
client_unseal);
create_random_alts_seal_crypter(&server_seal, &server_unseal, &client_seal,
&client_unseal, &server_crypter_seal,
&server_crypter_unseal, &client_crypter_seal,
&client_crypter_unseal, /*rekey=*/true);
alts_crypter_test_random_seal_unseal(server_seal, server_unseal, client_seal,
client_unseal);
destroy_random_alts_seal_crypter(server_seal, server_unseal, client_seal,
client_unseal);
/* Multiple random seal and unseal tests */
create_random_alts_seal_crypter(&server_seal, &server_unseal, &client_seal,
&client_unseal, &server_crypter_seal,
&server_crypter_unseal, &client_crypter_seal,
&client_crypter_unseal, /*rekey=*/false);
alts_crypter_test_multiple_random_seal_unseal(server_seal, server_unseal,
client_seal, client_unseal);
destroy_random_alts_seal_crypter(server_seal, server_unseal, client_seal,
client_unseal);
create_random_alts_seal_crypter(&server_seal, &server_unseal, &client_seal,
&client_unseal, &server_crypter_seal,
&server_crypter_unseal, &client_crypter_seal,
&client_crypter_unseal, /*rekey=*/true);
alts_crypter_test_multiple_random_seal_unseal(server_seal, server_unseal,
client_seal, client_unseal);
destroy_random_alts_seal_crypter(server_seal, server_unseal, client_seal,
client_unseal);
/* Corrupted unseal tests */
create_random_alts_seal_crypter(&server_seal, &server_unseal, &client_seal,
&client_unseal, &server_crypter_seal,
&server_crypter_unseal, &client_crypter_seal,
&client_crypter_unseal, /*rekey=*/false);
alts_crypter_test_corrupted_unseal(server_seal, server_unseal, client_seal,
client_unseal);
destroy_random_alts_seal_crypter(server_seal, server_unseal, client_seal,
client_unseal);
create_random_alts_seal_crypter(&server_seal, &server_unseal, &client_seal,
&client_unseal, &server_crypter_seal,
&server_crypter_unseal, &client_crypter_seal,
&client_crypter_unseal, /*rekey=*/true);
alts_crypter_test_corrupted_unseal(server_seal, server_unseal, client_seal,
client_unseal);
destroy_random_alts_seal_crypter(server_seal, server_unseal, client_seal,
client_unseal);
/* Unsync seal and unseal tests */
create_random_alts_seal_crypter(&server_seal, &server_unseal, &client_seal,
&client_unseal, &server_crypter_seal,
&server_crypter_unseal, &client_crypter_seal,
&client_crypter_unseal, /*rekey=*/false);
alts_crypter_test_unsync_seal_unseal(server_seal, server_unseal, client_seal,
client_unseal);
destroy_random_alts_seal_crypter(server_seal, server_unseal, client_seal,
client_unseal);
create_random_alts_seal_crypter(&server_seal, &server_unseal, &client_seal,
&client_unseal, &server_crypter_seal,
&server_crypter_unseal, &client_crypter_seal,
&client_crypter_unseal, /*rekey=*/true);
alts_crypter_test_unsync_seal_unseal(server_seal, server_unseal, client_seal,
client_unseal);
destroy_random_alts_seal_crypter(server_seal, server_unseal, client_seal,
client_unseal);
/* Input sanity check tests */
create_random_alts_seal_crypter(&server_seal, &server_unseal, &client_seal,
&client_unseal, &server_crypter_seal,
&server_crypter_unseal, &client_crypter_seal,
&client_crypter_unseal, /*rekey=*/false);
alts_crypter_test_input_sanity_check(server_seal, server_unseal);
destroy_random_alts_seal_crypter(server_seal, server_unseal, client_seal,
client_unseal);
create_random_alts_seal_crypter(&server_seal, &server_unseal, &client_seal,
&client_unseal, &server_crypter_seal,
&server_crypter_unseal, &client_crypter_seal,
&client_crypter_unseal, /*rekey=*/true);
alts_crypter_test_input_sanity_check(server_seal, server_unseal);
destroy_random_alts_seal_crypter(server_seal, server_unseal, client_seal,
client_unseal);
}
int main(int argc, char** argv) {
alts_crypter_do_generic_tests();
return 0;
}

@ -0,0 +1,394 @@
/*
*
* Copyright 2018 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 <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <stdbool.h>
#include "src/core/tsi/alts/crypt/gsec.h"
#include "src/core/tsi/alts/frame_protector/alts_frame_protector.h"
#include "src/core/tsi/transport_security_interface.h"
#include "test/core/tsi/alts/crypt/gsec_test_util.h"
#include "test/core/tsi/transport_security_test_lib.h"
const size_t kChannelSize = 32768;
static void alts_test_do_round_trip_check_frames(
tsi_test_frame_protector_fixture* fixture, const uint8_t* key,
const size_t key_size, bool rekey, const uint8_t* client_message,
const size_t client_message_size, const uint8_t* client_expected_frames,
const size_t client_frame_size, const uint8_t* server_message,
const size_t server_message_size, const uint8_t* server_expected_frames,
const size_t server_frame_size) {
GPR_ASSERT(fixture != nullptr);
GPR_ASSERT(fixture->config != nullptr);
tsi_frame_protector* client_frame_protector = nullptr;
tsi_frame_protector* server_frame_protector = nullptr;
tsi_test_frame_protector_config* config = fixture->config;
tsi_test_channel* channel = fixture->channel;
/* Create a client frame protector. */
size_t client_max_output_protected_frame_size =
config->client_max_output_protected_frame_size;
GPR_ASSERT(
alts_create_frame_protector(key, key_size, /*is_client=*/true, rekey,
client_max_output_protected_frame_size == 0
? nullptr
: &client_max_output_protected_frame_size,
&client_frame_protector) == TSI_OK);
/* Create a server frame protector. */
size_t server_max_output_protected_frame_size =
config->server_max_output_protected_frame_size;
GPR_ASSERT(
alts_create_frame_protector(key, key_size, /*is_client=*/false, rekey,
server_max_output_protected_frame_size == 0
? nullptr
: &server_max_output_protected_frame_size,
&server_frame_protector) == TSI_OK);
tsi_test_frame_protector_fixture_init(fixture, client_frame_protector,
server_frame_protector);
/* Client sends a message to server. */
uint8_t* saved_client_message = config->client_message;
config->client_message = const_cast<uint8_t*>(client_message);
config->client_message_size = client_message_size;
tsi_test_frame_protector_send_message_to_peer(config, channel,
client_frame_protector,
/*is_client=*/true);
/* Verify if the generated frame is the same as the expected. */
GPR_ASSERT(channel->bytes_written_to_server_channel == client_frame_size);
GPR_ASSERT(memcmp(client_expected_frames, channel->server_channel,
client_frame_size) == 0);
unsigned char* server_received_message =
static_cast<unsigned char*>(gpr_malloc(kChannelSize));
size_t server_received_message_size = 0;
tsi_test_frame_protector_receive_message_from_peer(
config, channel, server_frame_protector, server_received_message,
&server_received_message_size, /*is_client=*/false);
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. */
uint8_t* saved_server_message = config->server_message;
config->server_message = const_cast<uint8_t*>(server_message);
config->server_message_size = server_message_size;
tsi_test_frame_protector_send_message_to_peer(config, channel,
server_frame_protector,
/*is_client=*/false);
/* Verify if the generated frame is the same as the expected. */
GPR_ASSERT(channel->bytes_written_to_client_channel == server_frame_size);
GPR_ASSERT(memcmp(server_expected_frames, channel->client_channel,
server_frame_size) == 0);
unsigned char* client_received_message =
static_cast<unsigned char*>(gpr_malloc(kChannelSize));
size_t client_received_message_size = 0;
tsi_test_frame_protector_receive_message_from_peer(
config, channel, client_frame_protector, client_received_message,
&client_received_message_size,
/*is_client=*/true);
GPR_ASSERT(config->server_message_size == client_received_message_size);
GPR_ASSERT(memcmp(config->server_message, client_received_message,
client_received_message_size) == 0);
config->client_message = saved_client_message;
config->server_message = saved_server_message;
/* Destroy server and client frame protectors. */
gpr_free(server_received_message);
gpr_free(client_received_message);
}
static void alts_test_do_round_trip_vector_tests() {
const uint8_t key[] = {0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08};
const char small_message[] = {'C', 'h', 'a', 'p', 'i', ' ',
'C', 'h', 'a', 'p', 'o'};
const uint8_t large_message[] = {
0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5,
0xaf, 0xf5, 0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95,
0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, 0xba, 0x63, 0x7b, 0x39,
0x1a, 0xaf, 0xd2, 0x55, 0xd6, 0x09, 0xb1, 0xf0, 0x56, 0x63, 0x7a, 0x0d,
0x46, 0xdf, 0x99, 0x8d, 0x88, 0xe5, 0x22, 0x2a, 0xb2, 0xc2, 0x84, 0x65,
0x12, 0x15, 0x35, 0x24, 0xc0, 0x89, 0x5e, 0x81, 0x08, 0x06, 0x0f, 0x10,
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c,
0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30};
const size_t small_message_size = sizeof(small_message) / sizeof(uint8_t);
const size_t large_message_size = sizeof(large_message) / sizeof(uint8_t);
/* Test small client message and large server message. */
const uint8_t client_expected_frame1[] = {
0x1f, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x09, 0xd8, 0xd5, 0x92,
0x4d, 0x50, 0x32, 0xb7, 0x1f, 0xb8, 0xf2, 0xbb, 0x43, 0xc7, 0xe2, 0x94,
0x3d, 0x3e, 0x9a, 0x78, 0x76, 0xaa, 0x0a, 0x6b, 0xfa, 0x98, 0x3a};
const uint8_t server_expected_frame1[] = {
0x94, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xa9, 0x4b, 0xf8, 0xc8,
0xe7, 0x8f, 0x1a, 0x26, 0x37, 0x44, 0xa2, 0x5c, 0x55, 0x94, 0x30, 0x4e,
0x3e, 0x16, 0xe7, 0x9e, 0x96, 0xe8, 0x1b, 0xc0, 0xdd, 0x52, 0x30, 0x06,
0xc2, 0x72, 0x9a, 0xa1, 0x0b, 0xdb, 0xdc, 0x19, 0x8c, 0x93, 0x5e, 0x84,
0x1f, 0x4b, 0x97, 0x26, 0xf0, 0x73, 0x85, 0x59, 0x00, 0x95, 0xc1, 0xc5,
0x22, 0x2f, 0x70, 0x85, 0x68, 0x2c, 0x4f, 0xfe, 0x30, 0x26, 0x91, 0xde,
0x62, 0x55, 0x1d, 0x35, 0x01, 0x96, 0x1c, 0xe7, 0xa2, 0x8b, 0x14, 0x8a,
0x5e, 0x1b, 0x4a, 0x3b, 0x4f, 0x65, 0x0f, 0xca, 0x79, 0x10, 0xb4, 0xdd,
0xf7, 0xa4, 0x8b, 0x64, 0x2f, 0x00, 0x39, 0x60, 0x03, 0xfc, 0xe1, 0x8b,
0x5c, 0x19, 0xba, 0xcc, 0x46, 0xba, 0x88, 0xdd, 0x40, 0x42, 0x27, 0x4f,
0xe4, 0x1a, 0x6a, 0x31, 0x6c, 0x1c, 0xb0, 0xb6, 0x5c, 0x3e, 0xca, 0x84,
0x9b, 0x5f, 0x04, 0x84, 0x11, 0xa9, 0xf8, 0x39, 0xe7, 0xe7, 0xc5, 0xc4,
0x33, 0x9f, 0x63, 0x21, 0x9a, 0x7c, 0x9c, 0x64};
const size_t client_frame_size1 =
sizeof(client_expected_frame1) / sizeof(uint8_t);
const size_t server_frame_size1 =
sizeof(server_expected_frame1) / sizeof(uint8_t);
tsi_test_frame_protector_fixture* fixture =
tsi_test_frame_protector_fixture_create();
alts_test_do_round_trip_check_frames(
fixture, key, kAes128GcmKeyLength, /*rekey=*/false,
reinterpret_cast<const uint8_t*>(small_message), small_message_size,
client_expected_frame1, client_frame_size1, large_message,
large_message_size, server_expected_frame1, server_frame_size1);
tsi_test_frame_protector_fixture_destroy(fixture);
/**
* Test large client message, small server message, and small
* message_buffer_allocated_size.
*/
const uint8_t client_expected_frame2[] = {
0x94, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x93, 0x81, 0x86, 0xc7,
0xdc, 0xf4, 0x77, 0x3a, 0xdb, 0x91, 0x94, 0x61, 0xba, 0xed, 0xd5, 0x37,
0x47, 0x53, 0x0c, 0xe1, 0xbf, 0x59, 0x23, 0x20, 0xde, 0x8b, 0x25, 0x13,
0x72, 0xe7, 0x8a, 0x4f, 0x32, 0x61, 0xc6, 0xda, 0xc3, 0xe9, 0xff, 0x31,
0x33, 0x53, 0x4a, 0xf8, 0xc9, 0x98, 0xe4, 0x19, 0x71, 0x9c, 0x5e, 0x72,
0xc7, 0x35, 0x97, 0x78, 0x30, 0xf2, 0xc4, 0xd1, 0x53, 0xd5, 0x6e, 0x8f,
0x4f, 0xd9, 0x28, 0x5a, 0xfd, 0x22, 0x57, 0x7f, 0x95, 0xb4, 0x8a, 0x5e,
0x7c, 0x47, 0xa8, 0xcf, 0x64, 0x3d, 0x83, 0xa5, 0xcf, 0xc3, 0xfe, 0x54,
0xc2, 0x6a, 0x40, 0xc4, 0xfb, 0x8e, 0x07, 0x77, 0x70, 0x8f, 0x99, 0x94,
0xb1, 0xd5, 0xa7, 0xf9, 0x0d, 0xc7, 0x11, 0xc5, 0x6f, 0x4a, 0x4f, 0x56,
0xd5, 0xe2, 0x9c, 0xbb, 0x95, 0x7a, 0xd0, 0x9f, 0x30, 0x54, 0xca, 0x6d,
0x5c, 0x8e, 0x83, 0xa0, 0x04, 0x5e, 0xd0, 0x22, 0x8c, 0x2a, 0x7f, 0xdb,
0xfe, 0xb3, 0x2e, 0xae, 0x22, 0xe6, 0xf4, 0xb7};
const uint8_t server_expected_frame2[] = {
0x1f, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x33, 0x12, 0xab, 0x9d,
0x76, 0x2b, 0x5f, 0xab, 0xf3, 0x6d, 0xc4, 0xaa, 0xe5, 0x1e, 0x63, 0xc1,
0x7b, 0x7b, 0x10, 0xd5, 0x63, 0x0f, 0x29, 0xad, 0x17, 0x33, 0x73};
const size_t client_frame_size2 =
sizeof(client_expected_frame2) / sizeof(uint8_t);
const size_t server_frame_size2 =
sizeof(server_expected_frame2) / sizeof(uint8_t);
fixture = tsi_test_frame_protector_fixture_create();
alts_test_do_round_trip_check_frames(
fixture, key, kAes128GcmKeyLength, /*rekey=*/false, large_message,
large_message_size, client_expected_frame2, client_frame_size2,
reinterpret_cast<const uint8_t*>(small_message), small_message_size,
server_expected_frame2, server_frame_size2);
tsi_test_frame_protector_fixture_destroy(fixture);
/**
* Test large client message, small server message, and small
* protected_buffer_size.
*/
const uint8_t client_expected_frame3[] = {
0x94, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x93, 0x81, 0x86, 0xc7,
0xdc, 0xf4, 0x77, 0x3a, 0xdb, 0x91, 0x94, 0x61, 0xba, 0xed, 0xd5, 0x37,
0x47, 0x53, 0x0c, 0xe1, 0xbf, 0x59, 0x23, 0x20, 0xde, 0x8b, 0x25, 0x13,
0x72, 0xe7, 0x8a, 0x4f, 0x32, 0x61, 0xc6, 0xda, 0xc3, 0xe9, 0xff, 0x31,
0x33, 0x53, 0x4a, 0xf8, 0xc9, 0x98, 0xe4, 0x19, 0x71, 0x9c, 0x5e, 0x72,
0xc7, 0x35, 0x97, 0x78, 0x30, 0xf2, 0xc4, 0xd1, 0x53, 0xd5, 0x6e, 0x8f,
0x4f, 0xd9, 0x28, 0x5a, 0xfd, 0x22, 0x57, 0x7f, 0x95, 0xb4, 0x8a, 0x5e,
0x7c, 0x47, 0xa8, 0xcf, 0x64, 0x3d, 0x83, 0xa5, 0xcf, 0xc3, 0xfe, 0x54,
0xc2, 0x6a, 0x40, 0xc4, 0xfb, 0x8e, 0x07, 0x77, 0x70, 0x8f, 0x99, 0x94,
0xb1, 0xd5, 0xa7, 0xf9, 0x0d, 0xc7, 0x11, 0xc5, 0x6f, 0x4a, 0x4f, 0x56,
0xd5, 0xe2, 0x9c, 0xbb, 0x95, 0x7a, 0xd0, 0x9f, 0x30, 0x54, 0xca, 0x6d,
0x5c, 0x8e, 0x83, 0xa0, 0x04, 0x5e, 0xd0, 0x22, 0x8c, 0x2a, 0x7f, 0xdb,
0xfe, 0xb3, 0x2e, 0xae, 0x22, 0xe6, 0xf4, 0xb7};
const uint8_t server_expected_frame3[] = {
0x1f, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x33, 0x12, 0xab, 0x9d,
0x76, 0x2b, 0x5f, 0xab, 0xf3, 0x6d, 0xc4, 0xaa, 0xe5, 0x1e, 0x63, 0xc1,
0x7b, 0x7b, 0x10, 0xd5, 0x63, 0x0f, 0x29, 0xad, 0x17, 0x33, 0x73};
const size_t client_frame_size3 =
sizeof(client_expected_frame3) / sizeof(uint8_t);
const size_t server_frame_size3 =
sizeof(server_expected_frame3) / sizeof(uint8_t);
fixture = tsi_test_frame_protector_fixture_create();
alts_test_do_round_trip_check_frames(
fixture, key, kAes128GcmKeyLength, /*rekey=*/false, large_message,
large_message_size, client_expected_frame3, client_frame_size3,
reinterpret_cast<const uint8_t*>(small_message), small_message_size,
server_expected_frame3, server_frame_size3);
tsi_test_frame_protector_fixture_destroy(fixture);
/**
* Test large client message, small server message, and small
* read_buffer_allocated_size.
*/
const uint8_t client_expected_frame4[] = {
0x94, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x93, 0x81, 0x86, 0xc7,
0xdc, 0xf4, 0x77, 0x3a, 0xdb, 0x91, 0x94, 0x61, 0xba, 0xed, 0xd5, 0x37,
0x47, 0x53, 0x0c, 0xe1, 0xbf, 0x59, 0x23, 0x20, 0xde, 0x8b, 0x25, 0x13,
0x72, 0xe7, 0x8a, 0x4f, 0x32, 0x61, 0xc6, 0xda, 0xc3, 0xe9, 0xff, 0x31,
0x33, 0x53, 0x4a, 0xf8, 0xc9, 0x98, 0xe4, 0x19, 0x71, 0x9c, 0x5e, 0x72,
0xc7, 0x35, 0x97, 0x78, 0x30, 0xf2, 0xc4, 0xd1, 0x53, 0xd5, 0x6e, 0x8f,
0x4f, 0xd9, 0x28, 0x5a, 0xfd, 0x22, 0x57, 0x7f, 0x95, 0xb4, 0x8a, 0x5e,
0x7c, 0x47, 0xa8, 0xcf, 0x64, 0x3d, 0x83, 0xa5, 0xcf, 0xc3, 0xfe, 0x54,
0xc2, 0x6a, 0x40, 0xc4, 0xfb, 0x8e, 0x07, 0x77, 0x70, 0x8f, 0x99, 0x94,
0xb1, 0xd5, 0xa7, 0xf9, 0x0d, 0xc7, 0x11, 0xc5, 0x6f, 0x4a, 0x4f, 0x56,
0xd5, 0xe2, 0x9c, 0xbb, 0x95, 0x7a, 0xd0, 0x9f, 0x30, 0x54, 0xca, 0x6d,
0x5c, 0x8e, 0x83, 0xa0, 0x04, 0x5e, 0xd0, 0x22, 0x8c, 0x2a, 0x7f, 0xdb,
0xfe, 0xb3, 0x2e, 0xae, 0x22, 0xe6, 0xf4, 0xb7};
const uint8_t server_expected_frame4[] = {
0x1f, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x33, 0x12, 0xab, 0x9d,
0x76, 0x2b, 0x5f, 0xab, 0xf3, 0x6d, 0xc4, 0xaa, 0xe5, 0x1e, 0x63, 0xc1,
0x7b, 0x7b, 0x10, 0xd5, 0x63, 0x0f, 0x29, 0xad, 0x17, 0x33, 0x73};
const size_t client_frame_size4 =
sizeof(client_expected_frame4) / sizeof(uint8_t);
const size_t server_frame_size4 =
sizeof(server_expected_frame4) / sizeof(uint8_t);
fixture = tsi_test_frame_protector_fixture_create();
alts_test_do_round_trip_check_frames(
fixture, key, kAes128GcmKeyLength, /*rekey=*/false, large_message,
large_message_size, client_expected_frame4, client_frame_size4,
reinterpret_cast<const uint8_t*>(small_message), small_message_size,
server_expected_frame4, server_frame_size4);
tsi_test_frame_protector_fixture_destroy(fixture);
/**
* Test large client message, small server message, and small
* client_max_output_protected_frame_size.
*/
const uint8_t client_expected_frame5[] = {
0x94, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x93, 0x81, 0x86, 0xc7,
0xdc, 0xf4, 0x77, 0x3a, 0xdb, 0x91, 0x94, 0x61, 0xba, 0xed, 0xd5, 0x37,
0x47, 0x53, 0x0c, 0xe1, 0xbf, 0x59, 0x23, 0x20, 0xde, 0x8b, 0x25, 0x13,
0x72, 0xe7, 0x8a, 0x4f, 0x32, 0x61, 0xc6, 0xda, 0xc3, 0xe9, 0xff, 0x31,
0x33, 0x53, 0x4a, 0xf8, 0xc9, 0x98, 0xe4, 0x19, 0x71, 0x9c, 0x5e, 0x72,
0xc7, 0x35, 0x97, 0x78, 0x30, 0xf2, 0xc4, 0xd1, 0x53, 0xd5, 0x6e, 0x8f,
0x4f, 0xd9, 0x28, 0x5a, 0xfd, 0x22, 0x57, 0x7f, 0x95, 0xb4, 0x8a, 0x5e,
0x7c, 0x47, 0xa8, 0xcf, 0x64, 0x3d, 0x83, 0xa5, 0xcf, 0xc3, 0xfe, 0x54,
0xc2, 0x6a, 0x40, 0xc4, 0xfb, 0x8e, 0x07, 0x77, 0x70, 0x8f, 0x99, 0x94,
0xb1, 0xd5, 0xa7, 0xf9, 0x0d, 0xc7, 0x11, 0xc5, 0x6f, 0x4a, 0x4f, 0x56,
0xd5, 0xe2, 0x9c, 0xbb, 0x95, 0x7a, 0xd0, 0x9f, 0x30, 0x54, 0xca, 0x6d,
0x5c, 0x8e, 0x83, 0xa0, 0x04, 0x5e, 0xd0, 0x22, 0x8c, 0x2a, 0x7f, 0xdb,
0xfe, 0xb3, 0x2e, 0xae, 0x22, 0xe6, 0xf4, 0xb7};
const uint8_t server_expected_frame5[] = {
0x1f, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x33, 0x12, 0xab, 0x9d,
0x76, 0x2b, 0x5f, 0xab, 0xf3, 0x6d, 0xc4, 0xaa, 0xe5, 0x1e, 0x63, 0xc1,
0x7b, 0x7b, 0x10, 0xd5, 0x63, 0x0f, 0x29, 0xad, 0x17, 0x33, 0x73};
const size_t client_frame_size5 =
sizeof(client_expected_frame5) / sizeof(uint8_t);
const size_t server_frame_size5 =
sizeof(server_expected_frame5) / sizeof(uint8_t);
fixture = tsi_test_frame_protector_fixture_create();
alts_test_do_round_trip_check_frames(
fixture, key, kAes128GcmKeyLength, /*rekey=*/false, large_message,
large_message_size, client_expected_frame5, client_frame_size5,
reinterpret_cast<const uint8_t*>(small_message), small_message_size,
server_expected_frame5, server_frame_size5);
tsi_test_frame_protector_fixture_destroy(fixture);
/**
* Test small client message, large server message, and small
* server_max_output_protected_frame_size.
*/
const uint8_t client_expected_frame6[] = {
0x1f, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x09, 0xd8, 0xd5, 0x92,
0x4d, 0x50, 0x32, 0xb7, 0x1f, 0xb8, 0xf2, 0xbb, 0x43, 0xc7, 0xe2, 0x94,
0x3d, 0x3e, 0x9a, 0x78, 0x76, 0xaa, 0x0a, 0x6b, 0xfa, 0x98, 0x3a};
const uint8_t server_expected_frame6[] = {
0x94, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xa9, 0x4b, 0xf8, 0xc8,
0xe7, 0x8f, 0x1a, 0x26, 0x37, 0x44, 0xa2, 0x5c, 0x55, 0x94, 0x30, 0x4e,
0x3e, 0x16, 0xe7, 0x9e, 0x96, 0xe8, 0x1b, 0xc0, 0xdd, 0x52, 0x30, 0x06,
0xc2, 0x72, 0x9a, 0xa1, 0x0b, 0xdb, 0xdc, 0x19, 0x8c, 0x93, 0x5e, 0x84,
0x1f, 0x4b, 0x97, 0x26, 0xf0, 0x73, 0x85, 0x59, 0x00, 0x95, 0xc1, 0xc5,
0x22, 0x2f, 0x70, 0x85, 0x68, 0x2c, 0x4f, 0xfe, 0x30, 0x26, 0x91, 0xde,
0x62, 0x55, 0x1d, 0x35, 0x01, 0x96, 0x1c, 0xe7, 0xa2, 0x8b, 0x14, 0x8a,
0x5e, 0x1b, 0x4a, 0x3b, 0x4f, 0x65, 0x0f, 0xca, 0x79, 0x10, 0xb4, 0xdd,
0xf7, 0xa4, 0x8b, 0x64, 0x2f, 0x00, 0x39, 0x60, 0x03, 0xfc, 0xe1, 0x8b,
0x5c, 0x19, 0xba, 0xcc, 0x46, 0xba, 0x88, 0xdd, 0x40, 0x42, 0x27, 0x4f,
0xe4, 0x1a, 0x6a, 0x31, 0x6c, 0x1c, 0xb0, 0xb6, 0x5c, 0x3e, 0xca, 0x84,
0x9b, 0x5f, 0x04, 0x84, 0x11, 0xa9, 0xf8, 0x39, 0xe7, 0xe7, 0xc5, 0xc4,
0x33, 0x9f, 0x63, 0x21, 0x9a, 0x7c, 0x9c, 0x64};
const size_t client_frame_size6 =
sizeof(client_expected_frame6) / sizeof(uint8_t);
const size_t server_frame_size6 =
sizeof(server_expected_frame6) / sizeof(uint8_t);
fixture = tsi_test_frame_protector_fixture_create();
alts_test_do_round_trip_check_frames(
fixture, key, kAes128GcmKeyLength, /*rekey=*/false,
reinterpret_cast<const uint8_t*>(small_message), small_message_size,
client_expected_frame6, client_frame_size6, large_message,
large_message_size, server_expected_frame6, server_frame_size6);
tsi_test_frame_protector_fixture_destroy(fixture);
}
static void alts_test_do_round_trip(tsi_test_frame_protector_fixture* fixture,
bool rekey) {
GPR_ASSERT(fixture != nullptr);
GPR_ASSERT(fixture->config != nullptr);
tsi_frame_protector* client_frame_protector = nullptr;
tsi_frame_protector* server_frame_protector = nullptr;
tsi_test_frame_protector_config* config = fixture->config;
/* Create a key to be used by both client and server. */
uint8_t* key = nullptr;
size_t key_length = rekey ? kAes128GcmRekeyKeyLength : kAes128GcmKeyLength;
gsec_test_random_array(&key, key_length);
/* Create a client frame protector. */
size_t client_max_output_protected_frame_size =
config->client_max_output_protected_frame_size;
GPR_ASSERT(
alts_create_frame_protector(key, key_length, /*is_client=*/true, rekey,
client_max_output_protected_frame_size == 0
? nullptr
: &client_max_output_protected_frame_size,
&client_frame_protector) == TSI_OK);
/* Create a server frame protector. */
size_t server_max_output_protected_frame_size =
config->server_max_output_protected_frame_size;
GPR_ASSERT(
alts_create_frame_protector(key, key_length, /*is_client=*/false, rekey,
server_max_output_protected_frame_size == 0
? nullptr
: &server_max_output_protected_frame_size,
&server_frame_protector) == TSI_OK);
tsi_test_frame_protector_fixture_init(fixture, client_frame_protector,
server_frame_protector);
tsi_test_frame_protector_do_round_trip_no_handshake(fixture);
gpr_free(key);
}
/* Run all combinations of different arguments of test config. */
static void alts_test_do_round_trip_all(bool rekey) {
unsigned int* bit_array = static_cast<unsigned int*>(
gpr_malloc(sizeof(unsigned int) * TSI_TEST_NUM_OF_ARGUMENTS));
unsigned int mask = 1U << (TSI_TEST_NUM_OF_ARGUMENTS - 1);
unsigned int val = 0, ind = 0;
for (val = 0; val < TSI_TEST_NUM_OF_COMBINATIONS; val++) {
unsigned int v = val;
for (ind = 0; ind < TSI_TEST_NUM_OF_ARGUMENTS; ind++) {
bit_array[ind] = (v & mask) ? 1 : 0;
v <<= 1;
}
tsi_test_frame_protector_fixture* fixture =
tsi_test_frame_protector_fixture_create();
tsi_test_frame_protector_config_destroy(fixture->config);
fixture->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]);
alts_test_do_round_trip(fixture, rekey);
tsi_test_frame_protector_fixture_destroy(fixture);
}
gpr_free(bit_array);
}
int main(int argc, char** argv) {
alts_test_do_round_trip_vector_tests();
alts_test_do_round_trip_all(/*rekey=*/false);
alts_test_do_round_trip_all(/*rekey=*/true);
return 0;
}

@ -0,0 +1,244 @@
/*
*
* Copyright 2018 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 <stdint.h>
#include <stdio.h>
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "src/core/lib/gpr/useful.h"
#include "src/core/tsi/alts/frame_protector/frame_handler.h"
#include "test/core/tsi/alts/crypt/gsec_test_util.h"
const size_t kFrameHandlerTestBufferSize = 1024;
typedef struct frame_handler {
alts_frame_writer* writer;
alts_frame_reader* reader;
unsigned char* buffer;
size_t buffer_size;
} frame_handler;
static size_t frame_length(size_t payload_length) {
return payload_length + kFrameHeaderSize;
}
static frame_handler* create_frame_handler() {
frame_handler* handler =
static_cast<frame_handler*>(gpr_malloc(sizeof(frame_handler)));
handler->writer = alts_create_frame_writer();
handler->reader = alts_create_frame_reader();
handler->buffer = nullptr;
handler->buffer_size = 0;
return handler;
}
static void destroy_frame_handler(frame_handler* handler) {
if (handler != nullptr) {
alts_destroy_frame_reader(handler->reader);
alts_destroy_frame_writer(handler->writer);
if (handler->buffer != nullptr) gpr_free(handler->buffer);
gpr_free(handler);
}
}
static void frame(frame_handler* handler, unsigned char* payload,
size_t payload_length, size_t write_length) {
handler->buffer_size = frame_length(payload_length);
handler->buffer =
static_cast<unsigned char*>(gpr_malloc(handler->buffer_size));
GPR_ASSERT(alts_reset_frame_writer(handler->writer, payload, payload_length));
size_t offset = 0;
while (offset < handler->buffer_size &&
!alts_is_frame_writer_done(handler->writer)) {
size_t bytes_written = GPR_MIN(write_length, handler->buffer_size - offset);
GPR_ASSERT(alts_write_frame_bytes(handler->writer, handler->buffer + offset,
&bytes_written));
offset += bytes_written;
}
GPR_ASSERT(alts_is_frame_writer_done(handler->writer));
GPR_ASSERT(handler->buffer_size == offset);
}
static size_t deframe(frame_handler* handler, unsigned char* bytes,
size_t read_length) {
GPR_ASSERT(alts_reset_frame_reader(handler->reader, bytes));
size_t offset = 0;
while (offset < handler->buffer_size &&
!alts_is_frame_reader_done(handler->reader)) {
size_t bytes_read = GPR_MIN(read_length, handler->buffer_size - offset);
GPR_ASSERT(alts_read_frame_bytes(handler->reader, handler->buffer + offset,
&bytes_read));
offset += bytes_read;
}
GPR_ASSERT(alts_is_frame_reader_done(handler->reader));
GPR_ASSERT(handler->buffer_size == offset);
return offset - handler->reader->header_bytes_read;
}
static void frame_n_deframe(frame_handler* handler, unsigned char* payload,
size_t payload_length, size_t write_length,
size_t read_length) {
frame(handler, payload, payload_length, write_length);
unsigned char* bytes =
static_cast<unsigned char*>(gpr_malloc(kFrameHandlerTestBufferSize));
size_t deframed_payload_length = deframe(handler, bytes, read_length);
GPR_ASSERT(payload_length == deframed_payload_length);
GPR_ASSERT(memcmp(payload, bytes, payload_length) == 0);
gpr_free(bytes);
}
static void frame_handler_test_frame_deframe() {
unsigned char payload[] = "hello world";
size_t payload_length = strlen((char*)payload) + 1;
frame_handler* handler = create_frame_handler();
frame_n_deframe(handler, payload, payload_length,
frame_length(payload_length), frame_length(payload_length));
destroy_frame_handler(handler);
}
static void frame_handler_test_small_buffer() {
unsigned char payload[] = "hello world";
size_t payload_length = strlen(reinterpret_cast<char*>(payload)) + 1;
frame_handler* handler = create_frame_handler();
frame_n_deframe(handler, payload, payload_length, 1, 1);
destroy_frame_handler(handler);
}
static void frame_handler_test_null_input_stream() {
frame_handler* handler = create_frame_handler();
GPR_ASSERT(!alts_reset_frame_writer(handler->writer, nullptr, 0));
destroy_frame_handler(handler);
}
static void frame_handler_test_bad_input_length() {
unsigned char payload[] = "hello world";
frame_handler* handler = create_frame_handler();
GPR_ASSERT(!alts_reset_frame_writer(handler->writer, payload, SIZE_MAX));
destroy_frame_handler(handler);
}
static void frame_handler_test_null_writer_byte_length() {
unsigned char payload[] = "hello world";
size_t payload_length = strlen(reinterpret_cast<char*>(payload)) + 1;
frame_handler* handler = create_frame_handler();
GPR_ASSERT(alts_reset_frame_writer(handler->writer, payload, payload_length));
GPR_ASSERT(
!alts_write_frame_bytes(handler->writer, handler->buffer, nullptr));
destroy_frame_handler(handler);
}
static void frame_handler_test_null_writer_bytes() {
unsigned char payload[] = "hello world";
size_t payload_length = strlen(reinterpret_cast<char*>(payload)) + 1;
frame_handler* handler = create_frame_handler();
GPR_ASSERT(alts_reset_frame_writer(handler->writer, payload, payload_length));
GPR_ASSERT(
!alts_write_frame_bytes(handler->writer, nullptr, &payload_length));
destroy_frame_handler(handler);
}
static void frame_handler_test_bad_frame_length() {
unsigned char payload[] = "hello world";
size_t payload_length = strlen(reinterpret_cast<char*>(payload)) + 1;
frame_handler* handler = create_frame_handler();
frame(handler, payload, payload_length, payload_length);
memset(handler->buffer, 0x00, kFrameLengthFieldSize);
unsigned char* bytes =
static_cast<unsigned char*>(gpr_malloc(kFrameHandlerTestBufferSize));
GPR_ASSERT(alts_reset_frame_reader(handler->reader, bytes));
size_t bytes_read = handler->buffer_size;
GPR_ASSERT(
!alts_read_frame_bytes(handler->reader, handler->buffer, &bytes_read));
GPR_ASSERT(alts_is_frame_reader_done(handler->reader));
GPR_ASSERT(bytes_read == 0);
gpr_free(bytes);
destroy_frame_handler(handler);
}
static void frame_handler_test_unsupported_message_type() {
unsigned char payload[] = "hello world";
size_t payload_length = strlen(reinterpret_cast<char*>(payload)) + 1;
frame_handler* handler = create_frame_handler();
frame(handler, payload, payload_length, payload_length);
memset(handler->buffer + kFrameLengthFieldSize, 0x00,
kFrameMessageTypeFieldSize);
unsigned char* bytes =
static_cast<unsigned char*>(gpr_malloc(kFrameHandlerTestBufferSize));
GPR_ASSERT(alts_reset_frame_reader(handler->reader, bytes));
size_t bytes_read = handler->buffer_size;
GPR_ASSERT(
!alts_read_frame_bytes(handler->reader, handler->buffer, &bytes_read));
GPR_ASSERT(alts_is_frame_reader_done(handler->reader));
GPR_ASSERT(bytes_read == 0);
gpr_free(bytes);
destroy_frame_handler(handler);
}
static void frame_handler_test_null_output_stream() {
unsigned char payload[] = "hello world";
size_t payload_length = strlen(reinterpret_cast<char*>(payload)) + 1;
frame_handler* handler = create_frame_handler();
frame(handler, payload, payload_length, payload_length);
GPR_ASSERT(!alts_reset_frame_reader(handler->reader, nullptr));
destroy_frame_handler(handler);
}
static void frame_handler_test_null_reader_byte_length() {
unsigned char payload[] = "hello world";
size_t payload_length = strlen(reinterpret_cast<char*>(payload)) + 1;
frame_handler* handler = create_frame_handler();
frame(handler, payload, payload_length, payload_length);
unsigned char* bytes =
static_cast<unsigned char*>(gpr_malloc(kFrameHandlerTestBufferSize));
GPR_ASSERT(alts_reset_frame_reader(handler->reader, bytes));
GPR_ASSERT(!alts_read_frame_bytes(handler->reader, handler->buffer, nullptr));
gpr_free(bytes);
destroy_frame_handler(handler);
}
static void frame_handler_test_null_reader_bytes() {
unsigned char payload[] = "hello world";
size_t payload_length = strlen(reinterpret_cast<char*>(payload)) + 1;
frame_handler* handler = create_frame_handler();
frame(handler, payload, payload_length, payload_length);
unsigned char* bytes =
static_cast<unsigned char*>(gpr_malloc(kFrameHandlerTestBufferSize));
GPR_ASSERT(alts_reset_frame_reader(handler->reader, bytes));
size_t bytes_read = handler->buffer_size;
GPR_ASSERT(!alts_read_frame_bytes(handler->reader, nullptr, &bytes_read));
gpr_free(bytes);
destroy_frame_handler(handler);
}
int main(int argc, char** argv) {
frame_handler_test_frame_deframe();
frame_handler_test_small_buffer();
frame_handler_test_null_input_stream();
frame_handler_test_bad_input_length();
frame_handler_test_null_writer_byte_length();
frame_handler_test_null_writer_bytes();
frame_handler_test_bad_frame_length();
frame_handler_test_unsupported_message_type();
frame_handler_test_null_output_stream();
frame_handler_test_null_reader_byte_length();
frame_handler_test_null_reader_bytes();
return 0;
}

@ -0,0 +1,86 @@
# Copyright 2018 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.
load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_package")
licenses(["notice"]) # Apache v2
grpc_package(name = "handshaker")
grpc_cc_library(
name = "alts_handshaker_service_api_test_lib",
srcs = ["alts_handshaker_service_api_test_lib.cc"],
hdrs = ["alts_handshaker_service_api_test_lib.h"],
deps = [
"//:alts_util",
"//:grpc",
],
)
grpc_cc_test(
name = "alts_handshaker_client_test",
srcs = ["alts_handshaker_client_test.cc"],
language = "C++",
deps = [
":alts_handshaker_service_api_test_lib",
"//:tsi",
"//:tsi_interface",
"//:grpc",
],
)
grpc_cc_test(
name = "alts_handshaker_service_api_test",
srcs = ["alts_handshaker_service_api_test.cc"],
language = "C++",
deps = [
":alts_handshaker_service_api_test_lib",
"//:grpc",
],
)
grpc_cc_test(
name = "alts_tsi_handshaker_test",
srcs = ["alts_tsi_handshaker_test.cc"],
language = "C++",
deps = [
":alts_handshaker_service_api_test_lib",
"//:gpr",
"//:gpr_base",
"//:grpc",
"//:tsi",
],
)
grpc_cc_test(
name = "alts_tsi_utils_test",
srcs = ["alts_tsi_utils_test.cc"],
language = "C++",
deps = [
":alts_handshaker_service_api_test_lib",
"//:grpc",
"//:tsi",
],
)
grpc_cc_test(
name = "transport_security_common_api_test",
srcs = ["transport_security_common_api_test.cc"],
language = "C++",
deps = [
"//:alts_util",
"//:grpc",
],
)

@ -0,0 +1,412 @@
/*
*
* Copyright 2018 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 <grpc/grpc.h>
#include "src/core/tsi/alts/handshaker/alts_handshaker_client.h"
#include "src/core/tsi/alts/handshaker/alts_tsi_event.h"
#include "src/core/tsi/alts/handshaker/alts_tsi_handshaker.h"
#include "src/core/tsi/transport_security.h"
#include "src/core/tsi/transport_security_interface.h"
#include "test/core/tsi/alts/handshaker/alts_handshaker_service_api_test_lib.h"
#define ALTS_HANDSHAKER_CLIENT_TEST_OUT_FRAME "Hello Google"
#define ALTS_HANDSHAKER_CLIENT_TEST_HANDSHAKER_SERVICE_URL "lame"
#define ALTS_HANDSHAKER_CLIENT_TEST_TARGET_NAME "bigtable.google.api.com"
#define ALTS_HANDSHAKER_CLIENT_TEST_TARGET_SERVICE_ACCOUNT1 "A@google.com"
#define ALTS_HANDSHAKER_CLIENT_TEST_TARGET_SERVICE_ACCOUNT2 "B@google.com"
const size_t kHandshakerClientOpNum = 4;
const size_t kMaxRpcVersionMajor = 3;
const size_t kMaxRpcVersionMinor = 2;
const size_t kMinRpcVersionMajor = 2;
const size_t kMinRpcVersionMinor = 1;
using grpc_core::internal::alts_handshaker_client_set_grpc_caller_for_testing;
typedef struct alts_handshaker_client_test_config {
grpc_channel* channel;
grpc_completion_queue* cq;
alts_handshaker_client* client;
grpc_slice out_frame;
} alts_handshaker_client_test_config;
static alts_tsi_event* alts_tsi_event_create_for_testing(bool is_client) {
alts_tsi_event* e = static_cast<alts_tsi_event*>(gpr_zalloc(sizeof(*e)));
grpc_metadata_array_init(&e->initial_metadata);
grpc_metadata_array_init(&e->trailing_metadata);
e->options = is_client ? grpc_alts_credentials_client_options_create()
: grpc_alts_credentials_server_options_create();
if (is_client) {
grpc_alts_credentials_client_options_add_target_service_account(
reinterpret_cast<grpc_alts_credentials_client_options*>(e->options),
ALTS_HANDSHAKER_CLIENT_TEST_TARGET_SERVICE_ACCOUNT1);
grpc_alts_credentials_client_options_add_target_service_account(
reinterpret_cast<grpc_alts_credentials_client_options*>(e->options),
ALTS_HANDSHAKER_CLIENT_TEST_TARGET_SERVICE_ACCOUNT2);
}
grpc_gcp_rpc_protocol_versions* versions = &e->options->rpc_versions;
GPR_ASSERT(grpc_gcp_rpc_protocol_versions_set_max(
versions, kMaxRpcVersionMajor, kMaxRpcVersionMinor));
GPR_ASSERT(grpc_gcp_rpc_protocol_versions_set_min(
versions, kMinRpcVersionMajor, kMinRpcVersionMinor));
e->target_name =
grpc_slice_from_static_string(ALTS_HANDSHAKER_CLIENT_TEST_TARGET_NAME);
return e;
}
static void validate_rpc_protocol_versions(
grpc_gcp_rpc_protocol_versions* versions) {
GPR_ASSERT(versions != nullptr);
GPR_ASSERT(versions->max_rpc_version.major == kMaxRpcVersionMajor);
GPR_ASSERT(versions->max_rpc_version.minor == kMaxRpcVersionMinor);
GPR_ASSERT(versions->min_rpc_version.major == kMinRpcVersionMajor);
GPR_ASSERT(versions->min_rpc_version.minor == kMinRpcVersionMinor);
}
static void validate_target_identities(
const repeated_field* target_identity_head) {
grpc_gcp_identity* target_identity1 = static_cast<grpc_gcp_identity*>(
const_cast<void*>(target_identity_head->next->data));
grpc_gcp_identity* target_identity2 = static_cast<grpc_gcp_identity*>(
const_cast<void*>(target_identity_head->data));
grpc_slice* service_account1 =
static_cast<grpc_slice*>(target_identity1->service_account.arg);
grpc_slice* service_account2 =
static_cast<grpc_slice*>(target_identity2->service_account.arg);
GPR_ASSERT(memcmp(GRPC_SLICE_START_PTR(*service_account1),
ALTS_HANDSHAKER_CLIENT_TEST_TARGET_SERVICE_ACCOUNT1,
GRPC_SLICE_LENGTH(*service_account1)) == 0);
GPR_ASSERT(strlen(ALTS_HANDSHAKER_CLIENT_TEST_TARGET_SERVICE_ACCOUNT1) ==
GRPC_SLICE_LENGTH(*service_account1));
GPR_ASSERT(memcmp(GRPC_SLICE_START_PTR(*service_account2),
ALTS_HANDSHAKER_CLIENT_TEST_TARGET_SERVICE_ACCOUNT2,
GRPC_SLICE_LENGTH(*service_account2)) == 0);
GPR_ASSERT(strlen(ALTS_HANDSHAKER_CLIENT_TEST_TARGET_SERVICE_ACCOUNT2) ==
GRPC_SLICE_LENGTH(*service_account2));
}
/**
* Validate if grpc operation data is correctly populated with the fields of
* ALTS TSI event.
*/
static bool validate_op(alts_tsi_event* event, const grpc_op* op, size_t nops,
bool is_start) {
GPR_ASSERT(event != nullptr && op != nullptr && nops != 0);
bool ok = true;
grpc_op* start_op = const_cast<grpc_op*>(op);
if (is_start) {
ok &= (op->op == GRPC_OP_SEND_INITIAL_METADATA);
ok &= (op->data.send_initial_metadata.count == 0);
op++;
GPR_ASSERT((size_t)(op - start_op) <= kHandshakerClientOpNum);
ok &= (op->op == GRPC_OP_RECV_INITIAL_METADATA);
ok &= (op->data.recv_initial_metadata.recv_initial_metadata ==
&event->initial_metadata);
op++;
GPR_ASSERT((size_t)(op - start_op) <= kHandshakerClientOpNum);
}
ok &= (op->op == GRPC_OP_SEND_MESSAGE);
ok &= (op->data.send_message.send_message == event->send_buffer);
op++;
GPR_ASSERT((size_t)(op - start_op) <= kHandshakerClientOpNum);
ok &= (op->op == GRPC_OP_RECV_MESSAGE);
ok &= (op->data.recv_message.recv_message == &event->recv_buffer);
op++;
GPR_ASSERT((size_t)(op - start_op) <= kHandshakerClientOpNum);
return ok;
}
static grpc_gcp_handshaker_req* deserialize_handshaker_req(
grpc_gcp_handshaker_req_type type, grpc_byte_buffer* buffer) {
GPR_ASSERT(buffer != nullptr);
grpc_gcp_handshaker_req* req = grpc_gcp_handshaker_decoded_req_create(type);
grpc_byte_buffer_reader bbr;
GPR_ASSERT(grpc_byte_buffer_reader_init(&bbr, buffer));
grpc_slice slice = grpc_byte_buffer_reader_readall(&bbr);
GPR_ASSERT(grpc_gcp_handshaker_req_decode(slice, req));
grpc_slice_unref(slice);
grpc_byte_buffer_reader_destroy(&bbr);
return req;
}
/**
* A mock grpc_caller used to check if client_start, server_start, and next
* operations correctly handle invalid arguments. It should not be called.
*/
static grpc_call_error check_must_not_be_called(grpc_call* call,
const grpc_op* ops, size_t nops,
void* tag) {
GPR_ASSERT(0);
}
/**
* A mock grpc_caller used to check correct execution of client_start operation.
* It checks if the client_start handshaker request is populated with correct
* handshake_security_protocol, application_protocol, and record_protocol, and
* op is correctly populated.
*/
static grpc_call_error check_client_start_success(grpc_call* call,
const grpc_op* op,
size_t nops, void* tag) {
alts_tsi_event* event = static_cast<alts_tsi_event*>(tag);
grpc_gcp_handshaker_req* req =
deserialize_handshaker_req(CLIENT_START_REQ, event->send_buffer);
GPR_ASSERT(req->client_start.handshake_security_protocol ==
grpc_gcp_HandshakeProtocol_ALTS);
const void* data = (static_cast<repeated_field*>(
req->client_start.application_protocols.arg))
->data;
GPR_ASSERT(data != nullptr);
grpc_slice* application_protocol = (grpc_slice*)data;
data = (static_cast<repeated_field*>(req->client_start.record_protocols.arg))
->data;
grpc_slice* record_protocol = (grpc_slice*)data;
GPR_ASSERT(memcmp(GRPC_SLICE_START_PTR(*application_protocol),
ALTS_APPLICATION_PROTOCOL,
GRPC_SLICE_LENGTH(*application_protocol)) == 0);
GPR_ASSERT(memcmp(GRPC_SLICE_START_PTR(*record_protocol),
ALTS_RECORD_PROTOCOL,
GRPC_SLICE_LENGTH(*record_protocol)) == 0);
validate_rpc_protocol_versions(&req->client_start.rpc_versions);
validate_target_identities(
static_cast<repeated_field*>(req->client_start.target_identities.arg));
grpc_slice* target_name =
static_cast<grpc_slice*>(req->client_start.target_name.arg);
GPR_ASSERT(memcmp(GRPC_SLICE_START_PTR(*target_name),
ALTS_HANDSHAKER_CLIENT_TEST_TARGET_NAME,
GRPC_SLICE_LENGTH(*target_name)) == 0);
GPR_ASSERT(GRPC_SLICE_LENGTH(*target_name) ==
strlen(ALTS_HANDSHAKER_CLIENT_TEST_TARGET_NAME));
GPR_ASSERT(validate_op(event, op, nops, true /* is_start */));
grpc_gcp_handshaker_req_destroy(req);
return GRPC_CALL_OK;
}
/**
* A mock grpc_caller used to check correct execution of server_start operation.
* It checks if the server_start handshaker request is populated with correct
* handshake_security_protocol, application_protocol, and record_protocol, and
* op is correctly populated.
*/
static grpc_call_error check_server_start_success(grpc_call* call,
const grpc_op* op,
size_t nops, void* tag) {
alts_tsi_event* event = static_cast<alts_tsi_event*>(tag);
grpc_gcp_handshaker_req* req =
deserialize_handshaker_req(SERVER_START_REQ, event->send_buffer);
const void* data = (static_cast<repeated_field*>(
req->server_start.application_protocols.arg))
->data;
GPR_ASSERT(data != nullptr);
grpc_slice* application_protocol = (grpc_slice*)data;
GPR_ASSERT(memcmp(GRPC_SLICE_START_PTR(*application_protocol),
ALTS_APPLICATION_PROTOCOL,
GRPC_SLICE_LENGTH(*application_protocol)) == 0);
GPR_ASSERT(req->server_start.handshake_parameters_count == 1);
GPR_ASSERT(req->server_start.handshake_parameters[0].key ==
grpc_gcp_HandshakeProtocol_ALTS);
data = (static_cast<repeated_field*>(req->server_start.handshake_parameters[0]
.value.record_protocols.arg))
->data;
GPR_ASSERT(data != nullptr);
grpc_slice* record_protocol = (grpc_slice*)data;
GPR_ASSERT(memcmp(GRPC_SLICE_START_PTR(*record_protocol),
ALTS_RECORD_PROTOCOL,
GRPC_SLICE_LENGTH(*record_protocol)) == 0);
validate_rpc_protocol_versions(&req->server_start.rpc_versions);
GPR_ASSERT(validate_op(event, op, nops, true /* is_start */));
grpc_gcp_handshaker_req_destroy(req);
return GRPC_CALL_OK;
}
/**
* A mock grpc_caller used to check correct execution of next operation. It
* checks if the next handshaker request is populated with correct information,
* and op is correctly populated.
*/
static grpc_call_error check_next_success(grpc_call* call, const grpc_op* op,
size_t nops, void* tag) {
alts_tsi_event* event = static_cast<alts_tsi_event*>(tag);
grpc_gcp_handshaker_req* req =
deserialize_handshaker_req(NEXT_REQ, event->send_buffer);
grpc_slice* in_bytes = static_cast<grpc_slice*>(req->next.in_bytes.arg);
GPR_ASSERT(in_bytes != nullptr);
GPR_ASSERT(memcmp(GRPC_SLICE_START_PTR(*in_bytes),
ALTS_HANDSHAKER_CLIENT_TEST_OUT_FRAME,
GRPC_SLICE_LENGTH(*in_bytes)) == 0);
GPR_ASSERT(validate_op(event, op, nops, false /* is_start */));
grpc_gcp_handshaker_req_destroy(req);
return GRPC_CALL_OK;
}
/**
* A mock grpc_caller used to check if client_start, server_start, and next
* operations correctly handle the situation when the grpc call made to the
* handshaker service fails.
*/
static grpc_call_error check_grpc_call_failure(grpc_call* call,
const grpc_op* op, size_t nops,
void* tag) {
return GRPC_CALL_ERROR;
}
static alts_handshaker_client_test_config* create_config() {
alts_handshaker_client_test_config* config =
static_cast<alts_handshaker_client_test_config*>(
gpr_zalloc(sizeof(*config)));
config->channel = grpc_insecure_channel_create(
ALTS_HANDSHAKER_CLIENT_TEST_HANDSHAKER_SERVICE_URL, nullptr, nullptr);
config->cq = grpc_completion_queue_create_for_next(nullptr);
config->client = alts_grpc_handshaker_client_create(
config->channel, config->cq,
ALTS_HANDSHAKER_CLIENT_TEST_HANDSHAKER_SERVICE_URL);
GPR_ASSERT(config->client != nullptr);
config->out_frame =
grpc_slice_from_static_string(ALTS_HANDSHAKER_CLIENT_TEST_OUT_FRAME);
return config;
}
static void destroy_config(alts_handshaker_client_test_config* config) {
if (config == nullptr) {
return;
}
grpc_completion_queue_destroy(config->cq);
grpc_channel_destroy(config->channel);
alts_handshaker_client_destroy(config->client);
grpc_slice_unref(config->out_frame);
gpr_free(config);
}
static void schedule_request_invalid_arg_test() {
/* Initialization. */
alts_handshaker_client_test_config* config = create_config();
alts_tsi_event* event = nullptr;
/* Tests. */
alts_handshaker_client_set_grpc_caller_for_testing(config->client,
check_must_not_be_called);
event = alts_tsi_event_create_for_testing(true /* is_client */);
/* Check client_start. */
GPR_ASSERT(alts_handshaker_client_start_client(nullptr, event) ==
TSI_INVALID_ARGUMENT);
GPR_ASSERT(alts_handshaker_client_start_client(config->client, nullptr) ==
TSI_INVALID_ARGUMENT);
/* Check server_start. */
GPR_ASSERT(alts_handshaker_client_start_server(
config->client, event, nullptr) == TSI_INVALID_ARGUMENT);
GPR_ASSERT(alts_handshaker_client_start_server(config->client, nullptr,
&config->out_frame) ==
TSI_INVALID_ARGUMENT);
GPR_ASSERT(alts_handshaker_client_start_server(
nullptr, event, &config->out_frame) == TSI_INVALID_ARGUMENT);
/* Check next. */
GPR_ASSERT(alts_handshaker_client_next(config->client, event, nullptr) ==
TSI_INVALID_ARGUMENT);
GPR_ASSERT(alts_handshaker_client_next(config->client, nullptr,
&config->out_frame) ==
TSI_INVALID_ARGUMENT);
GPR_ASSERT(alts_handshaker_client_next(nullptr, event, &config->out_frame) ==
TSI_INVALID_ARGUMENT);
/* Cleanup. */
alts_tsi_event_destroy(event);
destroy_config(config);
}
static void schedule_request_success_test() {
/* Initialization. */
alts_handshaker_client_test_config* config = create_config();
alts_tsi_event* event = nullptr;
/* Check client_start success. */
alts_handshaker_client_set_grpc_caller_for_testing(
config->client, check_client_start_success);
event = alts_tsi_event_create_for_testing(true /* is_client. */);
GPR_ASSERT(alts_handshaker_client_start_client(config->client, event) ==
TSI_OK);
alts_tsi_event_destroy(event);
/* Check server_start success. */
alts_handshaker_client_set_grpc_caller_for_testing(
config->client, check_server_start_success);
event = alts_tsi_event_create_for_testing(false /* is_client. */);
GPR_ASSERT(alts_handshaker_client_start_server(config->client, event,
&config->out_frame) == TSI_OK);
alts_tsi_event_destroy(event);
/* Check next success. */
alts_handshaker_client_set_grpc_caller_for_testing(config->client,
check_next_success);
event = alts_tsi_event_create_for_testing(true /* is_client. */);
GPR_ASSERT(alts_handshaker_client_next(config->client, event,
&config->out_frame) == TSI_OK);
alts_tsi_event_destroy(event);
/* Cleanup. */
destroy_config(config);
}
static void schedule_request_grpc_call_failure_test() {
/* Initialization. */
alts_handshaker_client_test_config* config = create_config();
alts_tsi_event* event = nullptr;
/* Check client_start failure. */
alts_handshaker_client_set_grpc_caller_for_testing(config->client,
check_grpc_call_failure);
event = alts_tsi_event_create_for_testing(true /* is_client. */);
GPR_ASSERT(alts_handshaker_client_start_client(config->client, event) ==
TSI_INTERNAL_ERROR);
alts_tsi_event_destroy(event);
/* Check server_start failure. */
event = alts_tsi_event_create_for_testing(false /* is_client. */);
GPR_ASSERT(alts_handshaker_client_start_server(config->client, event,
&config->out_frame) ==
TSI_INTERNAL_ERROR);
alts_tsi_event_destroy(event);
/* Check next failure. */
event = alts_tsi_event_create_for_testing(true /* is_cleint. */);
GPR_ASSERT(
alts_handshaker_client_next(config->client, event, &config->out_frame) ==
TSI_INTERNAL_ERROR);
alts_tsi_event_destroy(event);
/* Cleanup. */
destroy_config(config);
}
int main(int argc, char** argv) {
/* Initialization. */
grpc_init();
/* Tests. */
schedule_request_invalid_arg_test();
schedule_request_success_test();
schedule_request_grpc_call_failure_test();
/* Cleanup. */
grpc_shutdown();
return 0;
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save