3 * Copyright 2018 gRPC authors.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include "src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.h"
21 #include <grpc/support/alloc.h>
22 #include <grpc/support/log.h>
24 #include "test/core/tsi/alts/crypt/gsec_test_util.h"
26 constexpr size_t kMaxDataSize = 1024;
27 constexpr size_t kMaxSlices = 10;
28 constexpr size_t kSealRepeatTimes = 5;
29 constexpr size_t kTagLength = 16;
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;
39 /* Test variables for protect/unprotect operations. */
40 struct alts_iovec_record_protocol_test_var {
51 size_t data_iovec_length;
52 uint8_t* protected_buf;
53 iovec_t protected_iovec;
54 iovec_t unprotected_iovec;
57 /* --- Test utility functions. --- */
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) {
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++) {
70 gsec_test_bias_random_uint32(static_cast<uint32_t>(input_length));
71 iovec_t slice = {input, slice_length};
73 input += slice_length;
74 input_length -= slice_length;
76 iovec_t slice = {input, input_length};
77 (*output)[*output_length - 1] = slice;
80 static size_t alter_random_byte(uint8_t* buf, size_t buf_length) {
81 GPR_ASSERT(buf != nullptr);
83 gsec_test_bias_random_uint32(static_cast<uint32_t>(buf_length));
88 static void revert_back_alter(uint8_t* buf, size_t offset) {
89 GPR_ASSERT(buf != nullptr);
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;
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);
141 static void alts_iovec_record_protocol_test_fixture_destroy(
142 alts_iovec_record_protocol_test_fixture* fixture) {
143 if (fixture == nullptr) {
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);
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;
188 static void alts_iovec_record_protocol_test_var_destroy(
189 alts_iovec_record_protocol_test_var* var) {
190 if (var == nullptr) {
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);
202 /* --- Integrity-only protect/unprotect tests. --- */
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
224 GPR_ASSERT(memcmp(var->data_buf, var->dup_buf, var->data_length) == 0);
225 alts_iovec_record_protocol_test_var_destroy(var);
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);
245 static void integrity_only_unsync_seal_unseal(
246 alts_iovec_record_protocol* sender, alts_iovec_record_protocol* receiver) {
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);
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);
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;
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);
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);
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);
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,
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,
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,
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,
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);
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,
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,
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,
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,
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);
422 /* --- Privacy-integrity protect/unprotect tests. --- */
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);
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);
472 gpr_free(protected_buf);
473 alts_iovec_record_protocol_test_var_destroy(var);
476 static void privacy_integrity_unsync_seal_unseal(
477 alts_iovec_record_protocol* sender, alts_iovec_record_protocol* receiver) {
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,
485 GPR_ASSERT(status == GRPC_STATUS_OK);
486 alts_iovec_record_protocol_test_var_destroy(var);
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,
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,
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);
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,
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,
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,
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,
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,
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);
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,
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,
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);
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,
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,
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);
631 /* --- Integrity-only and privacy-integrity mixed. --- */
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);
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);
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,
719 iovec_t tag_iovec = {
720 var->protected_buf + var->header_length + var->data_length,
722 status = alts_iovec_record_protocol_integrity_only_unprotect(
723 integrity_only_receiver, &data_iovec, 1, header_iovec, tag_iovec,
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);
732 /* --- Test cases. --- */
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
917 alts_iovec_record_protocol_test_fixture_destroy(fixture_1);
918 alts_iovec_record_protocol_test_fixture_destroy(fixture_2);
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();