• 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 #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