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 #ifndef GRPC_SRC_CORE_TSI_ALTS_FRAME_PROTECTOR_ALTS_CRYPTER_H
20 #define GRPC_SRC_CORE_TSI_ALTS_FRAME_PROTECTOR_ALTS_CRYPTER_H
21 
22 #include <grpc/support/port_platform.h>
23 
24 #include <stdbool.h>
25 #include <string.h>
26 
27 #include <grpc/grpc.h>
28 
29 #include "src/core/tsi/alts/crypt/gsec.h"
30 
31 ///
32 /// An alts_crypter interface for an ALTS record protocol providing
33 /// seal/unseal functionality. The interface is thread-compatible.
34 ///
35 
36 typedef struct alts_crypter alts_crypter;
37 
38 ///
39 /// A typical usage of the interface would be
40 ///------------------------------------------------------------------------------
41 ///// Perform a seal operation. We assume the gsec_aead_crypter instance -
42 ///// client_aead_crypter is created beforehand with a 16-byte key and 12-byte
43 ///// nonce length.
44 ///
45 /// alts_crypter* client = nullptr;
46 /// char* client_error_in_creation = nullptr;
47 /// unsigned char* data = nullptr;
48 /// grpc_status_code client_status =
49 ///                alts_seal_crypter_create(client_aead_crypter, 1, 5, &client,
50 ///                                         &client_error_in_creation);
51 /// if (client_status == GRPC_STATUS_OK) {
52 ///  size_t data_size = 100;
53 ///  size_t num_overhead_bytes = alts_crypter_num_overhead_bytes(client);
54 ///  size_t data_allocated_size = data_size + num_overhead_bytes;
55 ///  data = gpr_malloc(data_allocated_size);
56 ///  char* client_error_in_seal = nullptr;
57 ///  // Client performs a seal operation.
58 ///  client_status = alts_crypter_process_in_place(client, data,
59 ///                                                data_allocated_size,
60 ///                                                &data_size,
61 ///                                                &client_error_in_seal);
62 ///  if (client_status != GRPC_STATUS_OK) {
63 ///    fprintf(stderr, "seal operation failed with error code:"
64 ///                    "%d, message: %s\n", client_status,
65 ///                     client_error_in_seal);
66 ///   }
67 ///   gpr_free(client_error_in_seal);
68 ///} else {
69 ///    fprintf(stderr, "alts_crypter instance creation failed with error"
70 ///                    "code: %d, message: %s\n", client_status,
71 ///                     client_error_in_creation);
72 ///}
73 ///
74 ///...
75 ///
76 /// gpr_free(client_error_in_creation);
77 /// alts_crypter_destroy(client);
78 ///
79 ///...
80 ///
81 ///// Perform an unseal operation. We assume the gsec_aead_crypter instance -
82 ///// server_aead_crypter is created beforehand with a 16-byte key and 12-byte
83 ///// nonce length. The key used in the creation of gsec_aead_crypter instances
84 ///// at server and client sides should be identical.
85 ///
86 /// alts_crypter* server = nullptr;
87 /// char* server_error_in_creation = nullptr;
88 /// grpc_status_code server_status =
89 ///              alts_unseal_crypter_create(server_aead_crypter, 0, 5, &server,
90 ///                                         &server_error_in_creation);
91 /// if (server_status == GRPC_STATUS_OK) {
92 ///  size_t num_overhead_bytes = alts_crypter_num_overhead_bytes(server);
93 ///  size_t data_size = 100 + num_overhead_bytes;
94 ///  size_t data_allocated_size = data_size;
95 ///  char* server_error_in_unseal = nullptr;
96 ///  // Server performs an unseal operation.
97 ///  server_status = alts_crypter_process_in_place(server, data,
98 ///                                                data_allocated_size,
99 ///                                                &data_size,
100 ///                                                &server_error_in_unseal);
101 ///  if (server_status != GRPC_STATUS_OK) {
102 ///    fprintf(stderr, "unseal operation failed with error code:"
103 ///                    "%d, message: %s\n", server_status,
104 ///                     server_error_in_unseal);
105 ///  }
106 ///  gpr_free(server_error_in_unseal);
107 ///} else {
108 ///    fprintf(stderr, "alts_crypter instance creation failed with error"
109 ///                    "code: %d, message: %s\n", server_status,
110 ///                     server_error_in_creation);
111 ///}
112 ///
113 ///...
114 ///
115 /// gpr_free(data);
116 /// gpr_free(server_error_in_creation);
117 /// alts_crypter_destroy(server);
118 ///
119 ///...
120 ///------------------------------------------------------------------------------
121 ///
122 
123 // V-table for alts_crypter operations
124 typedef struct alts_crypter_vtable {
125   size_t (*num_overhead_bytes)(const alts_crypter* crypter);
126   grpc_status_code (*process_in_place)(alts_crypter* crypter,
127                                        unsigned char* data,
128                                        size_t data_allocated_size,
129                                        size_t data_size, size_t* output_size,
130                                        char** error_details);
131   void (*destruct)(alts_crypter* crypter);
132 } alts_crypter_vtable;
133 
134 // Main struct for alts_crypter interface
135 struct alts_crypter {
136   const alts_crypter_vtable* vtable;
137 };
138 
139 ///
140 /// This method gets the number of overhead bytes needed for sealing data that
141 /// is the difference in size between the protected and raw data. The counter
142 /// value used in a seal or unseal operation is locally maintained (not sent or
143 /// received from the other peer) and therefore, will not be counted as part of
144 /// overhead bytes.
145 ///
146 ///- crypter: an alts_crypter instance.
147 ///
148 /// On success, the method returns the number of overhead bytes. Otherwise, it
149 /// returns zero.
150 ///
151 ///
152 size_t alts_crypter_num_overhead_bytes(const alts_crypter* crypter);
153 
154 ///
155 /// This method performs either a seal or an unseal operation depending on the
156 /// alts_crypter instance - crypter passed to the method. If the crypter is
157 /// an instance implementing a seal operation, the method will perform a seal
158 /// operation. That is, it seals raw data and stores the result in-place, and
159 /// the memory allocated for data must be at least data_length +
160 /// alts_crypter_num_overhead_bytes(). If the crypter is an instance
161 /// implementing an unseal operation, the method will perform an unseal
162 /// operation. That is, it unseals protected data and stores the result
163 /// in-place. The size of unsealed data will be data_length -
164 /// alts_crypter_num_overhead_bytes(). Integrity tag will be verified during
165 /// the unseal operation, and if verification fails, the data will be wiped.
166 /// The counters used in both seal and unseal operations are managed internally.
167 ///
168 ///- crypter: an alts_crypter instance.
169 ///- data: if the method performs a seal operation, the data represents raw data
170 ///  that needs to be sealed. It also plays the role of buffer to hold the
171 ///  protected data as a result of seal. If the method performs an unseal
172 ///  operation, the data represents protected data that needs to be unsealed. It
173 ///  also plays the role of buffer to hold raw data as a result of unseal.
174 ///- data_allocated_size: the size of data buffer. The parameter is used to
175 ///  check whether the result of either seal or unseal can be safely written to
176 ///  the data buffer.
177 ///- data_size: if the method performs a seal operation, data_size
178 ///  represents the size of raw data that needs to be sealed, and if the method
179 ///  performs an unseal operation, data_size represents the size of protected
180 ///  data that needs to be unsealed.
181 ///- output_size: size of data written to the data buffer after a seal or an
182 ///  unseal operation.
183 ///- error_details: a buffer containing an error message if the method does not
184 ///  function correctly. It is legal to pass nullptr into error_details and
185 ///  otherwise, the parameter should be freed with gpr_free.
186 ///
187 /// On success, the method returns GRPC_STATUS_OK. Otherwise,
188 /// it returns an error status code along with its details specified in
189 /// error_details (if error_details is not nullptr).
190 ///
191 grpc_status_code alts_crypter_process_in_place(
192     alts_crypter* crypter, unsigned char* data, size_t data_allocated_size,
193     size_t data_size, size_t* output_size, char** error_details);
194 
195 ///
196 /// This method creates an alts_crypter instance to be used to perform a seal
197 /// operation, given a gsec_aead_crypter instance and a flag indicating if the
198 /// created instance will be used at the client or server side. It takes
199 /// ownership of gsec_aead_crypter instance.
200 ///
201 ///- gc: a gsec_aead_crypter instance used to perform AEAD encryption.
202 ///- is_client: a flag indicating if the alts_crypter instance will be
203 ///  used at the client (is_client = true) or server (is_client =
204 ///  false) side.
205 ///- overflow_size: overflow size of counter in bytes.
206 ///- crypter: an alts_crypter instance to be returned from the method.
207 ///- error_details: a buffer containing an error message if the method does
208 ///  not function correctly. It is legal to pass nullptr into error_details, and
209 ///  otherwise, the parameter should be freed with gpr_free.
210 ///
211 /// On success of creation, the method returns GRPC_STATUS_OK.
212 /// Otherwise, it returns an error status code along with its details specified
213 /// in error_details (if error_details is not nullptr).
214 ///
215 grpc_status_code alts_seal_crypter_create(gsec_aead_crypter* gc, bool is_client,
216                                           size_t overflow_size,
217                                           alts_crypter** crypter,
218                                           char** error_details);
219 
220 ///
221 /// This method creates an alts_crypter instance used to perform an unseal
222 /// operation, given a gsec_aead_crypter instance and a flag indicating if the
223 /// created instance will be used at the client or server side. It takes
224 /// ownership of gsec_aead_crypter instance.
225 ///
226 ///- gc: a gsec_aead_crypter instance used to perform AEAD decryption.
227 ///- is_client: a flag indicating if the alts_crypter instance will be
228 ///  used at the client (is_client = true) or server (is_client =
229 ///  false) side.
230 ///- overflow_size: overflow size of counter in bytes.
231 ///- crypter: an alts_crypter instance to be returned from the method.
232 ///- error_details: a buffer containing an error message if the method does
233 ///  not function correctly. It is legal to pass nullptr into error_details, and
234 ///  otherwise, the parameter should be freed with gpr_free.
235 ///
236 /// On success of creation, the method returns GRPC_STATUS_OK.
237 /// Otherwise, it returns an error status code along with its details specified
238 /// in error_details (if error_details is not nullptr).
239 ///
240 grpc_status_code alts_unseal_crypter_create(gsec_aead_crypter* gc,
241                                             bool is_client,
242                                             size_t overflow_size,
243                                             alts_crypter** crypter,
244                                             char** error_details);
245 
246 ///
247 /// This method destroys an alts_crypter instance by de-allocating all of its
248 /// occupied memory. A gsec_aead_crypter instance passed in at alts_crypter
249 /// instance creation time will be destroyed in this method.
250 ///
251 ///- crypter: an alts_crypter instance.
252 ///
253 void alts_crypter_destroy(alts_crypter* crypter);
254 
255 #endif  // GRPC_SRC_CORE_TSI_ALTS_FRAME_PROTECTOR_ALTS_CRYPTER_H
256