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 <grpc/support/port_platform.h>
21 #include "src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.h"
23 #include <grpc/support/alloc.h>
24 #include <grpc/support/log.h>
26 #include "src/core/lib/slice/slice_internal.h"
27 #include "src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.h"
28 #include "src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.h"
30 /* Privacy-integrity alts_grpc_record_protocol object uses the same struct
31 * defined in alts_grpc_record_protocol_common.h. */
33 /* --- alts_grpc_record_protocol methods implementation. --- */
35 static tsi_result alts_grpc_privacy_integrity_protect(
36 alts_grpc_record_protocol* rp, grpc_slice_buffer* unprotected_slices,
37 grpc_slice_buffer* protected_slices) {
38 /* Input sanity check. */
39 if (rp == nullptr || unprotected_slices == nullptr ||
40 protected_slices == nullptr) {
42 "Invalid nullptr arguments to alts_grpc_record_protocol protect.");
43 return TSI_INVALID_ARGUMENT;
45 /* Allocates memory for output frame. In privacy-integrity protect, the
46 * protected frame is stored in a newly allocated buffer. */
47 size_t protected_frame_size =
48 unprotected_slices->length + rp->header_length +
49 alts_iovec_record_protocol_get_tag_length(rp->iovec_rp);
50 grpc_slice protected_slice = GRPC_SLICE_MALLOC(protected_frame_size);
51 iovec_t protected_iovec = {GRPC_SLICE_START_PTR(protected_slice),
52 GRPC_SLICE_LENGTH(protected_slice)};
53 /* Calls alts_iovec_record_protocol protect. */
54 char* error_details = nullptr;
55 alts_grpc_record_protocol_convert_slice_buffer_to_iovec(rp,
57 grpc_status_code status =
58 alts_iovec_record_protocol_privacy_integrity_protect(
59 rp->iovec_rp, rp->iovec_buf, unprotected_slices->count,
60 protected_iovec, &error_details);
61 if (status != GRPC_STATUS_OK) {
62 gpr_log(GPR_ERROR, "Failed to protect, %s", error_details);
63 gpr_free(error_details);
64 grpc_slice_unref_internal(protected_slice);
65 return TSI_INTERNAL_ERROR;
67 grpc_slice_buffer_add(protected_slices, protected_slice);
68 grpc_slice_buffer_reset_and_unref_internal(unprotected_slices);
72 static tsi_result alts_grpc_privacy_integrity_unprotect(
73 alts_grpc_record_protocol* rp, grpc_slice_buffer* protected_slices,
74 grpc_slice_buffer* unprotected_slices) {
75 /* Input sanity check. */
76 if (rp == nullptr || protected_slices == nullptr ||
77 unprotected_slices == nullptr) {
80 "Invalid nullptr arguments to alts_grpc_record_protocol unprotect.");
81 return TSI_INVALID_ARGUMENT;
83 /* Allocates memory for output frame. In privacy-integrity unprotect, the
84 * unprotected data are stored in a newly allocated buffer. */
85 if (protected_slices->length < rp->header_length + rp->tag_length) {
86 gpr_log(GPR_ERROR, "Protected slices do not have sufficient data.");
87 return TSI_INVALID_ARGUMENT;
89 size_t unprotected_frame_size =
90 protected_slices->length - rp->header_length - rp->tag_length;
91 grpc_slice unprotected_slice = GRPC_SLICE_MALLOC(unprotected_frame_size);
92 iovec_t unprotected_iovec = {GRPC_SLICE_START_PTR(unprotected_slice),
93 GRPC_SLICE_LENGTH(unprotected_slice)};
94 /* Strips frame header from protected slices. */
95 grpc_slice_buffer_reset_and_unref_internal(&rp->header_sb);
96 grpc_slice_buffer_move_first(protected_slices, rp->header_length,
98 iovec_t header_iovec = alts_grpc_record_protocol_get_header_iovec(rp);
99 /* Calls alts_iovec_record_protocol unprotect. */
100 char* error_details = nullptr;
101 alts_grpc_record_protocol_convert_slice_buffer_to_iovec(rp, protected_slices);
102 grpc_status_code status =
103 alts_iovec_record_protocol_privacy_integrity_unprotect(
104 rp->iovec_rp, header_iovec, rp->iovec_buf, protected_slices->count,
105 unprotected_iovec, &error_details);
106 if (status != GRPC_STATUS_OK) {
107 gpr_log(GPR_ERROR, "Failed to unprotect, %s", error_details);
108 gpr_free(error_details);
109 grpc_slice_unref_internal(unprotected_slice);
110 return TSI_INTERNAL_ERROR;
112 grpc_slice_buffer_reset_and_unref_internal(&rp->header_sb);
113 grpc_slice_buffer_reset_and_unref_internal(protected_slices);
114 grpc_slice_buffer_add(unprotected_slices, unprotected_slice);
118 static const alts_grpc_record_protocol_vtable
119 alts_grpc_privacy_integrity_record_protocol_vtable = {
120 alts_grpc_privacy_integrity_protect,
121 alts_grpc_privacy_integrity_unprotect, nullptr};
123 tsi_result alts_grpc_privacy_integrity_record_protocol_create(
124 gsec_aead_crypter* crypter, size_t overflow_size, bool is_client,
125 bool is_protect, alts_grpc_record_protocol** rp) {
126 if (crypter == nullptr || rp == nullptr) {
128 "Invalid nullptr arguments to alts_grpc_record_protocol create.");
129 return TSI_INVALID_ARGUMENT;
131 auto* impl = static_cast<alts_grpc_record_protocol*>(
132 gpr_zalloc(sizeof(alts_grpc_record_protocol)));
133 /* Calls alts_grpc_record_protocol init. */
135 alts_grpc_record_protocol_init(impl, crypter, overflow_size, is_client,
136 /*is_integrity_only=*/false, is_protect);
137 if (result != TSI_OK) {
141 impl->vtable = &alts_grpc_privacy_integrity_record_protocol_vtable;