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