Imported Upstream version 1.41.0
[platform/upstream/grpc.git] / test / core / tsi / alts / zero_copy_frame_protector / alts_iovec_record_protocol_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 "src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.h"
20
21 #include <grpc/support/alloc.h>
22 #include <grpc/support/log.h>
23
24 #include "test/core/tsi/alts/crypt/gsec_test_util.h"
25
26 constexpr size_t kMaxDataSize = 1024;
27 constexpr size_t kMaxSlices = 10;
28 constexpr size_t kSealRepeatTimes = 5;
29 constexpr size_t kTagLength = 16;
30
31 /* Test fixtures for each test cases.  */
32 struct alts_iovec_record_protocol_test_fixture {
33   alts_iovec_record_protocol* client_protect;
34   alts_iovec_record_protocol* client_unprotect;
35   alts_iovec_record_protocol* server_protect;
36   alts_iovec_record_protocol* server_unprotect;
37 };
38
39 /* Test variables for protect/unprotect operations.  */
40 struct alts_iovec_record_protocol_test_var {
41   uint8_t* header_buf;
42   size_t header_length;
43   iovec_t header_iovec;
44   uint8_t* tag_buf;
45   size_t tag_length;
46   iovec_t tag_iovec;
47   uint8_t* data_buf;
48   uint8_t* dup_buf;
49   size_t data_length;
50   iovec_t* data_iovec;
51   size_t data_iovec_length;
52   uint8_t* protected_buf;
53   iovec_t protected_iovec;
54   iovec_t unprotected_iovec;
55 };
56
57 /* --- Test utility functions. --- */
58
59 static void randomly_slice(uint8_t* input, size_t input_length,
60                            iovec_t** output, size_t* output_length) {
61   if (input_length == 0) {
62     *output = nullptr;
63     *output_length = 0;
64     return;
65   }
66   *output_length = gsec_test_bias_random_uint32(kMaxSlices) + 1;
67   *output = static_cast<iovec_t*>(gpr_malloc(*output_length * sizeof(iovec_t)));
68   for (size_t i = 0; i < *output_length - 1; i++) {
69     size_t slice_length =
70         gsec_test_bias_random_uint32(static_cast<uint32_t>(input_length));
71     iovec_t slice = {input, slice_length};
72     (*output)[i] = slice;
73     input += slice_length;
74     input_length -= slice_length;
75   }
76   iovec_t slice = {input, input_length};
77   (*output)[*output_length - 1] = slice;
78 }
79
80 static size_t alter_random_byte(uint8_t* buf, size_t buf_length) {
81   GPR_ASSERT(buf != nullptr);
82   uint32_t offset =
83       gsec_test_bias_random_uint32(static_cast<uint32_t>(buf_length));
84   (*(buf + offset))++;
85   return offset;
86 }
87
88 static void revert_back_alter(uint8_t* buf, size_t offset) {
89   GPR_ASSERT(buf != nullptr);
90   (*(buf + offset))--;
91 }
92
93 static alts_iovec_record_protocol_test_fixture*
94 alts_iovec_record_protocol_test_fixture_create(bool rekey,
95                                                bool integrity_only) {
96   alts_iovec_record_protocol_test_fixture* fixture =
97       static_cast<alts_iovec_record_protocol_test_fixture*>(
98           gpr_malloc(sizeof(alts_iovec_record_protocol_test_fixture)));
99   size_t overflow_size = 8;
100   size_t key_length = rekey ? kAes128GcmRekeyKeyLength : kAes128GcmKeyLength;
101   uint8_t* key;
102   gsec_test_random_array(&key, key_length);
103   gsec_aead_crypter* crypter = nullptr;
104   /* Create client record protocol for protect.  */
105   GPR_ASSERT(gsec_aes_gcm_aead_crypter_create(
106                  key, key_length, kAesGcmNonceLength, kAesGcmTagLength, rekey,
107                  &crypter, nullptr) == GRPC_STATUS_OK);
108   GPR_ASSERT(alts_iovec_record_protocol_create(
109                  crypter, overflow_size, /*is_client=*/true, integrity_only,
110                  /*is_protect=*/true, &fixture->client_protect,
111                  nullptr) == GRPC_STATUS_OK);
112   /* Create client record protocol for unprotect.  */
113   GPR_ASSERT(gsec_aes_gcm_aead_crypter_create(
114                  key, key_length, kAesGcmNonceLength, kAesGcmTagLength, rekey,
115                  &crypter, nullptr) == GRPC_STATUS_OK);
116   GPR_ASSERT(alts_iovec_record_protocol_create(
117                  crypter, overflow_size, /*is_client=*/true, integrity_only,
118                  /*is_protect=*/false, &fixture->client_unprotect,
119                  nullptr) == GRPC_STATUS_OK);
120   /* Create server record protocol for protect.  */
121   GPR_ASSERT(gsec_aes_gcm_aead_crypter_create(
122                  key, key_length, kAesGcmNonceLength, kAesGcmTagLength, rekey,
123                  &crypter, nullptr) == GRPC_STATUS_OK);
124   GPR_ASSERT(alts_iovec_record_protocol_create(
125                  crypter, overflow_size, /*is_client=*/false, integrity_only,
126                  /*is_protect=*/true, &fixture->server_protect,
127                  nullptr) == GRPC_STATUS_OK);
128   /* Create server record protocol for unprotect.  */
129   GPR_ASSERT(gsec_aes_gcm_aead_crypter_create(
130                  key, key_length, kAesGcmNonceLength, kAesGcmTagLength, rekey,
131                  &crypter, nullptr) == GRPC_STATUS_OK);
132   GPR_ASSERT(alts_iovec_record_protocol_create(
133                  crypter, overflow_size, /*is_client=*/false, integrity_only,
134                  /*is_protect=*/false, &fixture->server_unprotect,
135                  nullptr) == GRPC_STATUS_OK);
136
137   gpr_free(key);
138   return fixture;
139 }
140
141 static void alts_iovec_record_protocol_test_fixture_destroy(
142     alts_iovec_record_protocol_test_fixture* fixture) {
143   if (fixture == nullptr) {
144     return;
145   }
146   alts_iovec_record_protocol_destroy(fixture->client_protect);
147   alts_iovec_record_protocol_destroy(fixture->client_unprotect);
148   alts_iovec_record_protocol_destroy(fixture->server_protect);
149   alts_iovec_record_protocol_destroy(fixture->server_unprotect);
150   gpr_free(fixture);
151 }
152
153 static alts_iovec_record_protocol_test_var*
154 alts_iovec_record_protocol_test_var_create() {
155   auto* var = static_cast<alts_iovec_record_protocol_test_var*>(
156       gpr_zalloc(sizeof(alts_iovec_record_protocol_test_var)));
157   /* Sets header buffer.  */
158   var->header_length = alts_iovec_record_protocol_get_header_length();
159   var->header_buf = static_cast<uint8_t*>(gpr_malloc(var->header_length));
160   var->header_iovec.iov_base = var->header_buf;
161   var->header_iovec.iov_len = var->header_length;
162   /* Sets tag buffer.  */
163   var->tag_length = kTagLength;
164   var->tag_buf = static_cast<uint8_t*>(gpr_malloc(var->tag_length));
165   var->tag_iovec.iov_base = var->tag_buf;
166   var->tag_iovec.iov_len = var->tag_length;
167   /* Randomly sets data buffer and duplicates to dup_buf.  */
168   var->data_length = gsec_test_bias_random_uint32(kMaxDataSize) + 1;
169   var->data_buf = static_cast<uint8_t*>(gpr_malloc(var->data_length));
170   gsec_test_random_bytes(var->data_buf, var->data_length);
171   gsec_test_copy(var->data_buf, &var->dup_buf, var->data_length);
172   var->data_iovec = nullptr;
173   var->data_iovec_length = 0;
174   randomly_slice(var->data_buf, var->data_length, &var->data_iovec,
175                  &var->data_iovec_length);
176   /* Sets protected iovec.  */
177   size_t protected_buf_length =
178       var->header_length + var->data_length + var->tag_length;
179   var->protected_buf = static_cast<uint8_t*>(gpr_malloc(protected_buf_length));
180   var->protected_iovec.iov_base = var->protected_buf;
181   var->protected_iovec.iov_len = protected_buf_length;
182   /* Unprotected iovec points to data_buf.  */
183   var->unprotected_iovec.iov_base = var->data_buf;
184   var->unprotected_iovec.iov_len = var->data_length;
185   return var;
186 }
187
188 static void alts_iovec_record_protocol_test_var_destroy(
189     alts_iovec_record_protocol_test_var* var) {
190   if (var == nullptr) {
191     return;
192   }
193   gpr_free(var->header_buf);
194   gpr_free(var->tag_buf);
195   gpr_free(var->data_buf);
196   gpr_free(var->dup_buf);
197   gpr_free(var->data_iovec);
198   gpr_free(var->protected_buf);
199   gpr_free(var);
200 }
201
202 /* --- Integrity-only protect/unprotect tests. --- */
203
204 static void integrity_only_random_seal_unseal(
205     alts_iovec_record_protocol* sender, alts_iovec_record_protocol* receiver) {
206   for (size_t i = 0; i < kSealRepeatTimes; i++) {
207     alts_iovec_record_protocol_test_var* var =
208         alts_iovec_record_protocol_test_var_create();
209     /* Seals and then unseals.  */
210     grpc_status_code status = alts_iovec_record_protocol_integrity_only_protect(
211         sender, var->data_iovec, var->data_iovec_length, var->header_iovec,
212         var->tag_iovec, nullptr);
213     GPR_ASSERT(status == GRPC_STATUS_OK);
214     gpr_free(var->data_iovec);
215     /* Randomly slices data buffer again.  */
216     randomly_slice(var->data_buf, var->data_length, &var->data_iovec,
217                    &var->data_iovec_length);
218     status = alts_iovec_record_protocol_integrity_only_unprotect(
219         receiver, var->data_iovec, var->data_iovec_length, var->header_iovec,
220         var->tag_iovec, nullptr);
221     GPR_ASSERT(status == GRPC_STATUS_OK);
222     /* Makes sure data buffer has not been modified during
223      * seal/unseal.  */
224     GPR_ASSERT(memcmp(var->data_buf, var->dup_buf, var->data_length) == 0);
225     alts_iovec_record_protocol_test_var_destroy(var);
226   }
227 }
228
229 static void integrity_only_empty_seal_unseal(
230     alts_iovec_record_protocol* sender, alts_iovec_record_protocol* receiver) {
231   for (size_t i = 0; i < kSealRepeatTimes; i++) {
232     alts_iovec_record_protocol_test_var* var =
233         alts_iovec_record_protocol_test_var_create();
234     /* Seals and then unseals empty payload.  */
235     grpc_status_code status = alts_iovec_record_protocol_integrity_only_protect(
236         sender, nullptr, 0, var->header_iovec, var->tag_iovec, nullptr);
237     GPR_ASSERT(status == GRPC_STATUS_OK);
238     status = alts_iovec_record_protocol_integrity_only_unprotect(
239         receiver, nullptr, 0, var->header_iovec, var->tag_iovec, nullptr);
240     GPR_ASSERT(status == GRPC_STATUS_OK);
241     alts_iovec_record_protocol_test_var_destroy(var);
242   }
243 }
244
245 static void integrity_only_unsync_seal_unseal(
246     alts_iovec_record_protocol* sender, alts_iovec_record_protocol* receiver) {
247   /* Seals once.  */
248   alts_iovec_record_protocol_test_var* var =
249       alts_iovec_record_protocol_test_var_create();
250   grpc_status_code status = alts_iovec_record_protocol_integrity_only_protect(
251       sender, var->data_iovec, var->data_iovec_length, var->header_iovec,
252       var->tag_iovec, nullptr);
253   GPR_ASSERT(status == GRPC_STATUS_OK);
254   alts_iovec_record_protocol_test_var_destroy(var);
255   /* Seals again.  */
256   var = alts_iovec_record_protocol_test_var_create();
257   status = alts_iovec_record_protocol_integrity_only_protect(
258       sender, var->data_iovec, var->data_iovec_length, var->header_iovec,
259       var->tag_iovec, nullptr);
260   GPR_ASSERT(status == GRPC_STATUS_OK);
261   /* Unseals the second frame.  */
262   char* error_message = nullptr;
263   status = alts_iovec_record_protocol_integrity_only_unprotect(
264       receiver, var->data_iovec, var->data_iovec_length, var->header_iovec,
265       var->tag_iovec, &error_message);
266   GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
267       status, GRPC_STATUS_INTERNAL, error_message,
268       "Frame tag verification failed."));
269   gpr_free(error_message);
270   alts_iovec_record_protocol_test_var_destroy(var);
271 }
272
273 static void integrity_only_corrupted_data(
274     alts_iovec_record_protocol* sender, alts_iovec_record_protocol* receiver) {
275   /* Seals the data first.  */
276   alts_iovec_record_protocol_test_var* var =
277       alts_iovec_record_protocol_test_var_create();
278   grpc_status_code status = alts_iovec_record_protocol_integrity_only_protect(
279       sender, var->data_iovec, var->data_iovec_length, var->header_iovec,
280       var->tag_iovec, nullptr);
281   GPR_ASSERT(status == GRPC_STATUS_OK);
282   /* Alter frame length field.  */
283   char* error_message = nullptr;
284   size_t offset =
285       alter_random_byte(var->header_buf, kZeroCopyFrameLengthFieldSize);
286   status = alts_iovec_record_protocol_integrity_only_unprotect(
287       receiver, var->data_iovec, var->data_iovec_length, var->header_iovec,
288       var->tag_iovec, &error_message);
289   GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
290       status, GRPC_STATUS_INTERNAL, error_message, "Bad frame length."));
291   gpr_free(error_message);
292   revert_back_alter(var->header_buf, offset);
293   /* Alter message type field.  */
294   offset = alter_random_byte(var->header_buf + kZeroCopyFrameLengthFieldSize,
295                              kZeroCopyFrameMessageTypeFieldSize);
296   status = alts_iovec_record_protocol_integrity_only_unprotect(
297       receiver, var->data_iovec, var->data_iovec_length, var->header_iovec,
298       var->tag_iovec, &error_message);
299   GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
300       status, GRPC_STATUS_INTERNAL, error_message,
301       "Unsupported message type."));
302   gpr_free(error_message);
303   revert_back_alter(var->header_buf + kZeroCopyFrameLengthFieldSize, offset);
304   /* Alter data.  */
305   offset = alter_random_byte(var->data_buf, var->data_length);
306   status = alts_iovec_record_protocol_integrity_only_unprotect(
307       receiver, var->data_iovec, var->data_iovec_length, var->header_iovec,
308       var->tag_iovec, &error_message);
309   GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
310       status, GRPC_STATUS_INTERNAL, error_message,
311       "Frame tag verification failed."));
312   gpr_free(error_message);
313   revert_back_alter(var->data_buf, offset);
314   /* Alter tag.  */
315   offset = alter_random_byte(var->tag_buf, var->tag_length);
316   status = alts_iovec_record_protocol_integrity_only_unprotect(
317       receiver, var->data_iovec, var->data_iovec_length, var->header_iovec,
318       var->tag_iovec, &error_message);
319   GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
320       status, GRPC_STATUS_INTERNAL, error_message,
321       "Frame tag verification failed."));
322   gpr_free(error_message);
323   revert_back_alter(var->tag_buf, offset);
324   /* Reverted protected data should be verified correctly.  */
325   status = alts_iovec_record_protocol_integrity_only_unprotect(
326       receiver, var->data_iovec, var->data_iovec_length, var->header_iovec,
327       var->tag_iovec, nullptr);
328   GPR_ASSERT(status == GRPC_STATUS_OK);
329   GPR_ASSERT(memcmp(var->data_buf, var->dup_buf, var->data_length) == 0);
330   alts_iovec_record_protocol_test_var_destroy(var);
331 }
332
333 static void integrity_only_protect_input_check(alts_iovec_record_protocol* rp) {
334   alts_iovec_record_protocol_test_var* var =
335       alts_iovec_record_protocol_test_var_create();
336   char* error_message = nullptr;
337   /* Header buffer is nullptr.  */
338   iovec_t header_iovec = {nullptr, var->header_length};
339   grpc_status_code status = alts_iovec_record_protocol_integrity_only_protect(
340       rp, var->data_iovec, var->data_iovec_length, header_iovec, var->tag_iovec,
341       &error_message);
342   GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
343       status, GRPC_STATUS_INVALID_ARGUMENT, error_message,
344       "Header is nullptr."));
345   gpr_free(error_message);
346   /* Header buffer length is 0.  */
347   header_iovec.iov_base = var->header_buf;
348   header_iovec.iov_len = 0;
349   status = alts_iovec_record_protocol_integrity_only_protect(
350       rp, var->data_iovec, var->data_iovec_length, header_iovec, var->tag_iovec,
351       &error_message);
352   GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
353       status, GRPC_STATUS_INVALID_ARGUMENT, error_message,
354       "Header length is incorrect."));
355   gpr_free(error_message);
356   /* Tag buffer is nullptr.  */
357   iovec_t tag_iovec = {nullptr, var->tag_length};
358   status = alts_iovec_record_protocol_integrity_only_protect(
359       rp, var->data_iovec, var->data_iovec_length, var->header_iovec, tag_iovec,
360       &error_message);
361   GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
362       status, GRPC_STATUS_INVALID_ARGUMENT, error_message, "Tag is nullptr."));
363   gpr_free(error_message);
364   /* Tag buffer length is 0.  */
365   tag_iovec.iov_base = var->tag_buf;
366   tag_iovec.iov_len = 0;
367   status = alts_iovec_record_protocol_integrity_only_protect(
368       rp, var->data_iovec, var->data_iovec_length, var->header_iovec, tag_iovec,
369       &error_message);
370   GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
371       status, GRPC_STATUS_INVALID_ARGUMENT, error_message,
372       "Tag length is incorrect."));
373   gpr_free(error_message);
374   alts_iovec_record_protocol_test_var_destroy(var);
375 }
376
377 static void integrity_only_unprotect_input_check(
378     alts_iovec_record_protocol* rp) {
379   alts_iovec_record_protocol_test_var* var =
380       alts_iovec_record_protocol_test_var_create();
381   char* error_message = nullptr;
382   /* Header buffer is nullptr.  */
383   iovec_t header_iovec = {nullptr, var->header_length};
384   grpc_status_code status = alts_iovec_record_protocol_integrity_only_unprotect(
385       rp, var->data_iovec, var->data_iovec_length, header_iovec, var->tag_iovec,
386       &error_message);
387   GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
388       status, GRPC_STATUS_INVALID_ARGUMENT, error_message,
389       "Header is nullptr."));
390   gpr_free(error_message);
391   /* Header buffer length is 0.  */
392   header_iovec.iov_base = var->header_buf;
393   header_iovec.iov_len = 0;
394   status = alts_iovec_record_protocol_integrity_only_unprotect(
395       rp, var->data_iovec, var->data_iovec_length, header_iovec, var->tag_iovec,
396       &error_message);
397   GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
398       status, GRPC_STATUS_INVALID_ARGUMENT, error_message,
399       "Header length is incorrect."));
400   gpr_free(error_message);
401   /* Tag buffer is nullptr.  */
402   iovec_t tag_iovec = {nullptr, var->tag_length};
403   status = alts_iovec_record_protocol_integrity_only_unprotect(
404       rp, var->data_iovec, var->data_iovec_length, var->header_iovec, tag_iovec,
405       &error_message);
406   GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
407       status, GRPC_STATUS_INVALID_ARGUMENT, error_message, "Tag is nullptr."));
408   gpr_free(error_message);
409   /* Tag buffer length is 0.  */
410   tag_iovec.iov_base = var->tag_buf;
411   tag_iovec.iov_len = 0;
412   status = alts_iovec_record_protocol_integrity_only_unprotect(
413       rp, var->data_iovec, var->data_iovec_length, var->header_iovec, tag_iovec,
414       &error_message);
415   GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
416       status, GRPC_STATUS_INVALID_ARGUMENT, error_message,
417       "Tag length is incorrect."));
418   gpr_free(error_message);
419   alts_iovec_record_protocol_test_var_destroy(var);
420 }
421
422 /* --- Privacy-integrity protect/unprotect tests. --- */
423
424 static void privacy_integrity_random_seal_unseal(
425     alts_iovec_record_protocol* sender, alts_iovec_record_protocol* receiver) {
426   for (size_t i = 0; i < kSealRepeatTimes; i++) {
427     alts_iovec_record_protocol_test_var* var =
428         alts_iovec_record_protocol_test_var_create();
429     /* Seals and then unseals.  */
430     grpc_status_code status =
431         alts_iovec_record_protocol_privacy_integrity_protect(
432             sender, var->data_iovec, var->data_iovec_length,
433             var->protected_iovec, nullptr);
434     GPR_ASSERT(status == GRPC_STATUS_OK);
435     iovec_t header_iovec = {var->protected_buf, var->header_length};
436     gpr_free(var->data_iovec);
437     /* Randomly slices protected buffer, excluding the header.  */
438     randomly_slice(var->protected_buf + var->header_length,
439                    var->data_length + var->tag_length, &var->data_iovec,
440                    &var->data_iovec_length);
441     status = alts_iovec_record_protocol_privacy_integrity_unprotect(
442         receiver, header_iovec, var->data_iovec, var->data_iovec_length,
443         var->unprotected_iovec, nullptr);
444     GPR_ASSERT(status == GRPC_STATUS_OK);
445     /* Makes sure unprotected data are the same as the original.  */
446     GPR_ASSERT(memcmp(var->data_buf, var->dup_buf, var->data_length) == 0);
447     alts_iovec_record_protocol_test_var_destroy(var);
448   }
449 }
450
451 static void privacy_integrity_empty_seal_unseal(
452     alts_iovec_record_protocol* sender, alts_iovec_record_protocol* receiver) {
453   alts_iovec_record_protocol_test_var* var =
454       alts_iovec_record_protocol_test_var_create();
455   size_t empty_payload_frame_size = var->header_length + var->tag_length;
456   auto* protected_buf =
457       static_cast<uint8_t*>(gpr_malloc(empty_payload_frame_size));
458   for (size_t i = 0; i < kSealRepeatTimes; i++) {
459     iovec_t protected_iovec = {protected_buf, empty_payload_frame_size};
460     iovec_t unprotected_iovec = {nullptr, 0};
461     iovec_t data_iovec = {protected_buf + var->header_length, var->tag_length};
462     /* Seals and then unseals empty payload.  */
463     grpc_status_code status =
464         alts_iovec_record_protocol_privacy_integrity_protect(
465             sender, nullptr, 0, protected_iovec, nullptr);
466     GPR_ASSERT(status == GRPC_STATUS_OK);
467     iovec_t header_iovec = {protected_buf, var->header_length};
468     status = alts_iovec_record_protocol_privacy_integrity_unprotect(
469         receiver, header_iovec, &data_iovec, 1, unprotected_iovec, nullptr);
470     GPR_ASSERT(status == GRPC_STATUS_OK);
471   }
472   gpr_free(protected_buf);
473   alts_iovec_record_protocol_test_var_destroy(var);
474 }
475
476 static void privacy_integrity_unsync_seal_unseal(
477     alts_iovec_record_protocol* sender, alts_iovec_record_protocol* receiver) {
478   /* Seals once.  */
479   alts_iovec_record_protocol_test_var* var =
480       alts_iovec_record_protocol_test_var_create();
481   grpc_status_code status =
482       alts_iovec_record_protocol_privacy_integrity_protect(
483           sender, var->data_iovec, var->data_iovec_length, var->protected_iovec,
484           nullptr);
485   GPR_ASSERT(status == GRPC_STATUS_OK);
486   alts_iovec_record_protocol_test_var_destroy(var);
487   /* Seals again.  */
488   var = alts_iovec_record_protocol_test_var_create();
489   status = alts_iovec_record_protocol_privacy_integrity_protect(
490       sender, var->data_iovec, var->data_iovec_length, var->protected_iovec,
491       nullptr);
492   GPR_ASSERT(status == GRPC_STATUS_OK);
493   /* Unseals the second frame.  */
494   char* error_message = nullptr;
495   iovec_t header_iovec = {var->protected_buf, var->header_length};
496   iovec_t protected_iovec = {var->protected_buf + var->header_length,
497                              var->data_length + var->tag_length};
498   status = alts_iovec_record_protocol_privacy_integrity_unprotect(
499       receiver, header_iovec, &protected_iovec, 1, var->unprotected_iovec,
500       &error_message);
501   GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
502       status, GRPC_STATUS_INTERNAL, error_message, "Frame decryption failed."));
503   gpr_free(error_message);
504   alts_iovec_record_protocol_test_var_destroy(var);
505 }
506
507 static void privacy_integrity_corrupted_data(
508     alts_iovec_record_protocol* sender, alts_iovec_record_protocol* receiver) {
509   /* Seals the data first.  */
510   alts_iovec_record_protocol_test_var* var =
511       alts_iovec_record_protocol_test_var_create();
512   grpc_status_code status =
513       alts_iovec_record_protocol_privacy_integrity_protect(
514           sender, var->data_iovec, var->data_iovec_length, var->protected_iovec,
515           nullptr);
516   GPR_ASSERT(status == GRPC_STATUS_OK);
517   char* error_message = nullptr;
518   uint8_t* header_buf = var->protected_buf;
519   size_t header_length = var->header_length;
520   iovec_t header_iovec = {header_buf, header_length};
521   /* The following protected_buf and protected_length excludes header.  */
522   uint8_t* protected_buf = var->protected_buf + var->header_length;
523   size_t protected_length = var->data_length + var->tag_length;
524   iovec_t protected_iovec = {protected_buf, protected_length};
525   /* Alter frame length field.  */
526   size_t offset = alter_random_byte(header_buf, kZeroCopyFrameLengthFieldSize);
527   status = alts_iovec_record_protocol_privacy_integrity_unprotect(
528       receiver, header_iovec, &protected_iovec, 1, var->unprotected_iovec,
529       &error_message);
530   GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
531       status, GRPC_STATUS_INTERNAL, error_message, "Bad frame length."));
532   gpr_free(error_message);
533   revert_back_alter(header_buf, offset);
534   /* Alter message type field.  */
535   offset = alter_random_byte(header_buf + kZeroCopyFrameLengthFieldSize,
536                              kZeroCopyFrameMessageTypeFieldSize);
537   status = alts_iovec_record_protocol_privacy_integrity_unprotect(
538       receiver, header_iovec, &protected_iovec, 1, var->unprotected_iovec,
539       &error_message);
540   GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
541       status, GRPC_STATUS_INTERNAL, error_message,
542       "Unsupported message type."));
543   gpr_free(error_message);
544   revert_back_alter(header_buf + kZeroCopyFrameLengthFieldSize, offset);
545   /* Alter protected data.  */
546   offset = alter_random_byte(protected_buf, protected_length);
547   status = alts_iovec_record_protocol_privacy_integrity_unprotect(
548       receiver, header_iovec, &protected_iovec, 1, var->unprotected_iovec,
549       &error_message);
550   GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
551       status, GRPC_STATUS_INTERNAL, error_message, "Frame decryption failed."));
552   gpr_free(error_message);
553   revert_back_alter(protected_buf, offset);
554   /* Reverted protected data should be verified correctly.  */
555   status = alts_iovec_record_protocol_privacy_integrity_unprotect(
556       receiver, header_iovec, &protected_iovec, 1, var->unprotected_iovec,
557       nullptr);
558   GPR_ASSERT(status == GRPC_STATUS_OK);
559   GPR_ASSERT(memcmp(var->data_buf, var->dup_buf, var->data_length) == 0);
560   alts_iovec_record_protocol_test_var_destroy(var);
561 }
562
563 static void privacy_integrity_protect_input_check(
564     alts_iovec_record_protocol* rp) {
565   alts_iovec_record_protocol_test_var* var =
566       alts_iovec_record_protocol_test_var_create();
567   char* error_message = nullptr;
568   /* Protected output buffer is nullptr.  */
569   iovec_t protected_iovec = {nullptr, var->protected_iovec.iov_len};
570   grpc_status_code status =
571       alts_iovec_record_protocol_privacy_integrity_protect(
572           rp, var->data_iovec, var->data_iovec_length, protected_iovec,
573           &error_message);
574   GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
575       status, GRPC_STATUS_INVALID_ARGUMENT, error_message,
576       "Protected frame is nullptr."));
577   gpr_free(error_message);
578   /* Protected output buffer length incorrect.  */
579   protected_iovec.iov_base = var->protected_buf;
580   protected_iovec.iov_len = var->header_length + var->data_length;
581   status = alts_iovec_record_protocol_privacy_integrity_protect(
582       rp, var->data_iovec, var->data_iovec_length, protected_iovec,
583       &error_message);
584   GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
585       status, GRPC_STATUS_INVALID_ARGUMENT, error_message,
586       "Protected frame size is incorrect."));
587   gpr_free(error_message);
588   alts_iovec_record_protocol_test_var_destroy(var);
589 }
590
591 static void privacy_integrity_unprotect_input_check(
592     alts_iovec_record_protocol* rp) {
593   alts_iovec_record_protocol_test_var* var =
594       alts_iovec_record_protocol_test_var_create();
595   char* error_message = nullptr;
596   /* Header buffer is nullptr.  */
597   iovec_t header_iovec = {var->protected_buf, var->header_length};
598   iovec_t protected_iovec = {var->protected_buf + var->header_length,
599                              var->data_length + var->tag_length};
600   header_iovec.iov_base = nullptr;
601   grpc_status_code status =
602       alts_iovec_record_protocol_privacy_integrity_unprotect(
603           rp, header_iovec, &protected_iovec, 1, var->unprotected_iovec,
604           &error_message);
605   GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
606       status, GRPC_STATUS_INVALID_ARGUMENT, error_message,
607       "Header is nullptr."));
608   gpr_free(error_message);
609   header_iovec.iov_base = var->protected_buf;
610   /* Header buffer length is 0.  */
611   header_iovec.iov_len = 0;
612   status = alts_iovec_record_protocol_privacy_integrity_unprotect(
613       rp, header_iovec, &protected_iovec, 1, var->unprotected_iovec,
614       &error_message);
615   GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
616       status, GRPC_STATUS_INVALID_ARGUMENT, error_message,
617       "Header length is incorrect."));
618   gpr_free(error_message);
619   header_iovec.iov_len = var->header_length;
620   /* Unprotected output buffer length is incorrect.  */
621   iovec_t unprotected_iovec = {var->data_buf, var->data_length - 1};
622   status = alts_iovec_record_protocol_privacy_integrity_unprotect(
623       rp, header_iovec, &protected_iovec, 1, unprotected_iovec, &error_message);
624   GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
625       status, GRPC_STATUS_INVALID_ARGUMENT, error_message,
626       "Unprotected data size is incorrect."));
627   gpr_free(error_message);
628   alts_iovec_record_protocol_test_var_destroy(var);
629 }
630
631 /* --- Integrity-only and privacy-integrity mixed. --- */
632
633 static void record_protocol_wrong_mode(
634     alts_iovec_record_protocol* integrity_only_protect_rp,
635     alts_iovec_record_protocol* integrity_only_unprotect_rp,
636     alts_iovec_record_protocol* privacy_integrity_protect_rp,
637     alts_iovec_record_protocol* privacy_integrity_unprotect_rp) {
638   alts_iovec_record_protocol_test_var* var =
639       alts_iovec_record_protocol_test_var_create();
640   grpc_status_code status;
641   char* error_message = nullptr;
642   /* Call integrity-only protect on privacy-integrity record protocol.  */
643   status = alts_iovec_record_protocol_integrity_only_protect(
644       privacy_integrity_protect_rp, var->data_iovec, var->data_iovec_length,
645       var->header_iovec, var->tag_iovec, &error_message);
646   GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
647       status, GRPC_STATUS_FAILED_PRECONDITION, error_message,
648       "Integrity-only operations are not allowed for this object."));
649   gpr_free(error_message);
650   /* Call integrity-only unprotect on privacy-integrity record protocol.  */
651   status = alts_iovec_record_protocol_integrity_only_unprotect(
652       privacy_integrity_unprotect_rp, var->data_iovec, var->data_iovec_length,
653       var->header_iovec, var->tag_iovec, &error_message);
654   GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
655       status, GRPC_STATUS_FAILED_PRECONDITION, error_message,
656       "Integrity-only operations are not allowed for this object."));
657   gpr_free(error_message);
658   /* Call privacy-integrity protect on integrity-only record protocol.  */
659   status = alts_iovec_record_protocol_privacy_integrity_protect(
660       integrity_only_protect_rp, var->data_iovec, var->data_iovec_length,
661       var->protected_iovec, &error_message);
662   GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
663       status, GRPC_STATUS_FAILED_PRECONDITION, error_message,
664       "Privacy-integrity operations are not allowed for this object."));
665   gpr_free(error_message);
666   /* Call privacy-integrity unprotect on integrity-only record protocol.  */
667   status = alts_iovec_record_protocol_privacy_integrity_unprotect(
668       integrity_only_unprotect_rp, var->header_iovec, var->data_iovec,
669       var->data_iovec_length, var->unprotected_iovec, &error_message);
670   GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
671       status, GRPC_STATUS_FAILED_PRECONDITION, error_message,
672       "Privacy-integrity operations are not allowed for this object."));
673   gpr_free(error_message);
674   alts_iovec_record_protocol_test_var_destroy(var);
675 }
676
677 static void integrity_seal_privacy_unseal(
678     alts_iovec_record_protocol* integrity_only_sender,
679     alts_iovec_record_protocol* privacy_integrity_receiver) {
680   alts_iovec_record_protocol_test_var* var =
681       alts_iovec_record_protocol_test_var_create();
682   grpc_status_code status;
683   char* error_message = nullptr;
684   /* Seals with integrity-only protect.  */
685   status = alts_iovec_record_protocol_integrity_only_protect(
686       integrity_only_sender, var->data_iovec, var->data_iovec_length,
687       var->header_iovec, var->tag_iovec, nullptr);
688   GPR_ASSERT(status == GRPC_STATUS_OK);
689   /* Unseal with privacy-integrity unprotect.  */
690   memcpy(var->protected_buf, var->data_buf, var->data_length);
691   memcpy(var->protected_buf + var->data_length, var->tag_buf, var->tag_length);
692   iovec_t protected_iovec = {var->protected_buf,
693                              var->data_length + var->tag_length};
694   status = alts_iovec_record_protocol_privacy_integrity_unprotect(
695       privacy_integrity_receiver, var->header_iovec, &protected_iovec, 1,
696       var->unprotected_iovec, &error_message);
697   GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
698       status, GRPC_STATUS_INTERNAL, error_message, "Frame decryption failed."));
699   gpr_free(error_message);
700   alts_iovec_record_protocol_test_var_destroy(var);
701 }
702
703 static void privacy_seal_integrity_unseal(
704     alts_iovec_record_protocol* privacy_integrity_sender,
705     alts_iovec_record_protocol* integrity_only_receiver) {
706   alts_iovec_record_protocol_test_var* var =
707       alts_iovec_record_protocol_test_var_create();
708   grpc_status_code status;
709   char* error_message = nullptr;
710   /* Seals with privacy-integrity protect.  */
711   status = alts_iovec_record_protocol_privacy_integrity_protect(
712       privacy_integrity_sender, var->data_iovec, var->data_iovec_length,
713       var->protected_iovec, nullptr);
714   GPR_ASSERT(status == GRPC_STATUS_OK);
715   /* Unseal with integrity-only unprotect.  */
716   iovec_t header_iovec = {var->protected_buf, var->header_length};
717   iovec_t data_iovec = {var->protected_buf + var->header_length,
718                         var->data_length};
719   iovec_t tag_iovec = {
720       var->protected_buf + var->header_length + var->data_length,
721       var->tag_length};
722   status = alts_iovec_record_protocol_integrity_only_unprotect(
723       integrity_only_receiver, &data_iovec, 1, header_iovec, tag_iovec,
724       &error_message);
725   GPR_ASSERT(gsec_test_expect_compare_code_and_substr(
726       status, GRPC_STATUS_INTERNAL, error_message,
727       "Frame tag verification failed."));
728   gpr_free(error_message);
729   alts_iovec_record_protocol_test_var_destroy(var);
730 }
731
732 /* --- Test cases. --- */
733
734 static void alts_iovec_record_protocol_random_seal_unseal_tests() {
735   alts_iovec_record_protocol_test_fixture* fixture =
736       alts_iovec_record_protocol_test_fixture_create(
737           /*rekey=*/false, /*integrity_only=*/true);
738   integrity_only_random_seal_unseal(fixture->client_protect,
739                                     fixture->server_unprotect);
740   integrity_only_random_seal_unseal(fixture->server_protect,
741                                     fixture->client_unprotect);
742   alts_iovec_record_protocol_test_fixture_destroy(fixture);
743
744   fixture = alts_iovec_record_protocol_test_fixture_create(
745       /*rekey=*/true, /*integrity_only=*/true);
746   integrity_only_random_seal_unseal(fixture->client_protect,
747                                     fixture->server_unprotect);
748   integrity_only_random_seal_unseal(fixture->server_protect,
749                                     fixture->client_unprotect);
750   alts_iovec_record_protocol_test_fixture_destroy(fixture);
751
752   fixture = alts_iovec_record_protocol_test_fixture_create(
753       /*rekey=*/false, /*integrity_only=*/false);
754   privacy_integrity_random_seal_unseal(fixture->client_protect,
755                                        fixture->server_unprotect);
756   privacy_integrity_random_seal_unseal(fixture->server_protect,
757                                        fixture->client_unprotect);
758   alts_iovec_record_protocol_test_fixture_destroy(fixture);
759
760   fixture = alts_iovec_record_protocol_test_fixture_create(
761       /*rekey=*/true, /*integrity_only=*/false);
762   privacy_integrity_random_seal_unseal(fixture->client_protect,
763                                        fixture->server_unprotect);
764   privacy_integrity_random_seal_unseal(fixture->server_protect,
765                                        fixture->client_unprotect);
766   alts_iovec_record_protocol_test_fixture_destroy(fixture);
767 }
768
769 static void alts_iovec_record_protocol_empty_seal_unseal_tests() {
770   alts_iovec_record_protocol_test_fixture* fixture =
771       alts_iovec_record_protocol_test_fixture_create(
772           /*rekey=*/false, /*integrity_only=*/true);
773   integrity_only_empty_seal_unseal(fixture->client_protect,
774                                    fixture->server_unprotect);
775   integrity_only_empty_seal_unseal(fixture->server_protect,
776                                    fixture->client_unprotect);
777   alts_iovec_record_protocol_test_fixture_destroy(fixture);
778
779   fixture = alts_iovec_record_protocol_test_fixture_create(
780       /*rekey=*/true, /*integrity_only=*/true);
781   integrity_only_empty_seal_unseal(fixture->client_protect,
782                                    fixture->server_unprotect);
783   integrity_only_empty_seal_unseal(fixture->server_protect,
784                                    fixture->client_unprotect);
785   alts_iovec_record_protocol_test_fixture_destroy(fixture);
786
787   fixture = alts_iovec_record_protocol_test_fixture_create(
788       /*rekey=*/false, /*integrity_only=*/false);
789   privacy_integrity_empty_seal_unseal(fixture->client_protect,
790                                       fixture->server_unprotect);
791   privacy_integrity_empty_seal_unseal(fixture->server_protect,
792                                       fixture->client_unprotect);
793   alts_iovec_record_protocol_test_fixture_destroy(fixture);
794
795   fixture = alts_iovec_record_protocol_test_fixture_create(
796       /*rekey=*/true, /*integrity_only=*/false);
797   privacy_integrity_empty_seal_unseal(fixture->client_protect,
798                                       fixture->server_unprotect);
799   privacy_integrity_empty_seal_unseal(fixture->server_protect,
800                                       fixture->client_unprotect);
801   alts_iovec_record_protocol_test_fixture_destroy(fixture);
802 }
803
804 static void alts_iovec_record_protocol_unsync_seal_unseal_tests() {
805   alts_iovec_record_protocol_test_fixture* fixture =
806       alts_iovec_record_protocol_test_fixture_create(
807           /*rekey=*/false, /*integrity_only=*/true);
808   integrity_only_unsync_seal_unseal(fixture->client_protect,
809                                     fixture->server_unprotect);
810   integrity_only_unsync_seal_unseal(fixture->server_protect,
811                                     fixture->client_unprotect);
812   alts_iovec_record_protocol_test_fixture_destroy(fixture);
813
814   fixture = alts_iovec_record_protocol_test_fixture_create(
815       /*rekey=*/true, /*integrity_only=*/true);
816   integrity_only_unsync_seal_unseal(fixture->client_protect,
817                                     fixture->server_unprotect);
818   integrity_only_unsync_seal_unseal(fixture->server_protect,
819                                     fixture->client_unprotect);
820   alts_iovec_record_protocol_test_fixture_destroy(fixture);
821
822   fixture = alts_iovec_record_protocol_test_fixture_create(
823       /*rekey=*/false, /*integrity_only=*/false);
824   privacy_integrity_unsync_seal_unseal(fixture->client_protect,
825                                        fixture->server_unprotect);
826   privacy_integrity_unsync_seal_unseal(fixture->server_protect,
827                                        fixture->client_unprotect);
828   alts_iovec_record_protocol_test_fixture_destroy(fixture);
829
830   fixture = alts_iovec_record_protocol_test_fixture_create(
831       /*rekey=*/true, /*integrity_only=*/false);
832   privacy_integrity_unsync_seal_unseal(fixture->client_protect,
833                                        fixture->server_unprotect);
834   privacy_integrity_unsync_seal_unseal(fixture->server_protect,
835                                        fixture->client_unprotect);
836   alts_iovec_record_protocol_test_fixture_destroy(fixture);
837 }
838
839 static void alts_iovec_record_protocol_corrupted_data_tests() {
840   alts_iovec_record_protocol_test_fixture* fixture =
841       alts_iovec_record_protocol_test_fixture_create(
842           /*rekey=*/false, /*integrity_only=*/true);
843   integrity_only_corrupted_data(fixture->client_protect,
844                                 fixture->server_unprotect);
845   integrity_only_corrupted_data(fixture->server_protect,
846                                 fixture->client_unprotect);
847   alts_iovec_record_protocol_test_fixture_destroy(fixture);
848
849   fixture = alts_iovec_record_protocol_test_fixture_create(
850       /*rekey=*/true, /*integrity_only=*/true);
851   integrity_only_corrupted_data(fixture->client_protect,
852                                 fixture->server_unprotect);
853   integrity_only_corrupted_data(fixture->server_protect,
854                                 fixture->client_unprotect);
855   alts_iovec_record_protocol_test_fixture_destroy(fixture);
856
857   fixture = alts_iovec_record_protocol_test_fixture_create(
858       /*rekey=*/false, /*integrity_only=*/false);
859   privacy_integrity_corrupted_data(fixture->client_protect,
860                                    fixture->server_unprotect);
861   privacy_integrity_corrupted_data(fixture->server_protect,
862                                    fixture->client_unprotect);
863   alts_iovec_record_protocol_test_fixture_destroy(fixture);
864
865   fixture = alts_iovec_record_protocol_test_fixture_create(
866       /*rekey=*/true, /*integrity_only=*/false);
867   privacy_integrity_corrupted_data(fixture->client_protect,
868                                    fixture->server_unprotect);
869   privacy_integrity_corrupted_data(fixture->server_protect,
870                                    fixture->client_unprotect);
871   alts_iovec_record_protocol_test_fixture_destroy(fixture);
872 }
873
874 static void alts_iovec_record_protocol_input_check_tests() {
875   alts_iovec_record_protocol_test_fixture* fixture =
876       alts_iovec_record_protocol_test_fixture_create(
877           /*rekey=*/false, /*integrity_only=*/true);
878   integrity_only_protect_input_check(fixture->client_protect);
879   integrity_only_unprotect_input_check(fixture->client_unprotect);
880   alts_iovec_record_protocol_test_fixture_destroy(fixture);
881
882   fixture = alts_iovec_record_protocol_test_fixture_create(
883       /*rekey=*/true, /*integrity_only=*/true);
884   integrity_only_protect_input_check(fixture->client_protect);
885   integrity_only_unprotect_input_check(fixture->client_unprotect);
886   alts_iovec_record_protocol_test_fixture_destroy(fixture);
887
888   fixture = alts_iovec_record_protocol_test_fixture_create(
889       /*rekey=*/false, /*integrity_only=*/false);
890   privacy_integrity_protect_input_check(fixture->client_protect);
891   privacy_integrity_unprotect_input_check(fixture->client_unprotect);
892   alts_iovec_record_protocol_test_fixture_destroy(fixture);
893
894   fixture = alts_iovec_record_protocol_test_fixture_create(
895       /*rekey=*/true, /*integrity_only=*/false);
896   privacy_integrity_protect_input_check(fixture->client_protect);
897   privacy_integrity_unprotect_input_check(fixture->client_unprotect);
898   alts_iovec_record_protocol_test_fixture_destroy(fixture);
899 }
900
901 static void alts_iovec_record_protocol_mix_operations_tests() {
902   alts_iovec_record_protocol_test_fixture* fixture_1 =
903       alts_iovec_record_protocol_test_fixture_create(
904           /*rekey=*/false, /*integrity_only=*/true);
905   alts_iovec_record_protocol_test_fixture* fixture_2 =
906       alts_iovec_record_protocol_test_fixture_create(
907           /*rekey=*/false, /*integrity_only=*/false);
908
909   record_protocol_wrong_mode(
910       fixture_1->client_protect, fixture_1->client_unprotect,
911       fixture_2->client_protect, fixture_2->client_unprotect);
912   integrity_seal_privacy_unseal(fixture_1->client_protect,
913                                 fixture_2->server_unprotect);
914   privacy_seal_integrity_unseal(fixture_2->client_protect,
915                                 fixture_1->server_unprotect);
916
917   alts_iovec_record_protocol_test_fixture_destroy(fixture_1);
918   alts_iovec_record_protocol_test_fixture_destroy(fixture_2);
919 }
920
921 int main(int /*argc*/, char** /*argv*/) {
922   alts_iovec_record_protocol_random_seal_unseal_tests();
923   alts_iovec_record_protocol_empty_seal_unseal_tests();
924   alts_iovec_record_protocol_unsync_seal_unseal_tests();
925   alts_iovec_record_protocol_corrupted_data_tests();
926   alts_iovec_record_protocol_input_check_tests();
927   alts_iovec_record_protocol_mix_operations_tests();
928   return 0;
929 }