aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/tsi/alts/frame_protector/alts_crypter.h
blob: 3140778f4fc594f0ee37d6d21a7d045e4d73933b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
/*
 *
 * Copyright 2018 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#ifndef GRPC_CORE_TSI_ALTS_FRAME_PROTECTOR_ALTS_CRYPTER_H
#define GRPC_CORE_TSI_ALTS_FRAME_PROTECTOR_ALTS_CRYPTER_H

#include <grpc/support/port_platform.h>

#include <stdbool.h>
#include <string.h>

#include <grpc/grpc.h>

#include "src/core/tsi/alts/crypt/gsec.h"

/**
 * An alts_crypter interface for an ALTS record protocol providing
 * seal/unseal functionality. The interface is thread-compatible.
 */

typedef struct alts_crypter alts_crypter;

/**
 * A typical usage of the interface would be
 *------------------------------------------------------------------------------
 * // Perform a seal operation. We assume the gsec_aead_crypter instance -
 * // client_aead_crypter is created beforehand with a 16-byte key and 12-byte
 * // nonce length.
 *
 * alts_crypter* client = nullptr;
 * char* client_error_in_creation = nullptr;
 * unsigned char* data = nullptr;
 * grpc_status_code client_status =
 *                 alts_seal_crypter_create(client_aead_crypter, 1, 5, &client,
 *                                          &client_error_in_creation);
 * if (client_status == GRPC_STATUS_OK) {
 *   size_t data_size = 100;
 *   size_t num_overhead_bytes = alts_crypter_num_overhead_bytes(client);
 *   size_t data_allocated_size = data_size + num_overhead_bytes;
 *   data = gpr_malloc(data_allocated_size);
 *   char* client_error_in_seal = nullptr;
 *   // Client performs a seal operation.
 *   client_status = alts_crypter_process_in_place(client, data,
 *                                                 data_allocated_size,
 *                                                 &data_size,
 *                                                 &client_error_in_seal);
 *   if (client_status != GRPC_STATUS_OK) {
 *     fprintf(stderr, "seal operation failed with error code:"
 *                     "%d, message: %s\n", client_status,
 *                      client_error_in_seal);
 *    }
 *    gpr_free(client_error_in_seal);
 * } else {
 *     fprintf(stderr, "alts_crypter instance creation failed with error"
 *                     "code: %d, message: %s\n", client_status,
 *                      client_error_in_creation);
 * }
 *
 * ...
 *
 * gpr_free(client_error_in_creation);
 * alts_crypter_destroy(client);
 *
 * ...
 *
 * // Perform an unseal operation. We assume the gsec_aead_crypter instance -
 * // server_aead_crypter is created beforehand with a 16-byte key and 12-byte
 * // nonce length. The key used in the creation of gsec_aead_crypter instances
 * // at server and client sides should be identical.
 *
 * alts_crypter* server = nullptr;
 * char* server_error_in_creation = nullptr;
 * grpc_status_code server_status =
 *               alts_unseal_crypter_create(server_aead_crypter, 0, 5, &server,
 *                                          &server_error_in_creation);
 * if (server_status == GRPC_STATUS_OK) {
 *   size_t num_overhead_bytes = alts_crypter_num_overhead_bytes(server);
 *   size_t data_size = 100 + num_overhead_bytes;
 *   size_t data_allocated_size = data_size;
 *   char* server_error_in_unseal = nullptr;
 *   // Server performs an unseal operation.
 *   server_status = alts_crypter_process_in_place(server, data,
 *                                                 data_allocated_size,
 *                                                 &data_size,
 *                                                 &server_error_in_unseal);
 *   if (server_status != GRPC_STATUS_OK) {
 *     fprintf(stderr, "unseal operation failed with error code:"
 *                     "%d, message: %s\n", server_status,
 *                      server_error_in_unseal);
 *   }
 *   gpr_free(server_error_in_unseal);
 * } else {
 *     fprintf(stderr, "alts_crypter instance creation failed with error"
 *                     "code: %d, message: %s\n", server_status,
 *                      server_error_in_creation);
 * }
 *
 * ...
 *
 * gpr_free(data);
 * gpr_free(server_error_in_creation);
 * alts_crypter_destroy(server);
 *
 * ...
 *------------------------------------------------------------------------------
 */

/* V-table for alts_crypter operations */
typedef struct alts_crypter_vtable {
  size_t (*num_overhead_bytes)(const alts_crypter* crypter);
  grpc_status_code (*process_in_place)(alts_crypter* crypter,
                                       unsigned char* data,
                                       size_t data_allocated_size,
                                       size_t data_size, size_t* output_size,
                                       char** error_details);
  void (*destruct)(alts_crypter* crypter);
} alts_crypter_vtable;

/* Main struct for alts_crypter interface */
struct alts_crypter {
  const alts_crypter_vtable* vtable;
};

/**
 * This method gets the number of overhead bytes needed for sealing data that
 * is the difference in size between the protected and raw data. The counter
 * value used in a seal or unseal operation is locally maintained (not sent or
 * received from the other peer) and therefore, will not be counted as part of
 * overhead bytes.
 *
 * - crypter: an alts_crypter instance.
 *
 * On success, the method returns the number of overhead bytes. Otherwise, it
 * returns zero.
 *
 */
