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_CRYPT_GSEC_H 20 #define GRPC_SRC_CORE_TSI_ALTS_CRYPT_GSEC_H 21 22 #include <grpc/support/port_platform.h> 23 24 #include <assert.h> 25 #include <stdint.h> 26 #include <stdlib.h> 27 28 #include <grpc/event_engine/port.h> 29 #include <grpc/grpc.h> 30 31 #ifndef _STRUCT_IOVEC 32 #if !defined(GRPC_EVENT_ENGINE_POSIX) 33 struct iovec { 34 void* iov_base; 35 size_t iov_len; 36 }; 37 #endif // GRPC_EVENT_ENGINE_POSIX 38 #endif // _STRUCT_IOVEC 39 40 /// 41 /// A gsec interface for AEAD encryption schemes. The API is thread-compatible. 42 /// Each implementation of this interface should specify supported values for 43 /// key, nonce, and tag lengths. 44 /// 45 46 // Key, nonce, and tag length in bytes 47 const size_t kAesGcmNonceLength = 12; 48 const size_t kAesGcmTagLength = 16; 49 const size_t kAes128GcmKeyLength = 16; 50 const size_t kAes256GcmKeyLength = 32; 51 52 // The first 32 bytes are used as a KDF key and the remaining 12 bytes are used 53 // to mask the nonce. 54 const size_t kAes128GcmRekeyKeyLength = 44; 55 56 typedef struct gsec_aead_crypter gsec_aead_crypter; 57 58 /// 59 /// The gsec_aead_crypter is an API for different AEAD implementations such as 60 /// AES_GCM. It encapsulates all AEAD-related operations in the format of 61 /// V-table that stores pointers to functions implementing those operations. 62 /// It also provides helper functions to wrap each of those function pointers. 63 /// 64 /// A typical usage of this object would be: 65 /// 66 ///------------------------------------------------------------------------------ 67 ///// Declare a gsec_aead_crypter object, and create and assign an instance 68 ///// of specific AEAD implementation e.g., AES_GCM to it. We assume both 69 ///// key and nonce contain cryptographically secure random bytes, and the key 70 ///// can be derived from an upper-layer application. 71 /// gsec_aead_crypter* crypter; 72 /// char* error_in_creation; 73 ///// User can populate the message with any 100 bytes data. 74 /// uint8_t* message = gpr_malloc(100); 75 /// grpc_status_code creation_status = gsec_aes_gcm_aead_crypter_create(key, 76 /// kAes128GcmKeyLength, 77 /// kAesGcmNonceLength, 78 /// kAesGcmTagLength, 79 /// &crypter, 80 /// false, 81 /// 0 82 /// &error_in_creation); 83 /// 84 /// if (creation_status == GRPC_STATUS_OK) { 85 /// // Allocate a correct amount of memory to hold a ciphertext. 86 /// size_t clength = 0; 87 /// gsec_aead_crypter_max_ciphertext_and_tag_length(crypter, 100, &clength, 88 /// nullptr); 89 /// uint8_t* ciphertext = gpr_malloc(clength); 90 /// 91 /// // Perform encryption 92 /// size_t num_encrypted_bytes = 0; 93 /// char* error_in_encryption = nullptr; 94 /// grpc_status_code status = gsec_aead_crypter_encrypt(crypter, nonce, 95 /// kAesGcmNonceLength, 96 /// nullptr, 0, message, 97 /// 100, ciphertext, 98 /// clength, 99 /// &num_encrypted_bytes, 100 /// &error_in_encryption); 101 /// if (status == GRPC_STATUS_OK) { 102 /// // Allocate a correct amount of memory to hold a plaintext. 103 /// size_t plength = 0; 104 /// gsec_aead_crypter_max_plaintext_length(crypter, num_encrypted_bytes, 105 /// &plength, nullptr); 106 /// uint8_t* plaintext = gpr_malloc(plength); 107 /// 108 /// // Perform decryption. 109 /// size_t num_decrypted_bytes = 0; 110 /// char* error_in_decryption = nullptr; 111 /// status = gsec_aead_crypter_decrypt(crypter, nonce, 112 /// kAesGcmNonceLength, nullptr, 0, 113 /// ciphertext, num_encrypted_bytes, 114 /// plaintext, plength, 115 /// &num_decrypted_bytes, 116 /// &error_in_decryption); 117 /// if (status != GRPC_STATUS_OK) { 118 /// fprintf(stderr, "AEAD decrypt operation failed with error code:" 119 /// "%d, message: %s\n", status, error_in_decryption); 120 /// } 121 /// ... 122 /// gpr_free(plaintext); 123 /// gpr_free(error_in_decryption); 124 /// } else { 125 /// fprintf(stderr, "AEAD encrypt operation failed with error code:" 126 /// "%d, message: %s\n", status, error_in_encryption); 127 /// } 128 /// ... 129 /// gpr_free(ciphertext); 130 /// gpr_free(error_in_encryption); 131 ///} else { 132 /// fprintf(stderr, "Creation of AEAD crypter instance failed with error code:" 133 /// "%d, message: %s\n", creation_status, error_in_creation); 134 ///} 135 /// 136 ///// Destruct AEAD crypter instance. 137 /// if (creation_status == GRPC_STATUS_OK) { 138 /// gsec_aead_crypter_destroy(crypter); 139 ///} 140 /// gpr_free(error_in_creation); 141 /// gpr_free(message); 142 ///----------------------------------------------------------------------------- 143 /// 144 145 // V-table for gsec AEAD operations 146 typedef struct gsec_aead_crypter_vtable { 147 grpc_status_code (*encrypt_iovec)( 148 gsec_aead_crypter* crypter, const uint8_t* nonce, size_t nonce_length, 149 const struct iovec* aad_vec, size_t aad_vec_length, 150 const struct iovec* plaintext_vec, size_t plaintext_vec_length, 151 struct iovec ciphertext_vec, size_t* ciphertext_bytes_written, 152 char** error_details); 153 grpc_status_code (*decrypt_iovec)( 154 gsec_aead_crypter* crypter, const uint8_t* nonce, size_t nonce_length, 155 const struct iovec* aad_vec, size_t aad_vec_length, 156 const struct iovec* ciphertext_vec, size_t ciphertext_vec_length, 157 struct iovec plaintext_vec, size_t* plaintext_bytes_written, 158 char** error_details); 159 grpc_status_code (*max_ciphertext_and_tag_length)( 160 const gsec_aead_crypter* crypter, size_t plaintext_length, 161 size_t* max_ciphertext_and_tag_length_to_return, char** error_details); 162 grpc_status_code (*max_plaintext_length)( 163 const gsec_aead_crypter* crypter, size_t ciphertext_and_tag_length, 164 size_t* max_plaintext_length_to_return, char** error_details); 165 grpc_status_code (*nonce_length)(const gsec_aead_crypter* crypter, 166 size_t* nonce_length_to_return, 167 char** error_details); 168 grpc_status_code (*key_length)(const gsec_aead_crypter* crypter, 169 size_t* key_length_to_return, 170 char** error_details); 171 grpc_status_code (*tag_length)(const gsec_aead_crypter* crypter, 172 size_t* tag_length_to_return, 173 char** error_details); 174 void (*destruct)(gsec_aead_crypter* crypter); 175 } gsec_aead_crypter_vtable; 176 177 // Main struct for gsec interface 178 struct gsec_aead_crypter { 179 const struct gsec_aead_crypter_vtable* vtable; 180 }; 181 182 /// 183 /// This method performs an AEAD encrypt operation. 184 /// 185 ///- crypter: AEAD crypter instance. 186 ///- nonce: buffer containing a nonce with its size equal to nonce_length. 187 ///- nonce_length: size of nonce buffer, and must be equal to the value returned 188 /// from method gsec_aead_crypter_nonce_length. 189 ///- aad: buffer containing data that needs to be authenticated but not 190 /// encrypted with its size equal to aad_length. 191 ///- aad_length: size of aad buffer, which should be zero if the buffer is 192 /// nullptr. 193 ///- plaintext: buffer containing data that needs to be both encrypted and 194 /// authenticated with its size equal to plaintext_length. 195 ///- plaintext_length: size of plaintext buffer, which should be zero if 196 /// plaintext is nullptr. 197 ///- ciphertext_and_tag: buffer that will contain ciphertext and tags the method 198 /// produced. The buffer should not overlap the plaintext buffer, and pointers 199 /// to those buffers should not be equal. Also if the ciphertext+tag buffer is 200 /// nullptr, the plaintext_length should be zero. 201 ///- ciphertext_and_tag_length: size of ciphertext+tag buffer, which should be 202 /// at least as long as the one returned from method 203 /// gsec_aead_crypter_max_ciphertext_and_tag_length. 204 ///- bytes_written: the actual number of bytes written to the ciphertext+tag 205 /// buffer. If bytes_written is nullptr, the plaintext_length should be zero. 206 ///- error_details: a buffer containing an error message if the method does not 207 /// function correctly. It is legal to pass nullptr into error_details, and 208 /// otherwise, the parameter should be freed with gpr_free. 209 /// 210 /// On the success of encryption, the method returns GRPC_STATUS_OK. Otherwise, 211 /// it returns an error status code along with its details specified in 212 /// error_details (if error_details is not nullptr). 213 /// 214 /// 215 grpc_status_code gsec_aead_crypter_encrypt( 216 gsec_aead_crypter* crypter, const uint8_t* nonce, size_t nonce_length, 217 const uint8_t* aad, size_t aad_length, const uint8_t* plaintext, 218 size_t plaintext_length, uint8_t* ciphertext_and_tag, 219 size_t ciphertext_and_tag_length, size_t* bytes_written, 220 char** error_details); 221 222 /// 223 /// This method performs an AEAD encrypt operation. 224 /// 225 ///- crypter: AEAD crypter instance. 226 ///- nonce: buffer containing a nonce with its size equal to nonce_length. 227 ///- nonce_length: size of nonce buffer, and must be equal to the value returned 228 /// from method gsec_aead_crypter_nonce_length. 229 ///- aad_vec: an iovec array containing data that needs to be authenticated but 230 /// not encrypted. 231 ///- aad_vec_length: the array length of aad_vec. 232 ///- plaintext_vec: an iovec array containing data that needs to be both 233 /// encrypted and authenticated. 234 ///- plaintext_vec_length: the array length of plaintext_vec. 235 ///- ciphertext_vec: an iovec containing a ciphertext buffer. The buffer should 236 /// not overlap the plaintext buffer. 237 ///- ciphertext_bytes_written: the actual number of bytes written to 238 /// ciphertext_vec. 239 ///- error_details: a buffer containing an error message if the method does not 240 /// function correctly. It is legal to pass nullptr into error_details, and 241 /// otherwise, the parameter should be freed with gpr_free. 242 /// 243 /// On the success of encryption, the method returns GRPC_STATUS_OK. Otherwise, 244 /// it returns an error status code along with its details specified in 245 /// error_details (if error_details is not nullptr). 246 /// 247 /// 248 grpc_status_code gsec_aead_crypter_encrypt_iovec( 249 gsec_aead_crypter* crypter, const uint8_t* nonce, size_t nonce_length, 250 const struct iovec* aad_vec, size_t aad_vec_length, 251 const struct iovec* plaintext_vec, size_t plaintext_vec_length, 252 struct iovec ciphertext_vec, size_t* ciphertext_bytes_written, 253 char** error_details); 254 255 /// 256 /// This method performs an AEAD decrypt operation. 257 /// 258 ///- crypter: AEAD crypter instance. 259 ///- nonce: buffer containing a nonce with its size equal to nonce_length. 260 ///- nonce_length: size of nonce buffer, and must be equal to the value returned 261 /// from method gsec_aead_crypter_nonce_length. 262 ///- aad: buffer containing data that needs to be authenticated only. 263 ///- aad_length: size of aad buffer, which should be zero if the buffer is 264 /// nullptr. 265 ///- ciphertext_and_tag: buffer containing ciphertext and tag. 266 ///- ciphertext_and_tag_length: length of ciphertext and tag. It should be zero 267 /// if any of plaintext, ciphertext_and_tag, or bytes_written is nullptr. Also, 268 /// ciphertext_and_tag_length should be at least as large as the tag length set 269 /// at AEAD crypter instance construction time. 270 ///- plaintext: buffer containing decrypted and authenticated data the method 271 /// produced. The buffer should not overlap with the ciphertext+tag buffer, and 272 /// pointers to those buffers should not be equal. 273 ///- plaintext_length: size of plaintext buffer, which should be at least as 274 /// long as the one returned from gsec_aead_crypter_max_plaintext_length 275 /// method. 276 ///- bytes_written: the actual number of bytes written to the plaintext 277 /// buffer. 278 ///- error_details: a buffer containing an error message if the method does not 279 /// function correctly. It is legal to pass nullptr into error_details, and 280 /// otherwise, the parameter should be freed with gpr_free. 281 /// 282 /// On the success of decryption, the method returns GRPC_STATUS_OK. Otherwise, 283 /// it returns an error status code along with its details specified in 284 /// error_details (if error_details is not nullptr). 285 /// 286 grpc_status_code gsec_aead_crypter_decrypt( 287 gsec_aead_crypter* crypter, const uint8_t* nonce, size_t nonce_length, 288 const uint8_t* aad, size_t aad_length, const uint8_t* ciphertext_and_tag, 289 size_t ciphertext_and_tag_length, uint8_t* plaintext, 290 size_t plaintext_length, size_t* bytes_written, char** error_details); 291 292 /// 293 /// This method performs an AEAD decrypt operation. 294 /// 295 ///- crypter: AEAD crypter instance. 296 ///- nonce: buffer containing a nonce with its size equal to nonce_length. 297 ///- nonce_length: size of nonce buffer, and must be equal to the value returned 298 /// from method gsec_aead_crypter_nonce_length. 299 ///- aad_vec: an iovec array containing data that needs to be authenticated but 300 /// not encrypted. 301 ///- aad_vec_length: the array length of aad_vec. 302 ///- ciphertext_vec: an iovec array containing the ciphertext and tag. 303 ///- ciphertext_vec_length: the array length of ciphertext_vec. 304 ///- plaintext_vec: an iovec containing a plaintext buffer. The buffer should 305 /// not overlap the ciphertext buffer. 306 ///- plaintext_bytes_written: the actual number of bytes written to 307 /// plaintext_vec. 308 ///- error_details: a buffer containing an error message if the method does not 309 /// function correctly. It is legal to pass nullptr into error_details, and 310 /// otherwise, the parameter should be freed with gpr_free. 311 /// 312 /// On the success of decryption, the method returns GRPC_STATUS_OK. Otherwise, 313 /// it returns an error status code along with its details specified in 314 /// error_details (if error_details is not nullptr). 315 /// 316 grpc_status_code gsec_aead_crypter_decrypt_iovec( 317 gsec_aead_crypter* crypter, const uint8_t* nonce, size_t nonce_length, 318 const struct iovec* aad_vec, size_t aad_vec_length, 319 const struct iovec* ciphertext_vec, size_t ciphertext_vec_length, 320 struct iovec plaintext_vec, size_t* plaintext_bytes_written, 321 char** error_details); 322 323 /// 324 /// This method computes the size of ciphertext+tag buffer that must be passed 325 /// to gsec_aead_crypter_encrypt function to ensure correct encryption of a 326 /// plaintext. The actual size of ciphertext+tag written to the buffer could be 327 /// smaller. 328 /// 329 ///- crypter: AEAD crypter instance. 330 ///- plaintext_length: length of plaintext. 331 ///- max_ciphertext_and_tag_length_to_return: the size of ciphertext+tag buffer 332 /// the method returns. 333 ///- error_details: a buffer containing an error message if the method does not 334 /// function correctly. It is legal to pass nullptr into error_details, and 335 /// otherwise, the parameter should be freed with gpr_free. 336 /// 337 /// On the success of execution, the method returns GRPC_STATUS_OK. Otherwise, 338 /// it returns an error status code along with its details specified in 339 /// error_details (if error_details is not nullptr). 340 /// 341 grpc_status_code gsec_aead_crypter_max_ciphertext_and_tag_length( 342 const gsec_aead_crypter* crypter, size_t plaintext_length, 343 size_t* max_ciphertext_and_tag_length_to_return, char** error_details); 344 345 /// 346 /// This method computes the size of plaintext buffer that must be passed to 347 /// gsec_aead_crypter_decrypt function to ensure correct decryption of a 348 /// ciphertext. The actual size of plaintext written to the buffer could be 349 /// smaller. 350 /// 351 ///- crypter: AEAD crypter instance. 352 ///- ciphertext_and_tag_length: length of ciphertext and tag. 353 ///- max_plaintext_length_to_return: the size of plaintext buffer the method 354 /// returns. 355 ///- error_details: a buffer containing an error message if the method does not 356 /// function correctly. It is legal to pass nullptr into error_details, and 357 /// otherwise, the parameter should be freed with gpr_free. 358 /// 359 /// On the success of execution, the method returns GRPC_STATUS_OK. Otherwise, 360 /// it returns an error status code along with its details specified in 361 /// error_details (if error_details is not nullptr). 362 /// 363 grpc_status_code gsec_aead_crypter_max_plaintext_length( 364 const gsec_aead_crypter* crypter, size_t ciphertext_and_tag_length, 365 size_t* max_plaintext_length_to_return, char** error_details); 366 367 /// 368 /// This method returns a valid size of nonce array used at the construction of 369 /// AEAD crypter instance. It is also the size that should be passed to encrypt 370 /// and decrypt methods executed on the instance. 371 /// 372 ///- crypter: AEAD crypter instance. 373 ///- nonce_length_to_return: the length of nonce array the method returns. 374 ///- error_details: a buffer containing an error message if the method does not 375 /// function correctly. It is legal to pass nullptr into error_details, and 376 /// otherwise, the parameter should be freed with gpr_free. 377 /// 378 /// On the success of execution, the method returns GRPC_STATUS_OK. Otherwise, 379 /// it returns an error status code along with its details specified in 380 /// error_details (if error_details is not nullptr). 381 /// 382 grpc_status_code gsec_aead_crypter_nonce_length( 383 const gsec_aead_crypter* crypter, size_t* nonce_length_to_return, 384 char** error_details); 385 386 /// 387 /// This method returns a valid size of key array used at the construction of 388 /// AEAD crypter instance. It is also the size that should be passed to encrypt 389 /// and decrypt methods executed on the instance. 390 /// 391 ///- crypter: AEAD crypter instance. 392 ///- key_length_to_return: the length of key array the method returns. 393 ///- error_details: a buffer containing an error message if the method does not 394 /// function correctly. It is legal to pass nullptr into error_details, and 395 /// otherwise, the parameter should be freed with gpr_free. 396 /// 397 /// On the success of execution, the method returns GRPC_STATUS_OK. Otherwise, 398 /// it returns an error status code along with its details specified in 399 /// error_details (if error_details is not nullptr). 400 /// 401 grpc_status_code gsec_aead_crypter_key_length(const gsec_aead_crypter* crypter, 402 size_t* key_length_to_return, 403 char** error_details); 404 /// 405 /// This method returns a valid size of tag array used at the construction of 406 /// AEAD crypter instance. It is also the size that should be passed to encrypt 407 /// and decrypt methods executed on the instance. 408 /// 409 ///- crypter: AEAD crypter instance. 410 ///- tag_length_to_return: the length of tag array the method returns. 411 ///- error_details: a buffer containing an error message if the method does not 412 /// function correctly. It is legal to pass nullptr into error_details, and 413 /// otherwise, the parameter should be freed with gpr_free. 414 /// 415 /// On the success of execution, the method returns GRPC_STATUS_OK. Otherwise, 416 /// it returns an error status code along with its details specified in 417 /// error_details (if error_details is not nullptr). 418 /// 419 grpc_status_code gsec_aead_crypter_tag_length(const gsec_aead_crypter* crypter, 420 size_t* tag_length_to_return, 421 char** error_details); 422 423 /// 424 /// This method destroys an AEAD crypter instance by de-allocating all of its 425 /// occupied memory. 426 /// 427 ///- crypter: AEAD crypter instance that needs to be destroyed. 428 /// 429 void gsec_aead_crypter_destroy(gsec_aead_crypter* crypter); 430 431 /// 432 /// This method creates an AEAD crypter instance of AES-GCM encryption scheme 433 /// which supports 16 and 32 bytes long keys, 12 and 16 bytes long nonces, and 434 /// 16 bytes long tags. It should be noted that once the lengths of key, nonce, 435 /// and tag are determined at construction time, they cannot be modified later. 436 /// 437 ///- key: buffer containing a key which is binded with AEAD crypter instance. 438 ///- key_length: length of a key in bytes, which should be 44 if rekeying is 439 /// enabled and 16 or 32 otherwise. 440 ///- nonce_length: length of a nonce in bytes, which should be either 12 or 16. 441 ///- tag_length: length of a tag in bytes, which should be always 16. 442 ///- rekey: enable nonce-based rekeying and nonce-masking. 443 ///- crypter: address of AES_GCM crypter instance returned from the method. 444 ///- error_details: a buffer containing an error message if the method does not 445 /// function correctly. It is legal to pass nullptr into error_details, and 446 /// otherwise, the parameter should be freed with gpr_free. 447 /// 448 /// On success of instance creation, it stores the address of instance at 449 /// crypter. Otherwise, it returns an error status code together with its 450 /// details specified in error_details. 451 /// 452 grpc_status_code gsec_aes_gcm_aead_crypter_create(const uint8_t* key, 453 size_t key_length, 454 size_t nonce_length, 455 size_t tag_length, bool rekey, 456 gsec_aead_crypter** crypter, 457 char** error_details); 458 459 #endif // GRPC_SRC_CORE_TSI_ALTS_CRYPT_GSEC_H 460