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