size_t alts_crypter_num_overhead_bytes(const alts_crypter* crypter);

/**
 * This method performs either a seal or an unseal operation depending on the
 * alts_crypter instance - crypter passed to the method. If the crypter is
 * an instance implementing a seal operation, the method will perform a seal
 * operation. That is, it seals raw data and stores the result in-place, and the
 * memory allocated for data must be at least data_length +
 * alts_crypter_num_overhead_bytes(). If the crypter is an instance
 * implementing an unseal operation, the method will perform an unseal
 * operation. That is, it unseals protected data and stores the result in-place.
 * The size of unsealed data will be data_length -
 * alts_crypter_num_overhead_bytes(). Integrity tag will be verified during
 * the unseal operation, and if verification fails, the data will be wiped.
 * The counters used in both seal and unseal operations are managed internally.
 *
 * - crypter: an alts_crypter instance.
 * - data: if the method performs a seal operation, the data represents raw data
 *   that needs to be sealed. It also plays the role of buffer to hold the
 *   protected data as a result of seal. If the method performs an unseal
 *   operation, the data represents protected data that needs to be unsealed. It
 *   also plays the role of buffer to hold raw data as a result of unseal.
 * - data_allocated_size: the size of data buffer. The parameter is used to
 *   check whether the result of either seal or unseal can be safely written to
 *   the data buffer.
 * - data_size: if the method performs a seal operation, data_size
 *   represents the size of raw data that needs to be sealed, and if the method
 *   performs an unseal operation, data_size represents the size of protected
 *   data that needs to be unsealed.
 * - output_size: size of data written to the data buffer after a seal or an
 *   unseal operation.
 * - error_details: a buffer containing an error message if the method does not
 *   function correctly. It is legal to pass nullptr into error_details and
 *   otherwise, the parameter should be freed with gpr_free.
 *
 * On success, the method returns GRPC_STATUS_OK. Otherwise,
 * it returns an error status code along with its details specified in
 * error_details (if error_details is not nullptr).
 */
grpc_status_code alts_crypter_process_in_place(
    alts_crypter* crypter, unsigned char* data, size_t data_allocated_size,
    size_t data_size, size_t* output_size, char** error_details);

/**
 * This method creates an alts_crypter instance to be used to perform a seal
 * operation, given a gsec_aead_crypter instance and a flag indicating if the
 * created instance will be used at the client or server side. It takes
 * ownership of gsec_aead_crypter instance.
 *
 * - gc: a gsec_aead_crypter instance used to perform AEAD encryption.
 * - is_client: a flag indicating if the alts_crypter instance will be
 *   used at the client (is_client = true) or server (is_client =
 *   false) side.
 * - overflow_size: overflow size of counter in bytes.
 * - crypter: an alts_crypter instance to be returned from the method.
 * - error_details: a buffer containing an error message if the method does
 *   not function correctly. It is legal to pass nullptr into error_details, and
 *   otherwise, the parameter should be freed with gpr_free.
 *
 * On success of creation, the method returns GRPC_STATUS_OK.
 * Otherwise, it returns an error status code along with its details specified
 * in error_details (if error_details is not nullptr).
 */
grpc_status_code alts_seal_crypter_create(gsec_aead_crypter* gc, bool is_client,
                                          size_t overflow_size,
                                          alts_crypter** crypter,
                                          char** error_details);

/**
 * This method creates an alts_crypter instance used to perform an unseal
 * operation, given a gsec_aead_crypter instance and a flag indicating if the
 * created instance will be used at the client or server side. It takes
 * ownership of gsec_aead_crypter instance.
 *
 * - gc: a gsec_aead_crypter instance used to perform AEAD decryption.
 * - is_client: a flag indicating if the alts_crypter instance will be
 *   used at the client (is_client = true) or server (is_client =
 *   false) side.
 * - overflow_size: overflow size of counter in bytes.
 * - crypter: an alts_crypter instance to be returned from the method.
 * - error_details: a buffer containing an error message if the method does
 *   not function correctly. It is legal to pass nullptr into error_details, and
 *   otherwise, the parameter should be freed with gpr_free.
 *
 * On success of creation, the method returns GRPC_STATUS_OK.
 * Otherwise, it returns an error status code along with its details specified
 * in error_details (if error_details is not nullptr).
 */
grpc_status_code alts_unseal_crypter_create(gsec_aead_crypter* gc,
                                            bool is_client,
                                            size_t overflow_size,
                                            alts_crypter** crypter,
                                            char** error_details);

/**
 * This method destroys an alts_crypter instance by de-allocating all of its
 * occupied memory. A gsec_aead_crypter instance passed in at alts_crypter
 * instance creation time will be destroyed in this method.
 *
 * - crypter: an alts_crypter instance.
 */
void alts_crypter_destroy(alts_crypter* crypter);

#endif /* GRPC_CORE_TSI_ALTS_FRAME_PROTECTOR_ALTS_CRYPTER_H */