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