3 * Copyright 2018 gRPC authors.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #ifndef GRPC_CORE_TSI_ALTS_CRYPT_GSEC_H
20 #define GRPC_CORE_TSI_ALTS_CRYPT_GSEC_H
22 #include <grpc/support/port_platform.h>
28 #include <grpc/grpc.h>
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.
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;
47 // The first 32 bytes are used as a KDF key and the remaining 12 bytes are used
49 const size_t kAes128GcmRekeyKeyLength = 44;
51 typedef struct gsec_aead_crypter gsec_aead_crypter;
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.
59 * A typical usage of this object would be:
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,
77 * &error_in_creation);
79 * if (creation_status == GRPC_STATUS_OK) {
80 * // Allocate a correct amount of memory to hold a ciphertext.
82 * gsec_aead_crypter_max_ciphertext_and_tag_length(crypter, 100, &clength,
84 * uint8_t* ciphertext = gpr_malloc(clength);
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,
91 * nullptr, 0, message,
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.
99 * gsec_aead_crypter_max_plaintext_length(crypter, num_encrypted_bytes,
100 * &plength, nullptr);
101 * uint8_t* plaintext = gpr_malloc(plength);
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);
117 * gpr_free(plaintext);
118 * gpr_free(error_in_decryption);
120 * fprintf(stderr, "AEAD encrypt operation failed with error code:"
121 * "%d, message: %s\n", status, error_in_encryption);
124 * gpr_free(ciphertext);
125 * gpr_free(error_in_encryption);
127 * fprintf(stderr, "Creation of AEAD crypter instance failed with error code:"
128 * "%d, message: %s\n", creation_status, error_in_creation);
131 * // Destruct AEAD crypter instance.
132 * if (creation_status == GRPC_STATUS_OK) {
133 * gsec_aead_crypter_destroy(crypter);
135 * gpr_free(error_in_creation);
137 * -----------------------------------------------------------------------------
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;
172 /* Main struct for gsec interface */
173 struct gsec_aead_crypter {
174 const struct gsec_aead_crypter_vtable* vtable;
178 * This method performs an AEAD encrypt operation.
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
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.
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).
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);
218 * This method performs an AEAD encrypt operation.
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
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
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.
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).
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);
251 * This method performs an AEAD decrypt operation.
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
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
271 * - bytes_written: the actual number of bytes written to the plaintext
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.
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).
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);
288 * This method performs an AEAD decrypt operation.
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
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
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.
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).
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);
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
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.
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).
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);
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
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
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.
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).
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);
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.
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.
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).
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);
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.
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.
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).
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);
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.
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.
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).
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);
419 * This method destroys an AEAD crypter instance by de-allocating all of its
422 * - crypter: AEAD crypter instance that needs to be destroyed.
424 void gsec_aead_crypter_destroy(gsec_aead_crypter* crypter);
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.
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.
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.
447 grpc_status_code gsec_aes_gcm_aead_crypter_create(const uint8_t* key,
450 size_t tag_length, bool rekey,
451 gsec_aead_crypter** crypter,
452 char** error_details);
454 #endif /* GRPC_CORE_TSI_ALTS_CRYPT_GSEC_H */