1
#include "source/extensions/transport_sockets/alts/tsi_frame_protector.h"
2

            
3
#include "source/common/buffer/buffer_impl.h"
4
#include "source/common/common/assert.h"
5

            
6
#include "src/core/lib/iomgr/exec_ctx.h"
7
#include "src/core/tsi/transport_security_grpc.h"
8
#include "src/core/tsi/transport_security_interface.h"
9

            
10
namespace Envoy {
11
namespace Extensions {
12
namespace TransportSockets {
13
namespace Alts {
14

            
15
TsiFrameProtector::TsiFrameProtector(CFrameProtectorPtr&& frame_protector)
16
62
    : frame_protector_(std::move(frame_protector)) {}
17

            
18
24
tsi_result TsiFrameProtector::protect(const grpc_slice& input_slice, Buffer::Instance& output) {
19
24
  ASSERT(frame_protector_);
20

            
21
24
  if (GRPC_SLICE_LENGTH(input_slice) == 0) {
22
1
    return TSI_OK;
23
1
  }
24

            
25
23
  grpc_core::ExecCtx exec_ctx;
26

            
27
23
  grpc_slice_buffer message_buffer;
28
23
  grpc_slice_buffer_init(&message_buffer);
29
23
  grpc_slice_buffer_add(&message_buffer, input_slice);
30

            
31
23
  grpc_slice_buffer protected_buffer;
32
23
  grpc_slice_buffer_init(&protected_buffer);
33

            
34
23
  tsi_result result = tsi_zero_copy_grpc_protector_protect(frame_protector_.get(), &message_buffer,
35
23
                                                           &protected_buffer);
36

            
37
23
  if (result != TSI_OK) {
38
1
    ASSERT(result != TSI_INVALID_ARGUMENT && result != TSI_UNIMPLEMENTED);
39
1
    grpc_slice_buffer_destroy(&message_buffer);
40
1
    grpc_slice_buffer_destroy(&protected_buffer);
41
1
    return result;
42
1
  }
43

            
44
22
  const size_t protected_data_length = protected_buffer.length;
45
22
  char* protected_data = new char[protected_data_length];
46

            
47
22
  grpc_slice_buffer_move_first_into_buffer(&protected_buffer, protected_data_length,
48
22
                                           protected_data);
49

            
50
22
  auto fragment = new Buffer::BufferFragmentImpl(
51
22
      protected_data, protected_data_length,
52
22
      [protected_data](const void*, size_t,
53
22
                       const Envoy::Buffer::BufferFragmentImpl* this_fragment) {
54
22
        delete[] protected_data;
55
22
        delete this_fragment;
56
22
      });
57

            
58
22
  output.addBufferFragment(*fragment);
59

            
60
22
  grpc_slice_buffer_destroy(&message_buffer);
61
22
  grpc_slice_buffer_destroy(&protected_buffer);
62

            
63
22
  return TSI_OK;
64
23
}
65

            
66
23
tsi_result TsiFrameProtector::unprotect(Buffer::Instance& input, Buffer::Instance& output) {
67
23
  ASSERT(frame_protector_);
68

            
69
23
  if (input.length() == 0) {
70
1
    return TSI_OK;
71
1
  }
72

            
73
22
  grpc_core::ExecCtx exec_ctx;
74
22
  grpc_slice input_slice = grpc_slice_from_copied_buffer(
75
22
      reinterpret_cast<char*>(input.linearize(input.length())), input.length());
76

            
77
22
  grpc_slice_buffer protected_buffer;
78
22
  grpc_slice_buffer_init(&protected_buffer);
79
22
  grpc_slice_buffer_add(&protected_buffer, input_slice);
80

            
81
22
  grpc_slice_buffer unprotected_buffer;
82
22
  grpc_slice_buffer_init(&unprotected_buffer);
83

            
84
22
  tsi_result result = tsi_zero_copy_grpc_protector_unprotect(
85
22
      frame_protector_.get(), &protected_buffer, &unprotected_buffer, nullptr);
86

            
87
22
  if (result != TSI_OK) {
88
2
    ASSERT(result != TSI_INVALID_ARGUMENT && result != TSI_UNIMPLEMENTED);
89
2
    grpc_slice_buffer_destroy(&protected_buffer);
90
2
    grpc_slice_buffer_destroy(&unprotected_buffer);
91
2
    return result;
92
2
  }
93

            
94
20
  const size_t unprotected_data_length = unprotected_buffer.length;
95
20
  char* unprotected_data = new char[unprotected_data_length];
96

            
97
20
  grpc_slice_buffer_move_first_into_buffer(&unprotected_buffer, unprotected_data_length,
98
20
                                           unprotected_data);
99

            
100
20
  auto fragment = new Buffer::BufferFragmentImpl(
101
20
      unprotected_data, unprotected_data_length,
102
20
      [unprotected_data](const void*, size_t,
103
20
                         const Envoy::Buffer::BufferFragmentImpl* this_fragment) {
104
20
        delete[] unprotected_data;
105
20
        delete this_fragment;
106
20
      });
107

            
108
20
  output.addBufferFragment(*fragment);
109
20
  input.drain(input.length());
110

            
111
20
  grpc_slice_buffer_destroy(&protected_buffer);
112
20
  grpc_slice_buffer_destroy(&unprotected_buffer);
113

            
114
20
  return TSI_OK;
115
22
}
116

            
117
} // namespace Alts
118
} // namespace TransportSockets
119
} // namespace Extensions
120
} // namespace Envoy