• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_CORE_TSI_ALTS_FRAME_PROTECTOR_ALTS_CRYPTER_H
20 #define GRPC_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 the
159  * 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 in-place.
163  * 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_CORE_TSI_ALTS_FRAME_PROTECTOR_ALTS_CRYPTER_H */
256