Imported Upstream version 1.27.0
[platform/upstream/grpc.git] / test / core / tsi / alts / zero_copy_frame_protector / alts_zero_copy_grpc_protector_test.cc
1 /*
2  *
3  * Copyright 2018 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18
19 #include <grpc/slice_buffer.h>
20 #include <grpc/support/alloc.h>
21 #include <grpc/support/log.h>
22
23 #include "src/core/lib/iomgr/exec_ctx.h"
24 #include "src/core/lib/slice/slice_internal.h"
25 #include "src/core/tsi/alts/crypt/gsec.h"
26 #include "src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.h"
27 #include "src/core/tsi/transport_security_grpc.h"
28 #include "test/core/tsi/alts/crypt/gsec_test_util.h"
29 #include "test/core/util/test_config.h"
30
31 /* TODO: tests zero_copy_grpc_protector under TSI test library, which
32  * has more comprehensive tests.  */
33
34 constexpr size_t kSealRepeatTimes = 50;
35 constexpr size_t kSmallBufferSize = 16;
36 constexpr size_t kLargeBufferSize = 16384;
37 constexpr size_t kChannelMaxSize = 2048;
38 constexpr size_t kChannelMinSize = 128;
39
40 /* Test fixtures for each test cases.  */
41 struct alts_zero_copy_grpc_protector_test_fixture {
42   tsi_zero_copy_grpc_protector* client;
43   tsi_zero_copy_grpc_protector* server;
44 };
45
46 /* Test input variables for protect/unprotect operations.  */
47 struct alts_zero_copy_grpc_protector_test_var {
48   grpc_slice_buffer original_sb;
49   grpc_slice_buffer duplicate_sb;
50   grpc_slice_buffer staging_sb;
51   grpc_slice_buffer protected_sb;
52   grpc_slice_buffer unprotected_sb;
53 };
54
55 /* --- Test utility functions. --- */
56
57 static void create_random_slice_buffer(grpc_slice_buffer* sb,
58                                        grpc_slice_buffer* dup_sb,
59                                        size_t length) {
60   GPR_ASSERT(sb != nullptr);
61   GPR_ASSERT(dup_sb != nullptr);
62   GPR_ASSERT(length > 0);
63   grpc_slice slice = GRPC_SLICE_MALLOC(length);
64   gsec_test_random_bytes(GRPC_SLICE_START_PTR(slice), length);
65   grpc_slice_buffer_add(sb, grpc_slice_ref(slice));
66   grpc_slice_buffer_add(dup_sb, slice);
67 }
68
69 static uint8_t* pointer_to_nth_byte(grpc_slice_buffer* sb, size_t index) {
70   GPR_ASSERT(sb != nullptr);
71   GPR_ASSERT(index < sb->length);
72   for (size_t i = 0; i < sb->count; i++) {
73     if (index < GRPC_SLICE_LENGTH(sb->slices[i])) {
74       return GRPC_SLICE_START_PTR(sb->slices[i]) + index;
75     } else {
76       index -= GRPC_SLICE_LENGTH(sb->slices[i]);
77     }
78   }
79   return nullptr;
80 }
81
82 /* Checks if two slice buffer contents are the same. It is not super efficient,
83  * but OK for testing.  */
84 static bool are_slice_buffers_equal(grpc_slice_buffer* first,
85                                     grpc_slice_buffer* second) {
86   GPR_ASSERT(first != nullptr);
87   GPR_ASSERT(second != nullptr);
88   if (first->length != second->length) {
89     return false;
90   }
91   for (size_t i = 0; i < first->length; i++) {
92     uint8_t* first_ptr = pointer_to_nth_byte(first, i);
93     uint8_t* second_ptr = pointer_to_nth_byte(second, i);
94     GPR_ASSERT(first_ptr != nullptr && second_ptr != nullptr);
95     if ((*first_ptr) != (*second_ptr)) {
96       return false;
97     }
98   }
99   return true;
100 }
101
102 static alts_zero_copy_grpc_protector_test_fixture*
103 alts_zero_copy_grpc_protector_test_fixture_create(bool rekey,
104                                                   bool integrity_only,
105                                                   bool enable_extra_copy) {
106   alts_zero_copy_grpc_protector_test_fixture* fixture =
107       static_cast<alts_zero_copy_grpc_protector_test_fixture*>(
108           gpr_zalloc(sizeof(alts_zero_copy_grpc_protector_test_fixture)));
109   grpc_core::ExecCtx exec_ctx;
110   size_t key_length = rekey ? kAes128GcmRekeyKeyLength : kAes128GcmKeyLength;
111   uint8_t* key;
112   size_t max_protected_frame_size = 1024;
113   size_t actual_max_protected_frame_size;
114   gsec_test_random_array(&key, key_length);
115   GPR_ASSERT(alts_zero_copy_grpc_protector_create(
116                  key, key_length, rekey, /*is_client=*/true, integrity_only,
117                  enable_extra_copy, &max_protected_frame_size,
118                  &fixture->client) == TSI_OK);
119   GPR_ASSERT(tsi_zero_copy_grpc_protector_max_frame_size(
120                  fixture->client, &actual_max_protected_frame_size) == TSI_OK);
121   GPR_ASSERT(actual_max_protected_frame_size == max_protected_frame_size);
122   GPR_ASSERT(alts_zero_copy_grpc_protector_create(
123                  key, key_length, rekey, /*is_client=*/false, integrity_only,
124                  enable_extra_copy, &max_protected_frame_size,
125                  &fixture->server) == TSI_OK);
126   GPR_ASSERT(tsi_zero_copy_grpc_protector_max_frame_size(
127                  fixture->server, &actual_max_protected_frame_size) == TSI_OK);
128   GPR_ASSERT(actual_max_protected_frame_size == max_protected_frame_size);
129   gpr_free(key);
130   grpc_core::ExecCtx::Get()->Flush();
131   return fixture;
132 }
133
134 static void alts_zero_copy_grpc_protector_test_fixture_destroy(
135     alts_zero_copy_grpc_protector_test_fixture* fixture) {
136   if (fixture == nullptr) {
137     return;
138   }
139   grpc_core::ExecCtx exec_ctx;
140   tsi_zero_copy_grpc_protector_destroy(fixture->client);
141   tsi_zero_copy_grpc_protector_destroy(fixture->server);
142   grpc_core::ExecCtx::Get()->Flush();
143   gpr_free(fixture);
144 }
145
146 static alts_zero_copy_grpc_protector_test_var*
147 alts_zero_copy_grpc_protector_test_var_create() {
148   alts_zero_copy_grpc_protector_test_var* var =
149       static_cast<alts_zero_copy_grpc_protector_test_var*>(
150           gpr_zalloc(sizeof(alts_zero_copy_grpc_protector_test_var)));
151   grpc_slice_buffer_init(&var->original_sb);
152   grpc_slice_buffer_init(&var->duplicate_sb);
153   grpc_slice_buffer_init(&var->staging_sb);
154   grpc_slice_buffer_init(&var->protected_sb);
155   grpc_slice_buffer_init(&var->unprotected_sb);
156   return var;
157 }
158
159 static void alts_zero_copy_grpc_protector_test_var_destroy(
160     alts_zero_copy_grpc_protector_test_var* var) {
161   if (var == nullptr) {
162     return;
163   }
164   grpc_slice_buffer_destroy_internal(&var->original_sb);
165   grpc_slice_buffer_destroy_internal(&var->duplicate_sb);
166   grpc_slice_buffer_destroy_internal(&var->staging_sb);
167   grpc_slice_buffer_destroy_internal(&var->protected_sb);
168   grpc_slice_buffer_destroy_internal(&var->unprotected_sb);
169   gpr_free(var);
170 }
171
172 /* --- ALTS zero-copy protector tests. --- */
173
174 static void seal_unseal_small_buffer(tsi_zero_copy_grpc_protector* sender,
175                                      tsi_zero_copy_grpc_protector* receiver) {
176   grpc_core::ExecCtx exec_ctx;
177   for (size_t i = 0; i < kSealRepeatTimes; i++) {
178     alts_zero_copy_grpc_protector_test_var* var =
179         alts_zero_copy_grpc_protector_test_var_create();
180     /* Creates a random small slice buffer and calls protect().  */
181     create_random_slice_buffer(&var->original_sb, &var->duplicate_sb,
182                                kSmallBufferSize);
183     GPR_ASSERT(tsi_zero_copy_grpc_protector_protect(
184                    sender, &var->original_sb, &var->protected_sb) == TSI_OK);
185     /* Splits protected slice buffer into two: first one is staging_sb, and
186      * second one is protected_sb.  */
187     uint32_t staging_sb_size =
188         gsec_test_bias_random_uint32(
189             static_cast<uint32_t>(var->protected_sb.length - 1)) +
190         1;
191     grpc_slice_buffer_move_first(&var->protected_sb, staging_sb_size,
192                                  &var->staging_sb);
193     /* Unprotects one by one.  */
194     GPR_ASSERT(tsi_zero_copy_grpc_protector_unprotect(
195                    receiver, &var->staging_sb, &var->unprotected_sb) == TSI_OK);
196     GPR_ASSERT(var->unprotected_sb.length == 0);
197     GPR_ASSERT(tsi_zero_copy_grpc_protector_unprotect(
198                    receiver, &var->protected_sb, &var->unprotected_sb) ==
199                TSI_OK);
200     GPR_ASSERT(
201         are_slice_buffers_equal(&var->unprotected_sb, &var->duplicate_sb));
202     alts_zero_copy_grpc_protector_test_var_destroy(var);
203   }
204   grpc_core::ExecCtx::Get()->Flush();
205 }
206
207 static void seal_unseal_large_buffer(tsi_zero_copy_grpc_protector* sender,
208                                      tsi_zero_copy_grpc_protector* receiver) {
209   grpc_core::ExecCtx exec_ctx;
210   for (size_t i = 0; i < kSealRepeatTimes; i++) {
211     alts_zero_copy_grpc_protector_test_var* var =
212         alts_zero_copy_grpc_protector_test_var_create();
213     /* Creates a random large slice buffer and calls protect().  */
214     create_random_slice_buffer(&var->original_sb, &var->duplicate_sb,
215                                kLargeBufferSize);
216     GPR_ASSERT(tsi_zero_copy_grpc_protector_protect(
217                    sender, &var->original_sb, &var->protected_sb) == TSI_OK);
218     /* Splits protected slice buffer into multiple pieces. Receiver unprotects
219      * each slice buffer one by one.  */
220     uint32_t channel_size = gsec_test_bias_random_uint32(static_cast<uint32_t>(
221                                 kChannelMaxSize + 1 - kChannelMinSize)) +
222                             static_cast<uint32_t>(kChannelMinSize);
223     while (var->protected_sb.length > channel_size) {
224       grpc_slice_buffer_reset_and_unref_internal(&var->staging_sb);
225       grpc_slice_buffer_move_first(&var->protected_sb, channel_size,
226                                    &var->staging_sb);
227       GPR_ASSERT(tsi_zero_copy_grpc_protector_unprotect(
228                      receiver, &var->staging_sb, &var->unprotected_sb) ==
229                  TSI_OK);
230     }
231     GPR_ASSERT(tsi_zero_copy_grpc_protector_unprotect(
232                    receiver, &var->protected_sb, &var->unprotected_sb) ==
233                TSI_OK);
234     GPR_ASSERT(
235         are_slice_buffers_equal(&var->unprotected_sb, &var->duplicate_sb));
236     alts_zero_copy_grpc_protector_test_var_destroy(var);
237   }
238   grpc_core::ExecCtx::Get()->Flush();
239 }
240
241 /* --- Test cases. --- */
242
243 static void alts_zero_copy_protector_seal_unseal_small_buffer_tests(
244     bool enable_extra_copy) {
245   alts_zero_copy_grpc_protector_test_fixture* fixture =
246       alts_zero_copy_grpc_protector_test_fixture_create(
247           /*rekey=*/false, /*integrity_only=*/true, enable_extra_copy);
248   seal_unseal_small_buffer(fixture->client, fixture->server);
249   seal_unseal_small_buffer(fixture->server, fixture->client);
250   alts_zero_copy_grpc_protector_test_fixture_destroy(fixture);
251
252   fixture = alts_zero_copy_grpc_protector_test_fixture_create(
253       /*rekey=*/false, /*integrity_only=*/false, enable_extra_copy);
254   seal_unseal_small_buffer(fixture->client, fixture->server);
255   seal_unseal_small_buffer(fixture->server, fixture->client);
256   alts_zero_copy_grpc_protector_test_fixture_destroy(fixture);
257
258   fixture = alts_zero_copy_grpc_protector_test_fixture_create(
259       /*rekey=*/true, /*integrity_only=*/true, enable_extra_copy);
260   seal_unseal_small_buffer(fixture->client, fixture->server);
261   seal_unseal_small_buffer(fixture->server, fixture->client);
262   alts_zero_copy_grpc_protector_test_fixture_destroy(fixture);
263
264   fixture = alts_zero_copy_grpc_protector_test_fixture_create(
265       /*rekey=*/true, /*integrity_only=*/false, enable_extra_copy);
266   seal_unseal_small_buffer(fixture->client, fixture->server);
267   seal_unseal_small_buffer(fixture->server, fixture->client);
268   alts_zero_copy_grpc_protector_test_fixture_destroy(fixture);
269 }
270
271 static void alts_zero_copy_protector_seal_unseal_large_buffer_tests(
272     bool enable_extra_copy) {
273   alts_zero_copy_grpc_protector_test_fixture* fixture =
274       alts_zero_copy_grpc_protector_test_fixture_create(
275           /*rekey=*/false, /*integrity_only=*/true, enable_extra_copy);
276   seal_unseal_large_buffer(fixture->client, fixture->server);
277   seal_unseal_large_buffer(fixture->server, fixture->client);
278   alts_zero_copy_grpc_protector_test_fixture_destroy(fixture);
279
280   fixture = alts_zero_copy_grpc_protector_test_fixture_create(
281       /*rekey=*/false, /*integrity_only=*/false, enable_extra_copy);
282   seal_unseal_large_buffer(fixture->client, fixture->server);
283   seal_unseal_large_buffer(fixture->server, fixture->client);
284   alts_zero_copy_grpc_protector_test_fixture_destroy(fixture);
285
286   fixture = alts_zero_copy_grpc_protector_test_fixture_create(
287       /*rekey=*/true, /*integrity_only=*/true, enable_extra_copy);
288   seal_unseal_large_buffer(fixture->client, fixture->server);
289   seal_unseal_large_buffer(fixture->server, fixture->client);
290   alts_zero_copy_grpc_protector_test_fixture_destroy(fixture);
291
292   fixture = alts_zero_copy_grpc_protector_test_fixture_create(
293       /*rekey=*/true, /*integrity_only=*/false, enable_extra_copy);
294   seal_unseal_large_buffer(fixture->client, fixture->server);
295   seal_unseal_large_buffer(fixture->server, fixture->client);
296   alts_zero_copy_grpc_protector_test_fixture_destroy(fixture);
297 }
298
299 int main(int argc, char** argv) {
300   grpc::testing::TestEnvironment env(argc, argv);
301   grpc_init();
302   alts_zero_copy_protector_seal_unseal_small_buffer_tests(
303       /*enable_extra_copy=*/false);
304   alts_zero_copy_protector_seal_unseal_small_buffer_tests(
305       /*enable_extra_copy=*/true);
306   alts_zero_copy_protector_seal_unseal_large_buffer_tests(
307       /*enable_extra_copy=*/false);
308   alts_zero_copy_protector_seal_unseal_large_buffer_tests(
309       /*enable_extra_copy=*/true);
310   grpc_shutdown();
311   return 0;
312 }