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