• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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