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 #include <grpc/support/port_platform.h>
20 
21 #include <string.h>
22 
23 #include <openssl/bio.h>
24 #include <openssl/buffer.h>
25 #include <openssl/err.h>
26 #include <openssl/evp.h>
27 #include <openssl/hmac.h>
28 
29 #include <grpc/support/alloc.h>
30 
31 #include "src/core/tsi/alts/crypt/gsec.h"
32 
33 constexpr size_t kKdfKeyLen = 32;
34 constexpr size_t kKdfCounterLen = 6;
35 constexpr size_t kKdfCounterOffset = 2;
36 constexpr size_t kRekeyAeadKeyLen = kAes128GcmKeyLength;
37 
38 // Struct for additional data required if rekeying is enabled.
39 struct gsec_aes_gcm_aead_rekey_data {
40   uint8_t kdf_counter[kKdfCounterLen];
41   uint8_t nonce_mask[kAesGcmNonceLength];
42 };
43 
44 // Main struct for AES_GCM crypter interface.
45 struct gsec_aes_gcm_aead_crypter {
46   gsec_aead_crypter crypter;
47   size_t key_length;
48   size_t nonce_length;
49   size_t tag_length;
50   uint8_t* key;
51   gsec_aes_gcm_aead_rekey_data* rekey_data;
52   EVP_CIPHER_CTX* ctx;
53 };
54 
aes_gcm_get_openssl_errors()55 static char* aes_gcm_get_openssl_errors() {
56   BIO* bio = BIO_new(BIO_s_mem());
57   ERR_print_errors(bio);
58   BUF_MEM* mem = nullptr;
59   char* error_msg = nullptr;
60   BIO_get_mem_ptr(bio, &mem);
61   if (mem != nullptr) {
62     error_msg = static_cast<char*>(gpr_malloc(mem->length + 1));
63     memcpy(error_msg, mem->data, mem->length);
64     error_msg[mem->length] = '\0';
65   }
66   BIO_free_all(bio);
67   return error_msg;
68 }
69 
aes_gcm_format_errors(const char * error_msg,char ** error_details)70 static void aes_gcm_format_errors(const char* error_msg, char** error_details) {
71   if (error_details == nullptr) {
72     return;
73   }
74   unsigned long error = ERR_get_error();
75   if (error == 0 && error_msg != nullptr) {
76     *error_details = static_cast<char*>(gpr_malloc(strlen(error_msg) + 1));
77     memcpy(*error_details, error_msg, strlen(error_msg) + 1);
78     return;
79   }
80   char* openssl_errors = aes_gcm_get_openssl_errors();
81   if (openssl_errors != nullptr && error_msg != nullptr) {
82     size_t len = strlen(error_msg) + strlen(openssl_errors) + 2;  // ", "
83     *error_details = static_cast<char*>(gpr_malloc(len + 1));
84     snprintf(*error_details, len + 1, "%s, %s", error_msg, openssl_errors);
85     gpr_free(openssl_errors);
86   }
87 }
88 
gsec_aes_gcm_aead_crypter_max_ciphertext_and_tag_length(const gsec_aead_crypter * crypter,size_t plaintext_length,size_t * max_ciphertext_and_tag_length,char ** error_details)89 static grpc_status_code gsec_aes_gcm_aead_crypter_max_ciphertext_and_tag_length(
90     const gsec_aead_crypter* crypter, size_t plaintext_length,
91     size_t* max_ciphertext_and_tag_length, char** error_details) {
92   if (max_ciphertext_and_tag_length == nullptr) {
93     aes_gcm_format_errors("max_ciphertext_and_tag_length is nullptr.",
94                           error_details);
95     return GRPC_STATUS_INVALID_ARGUMENT;
96   }
97   gsec_aes_gcm_aead_crypter* aes_gcm_crypter =
98       reinterpret_cast<gsec_aes_gcm_aead_crypter*>(
99           const_cast<gsec_aead_crypter*>(crypter));
100   *max_ciphertext_and_tag_length =
101       plaintext_length + aes_gcm_crypter->tag_length;
102   return GRPC_STATUS_OK;
103 }
104 
gsec_aes_gcm_aead_crypter_max_plaintext_length(const gsec_aead_crypter * crypter,size_t ciphertext_and_tag_length,size_t * max_plaintext_length,char ** error_details)105 static grpc_status_code gsec_aes_gcm_aead_crypter_max_plaintext_length(
106     const gsec_aead_crypter* crypter, size_t ciphertext_and_tag_length,
107     size_t* max_plaintext_length, char** error_details) {
108   if (max_plaintext_length == nullptr) {
109     aes_gcm_format_errors("max_plaintext_length is nullptr.", error_details);
110     return GRPC_STATUS_INVALID_ARGUMENT;
111   }
112   gsec_aes_gcm_aead_crypter* aes_gcm_crypter =
113       reinterpret_cast<gsec_aes_gcm_aead_crypter*>(
114           const_cast<gsec_aead_crypter*>(crypter));
115   if (ciphertext_and_tag_length < aes_gcm_crypter->tag_length) {
116     *max_plaintext_length = 0;
117     aes_gcm_format_errors(
118         "ciphertext_and_tag_length is smaller than tag_length.", error_details);
119     return GRPC_STATUS_INVALID_ARGUMENT;
120   }
121   *max_plaintext_length =
122       ciphertext_and_tag_length - aes_gcm_crypter->tag_length;
123   return GRPC_STATUS_OK;
124 }
125 
gsec_aes_gcm_aead_crypter_nonce_length(const gsec_aead_crypter * crypter,size_t * nonce_length,char ** error_details)126 static grpc_status_code gsec_aes_gcm_aead_crypter_nonce_length(
127     const gsec_aead_crypter* crypter, size_t* nonce_length,
128     char** error_details) {
129   if (nonce_length == nullptr) {
130     aes_gcm_format_errors("nonce_length is nullptr.", error_details);
131     return GRPC_STATUS_INVALID_ARGUMENT;
132   }
133   gsec_aes_gcm_aead_crypter* aes_gcm_crypter =
134       reinterpret_cast<gsec_aes_gcm_aead_crypter*>(
135           const_cast<gsec_aead_crypter*>(crypter));
136   *nonce_length = aes_gcm_crypter->nonce_length;
137   return GRPC_STATUS_OK;
138 }
139 
gsec_aes_gcm_aead_crypter_key_length(const gsec_aead_crypter * crypter,size_t * key_length,char ** error_details)140 static grpc_status_code gsec_aes_gcm_aead_crypter_key_length(
141     const gsec_aead_crypter* crypter, size_t* key_length,
142     char** error_details) {
143   if (key_length == nullptr) {
144     aes_gcm_format_errors("key_length is nullptr.", error_details);
145     return GRPC_STATUS_INVALID_ARGUMENT;
146   }
147   gsec_aes_gcm_aead_crypter* aes_gcm_crypter =
148       reinterpret_cast<gsec_aes_gcm_aead_crypter*>(
149           const_cast<gsec_aead_crypter*>(crypter));
150   *key_length = aes_gcm_crypter->key_length;
151   return GRPC_STATUS_OK;
152 }
153 
gsec_aes_gcm_aead_crypter_tag_length(const gsec_aead_crypter * crypter,size_t * tag_length,char ** error_details)154 static grpc_status_code gsec_aes_gcm_aead_crypter_tag_length(
155     const gsec_aead_crypter* crypter, size_t* tag_length,
156     char** error_details) {
157   if (tag_length == nullptr) {
158     aes_gcm_format_errors("tag_length is nullptr.", error_details);
159     return GRPC_STATUS_INVALID_ARGUMENT;
160   }
161   gsec_aes_gcm_aead_crypter* aes_gcm_crypter =
162       reinterpret_cast<gsec_aes_gcm_aead_crypter*>(
163           const_cast<gsec_aead_crypter*>(crypter));
164   *tag_length = aes_gcm_crypter->tag_length;
165   return GRPC_STATUS_OK;
166 }
167 
aes_gcm_mask_nonce(uint8_t * dst,const uint8_t * nonce,const uint8_t * mask)168 static void aes_gcm_mask_nonce(uint8_t* dst, const uint8_t* nonce,
169                                const uint8_t* mask) {
170   uint64_t mask1;
171   uint32_t mask2;
172   memcpy(&mask1, mask, sizeof(mask1));
173   memcpy(&mask2, mask + sizeof(mask1), sizeof(mask2));
174   uint64_t nonce1;
175   uint32_t nonce2;
176   memcpy(&nonce1, nonce, sizeof(nonce1));
177   memcpy(&nonce2, nonce + sizeof(nonce1), sizeof(nonce2));
178   nonce1 ^= mask1;
179   nonce2 ^= mask2;
180   memcpy(dst, &nonce1, sizeof(nonce1));
181   memcpy(dst + sizeof(nonce1), &nonce2, sizeof(nonce2));
182 }
183 
aes_gcm_derive_aead_key(uint8_t * dst,const uint8_t * kdf_key,const uint8_t * kdf_counter)184 static grpc_status_code aes_gcm_derive_aead_key(uint8_t* dst,
185                                                 const uint8_t* kdf_key,
186                                                 const uint8_t* kdf_counter) {
187   unsigned char buf[EVP_MAX_MD_SIZE];
188   unsigned char ctr = 1;
189 #if OPENSSL_VERSION_NUMBER < 0x10100000L
190   HMAC_CTX hmac;
191   HMAC_CTX_init(&hmac);
192   if (!HMAC_Init_ex(&hmac, kdf_key, kKdfKeyLen, EVP_sha256(), nullptr) ||
193       !HMAC_Update(&hmac, kdf_counter, kKdfCounterLen) ||
194       !HMAC_Update(&hmac, &ctr, 1) || !HMAC_Final(&hmac, buf, nullptr)) {
195     HMAC_CTX_cleanup(&hmac);
196     return GRPC_STATUS_INTERNAL;
197   }
198   HMAC_CTX_cleanup(&hmac);
199 #else
200   HMAC_CTX* hmac = HMAC_CTX_new();
201   if (hmac == nullptr) {
202     return GRPC_STATUS_INTERNAL;
203   }
204   if (!HMAC_Init_ex(hmac, kdf_key, kKdfKeyLen, EVP_sha256(), nullptr) ||
205       !HMAC_Update(hmac, kdf_counter, kKdfCounterLen) ||
206       !HMAC_Update(hmac, &ctr, 1) || !HMAC_Final(hmac, buf, nullptr)) {
207     HMAC_CTX_free(hmac);
208     return GRPC_STATUS_INTERNAL;
209   }
210   HMAC_CTX_free(hmac);
211 #endif
212   memcpy(dst, buf, kRekeyAeadKeyLen);
213   return GRPC_STATUS_OK;
214 }
215 
aes_gcm_rekey_if_required(gsec_aes_gcm_aead_crypter * aes_gcm_crypter,const uint8_t * nonce,char ** error_details)216 static grpc_status_code aes_gcm_rekey_if_required(
217     gsec_aes_gcm_aead_crypter* aes_gcm_crypter, const uint8_t* nonce,
218     char** error_details) {
219   // If rekey_data is nullptr, then rekeying is not supported and not required.
220   // If bytes 2-7 of kdf_counter differ from the (per message) nonce, then the
221   // encryption key is recomputed from a new kdf_counter to ensure that we don't
222   // encrypt more than 2^16 messages per encryption key (in each direction).
223   if (aes_gcm_crypter->rekey_data == nullptr ||
224       memcmp(aes_gcm_crypter->rekey_data->kdf_counter,
225              nonce + kKdfCounterOffset, kKdfCounterLen) == 0) {
226     return GRPC_STATUS_OK;
227   }
228   memcpy(aes_gcm_crypter->rekey_data->kdf_counter, nonce + kKdfCounterOffset,
229          kKdfCounterLen);
230   uint8_t aead_key[kRekeyAeadKeyLen];
231   if (aes_gcm_derive_aead_key(aead_key, aes_gcm_crypter->key,
232                               aes_gcm_crypter->rekey_data->kdf_counter) !=
233       GRPC_STATUS_OK) {
234     aes_gcm_format_errors("Rekeying failed in key derivation.", error_details);
235     return GRPC_STATUS_INTERNAL;
236   }
237   if (!EVP_DecryptInit_ex(aes_gcm_crypter->ctx, nullptr, nullptr, aead_key,
238                           nullptr)) {
239     aes_gcm_format_errors("Rekeying failed in context update.", error_details);
240     return GRPC_STATUS_INTERNAL;
241   }
242   return GRPC_STATUS_OK;
243 }
244 
gsec_aes_gcm_aead_crypter_encrypt_iovec(gsec_aead_crypter * crypter,const uint8_t * nonce,size_t nonce_length,const struct iovec * aad_vec,size_t aad_vec_length,const struct iovec * plaintext_vec,size_t plaintext_vec_length,struct iovec ciphertext_vec,size_t * ciphertext_bytes_written,char ** error_details)245 static grpc_status_code gsec_aes_gcm_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   gsec_aes_gcm_aead_crypter* aes_gcm_crypter =
252       reinterpret_cast<gsec_aes_gcm_aead_crypter*>(crypter);
253   // Input checks
254   if (nonce == nullptr) {
255     aes_gcm_format_errors("Nonce buffer is nullptr.", error_details);
256     return GRPC_STATUS_INVALID_ARGUMENT;
257   }
258   if (kAesGcmNonceLength != nonce_length) {
259     aes_gcm_format_errors("Nonce buffer has the wrong length.", error_details);
260     return GRPC_STATUS_INVALID_ARGUMENT;
261   }
262   if (aad_vec_length > 0 && aad_vec == nullptr) {
263     aes_gcm_format_errors("Non-zero aad_vec_length but aad_vec is nullptr.",
264                           error_details);
265     return GRPC_STATUS_INVALID_ARGUMENT;
266   }
267   if (plaintext_vec_length > 0 && plaintext_vec == nullptr) {
268     aes_gcm_format_errors(
269         "Non-zero plaintext_vec_length but plaintext_vec is nullptr.",
270         error_details);
271     return GRPC_STATUS_INVALID_ARGUMENT;
272   }
273   if (ciphertext_bytes_written == nullptr) {
274     aes_gcm_format_errors("bytes_written is nullptr.", error_details);
275     return GRPC_STATUS_INVALID_ARGUMENT;
276   }
277   *ciphertext_bytes_written = 0;
278   // rekey if required
279   if (aes_gcm_rekey_if_required(aes_gcm_crypter, nonce, error_details) !=
280       GRPC_STATUS_OK) {
281     return GRPC_STATUS_INTERNAL;
282   }
283   // mask nonce if required
284   const uint8_t* nonce_aead = nonce;
285   uint8_t nonce_masked[kAesGcmNonceLength];
286   if (aes_gcm_crypter->rekey_data != nullptr) {
287     aes_gcm_mask_nonce(nonce_masked, aes_gcm_crypter->rekey_data->nonce_mask,
288                        nonce);
289     nonce_aead = nonce_masked;
290   }
291   // init openssl context
292   if (!EVP_EncryptInit_ex(aes_gcm_crypter->ctx, nullptr, nullptr, nullptr,
293                           nonce_aead)) {
294     aes_gcm_format_errors("Initializing nonce failed", error_details);
295     return GRPC_STATUS_INTERNAL;
296   }
297   // process aad
298   size_t i;
299   for (i = 0; i < aad_vec_length; i++) {
300     const uint8_t* aad = static_cast<uint8_t*>(aad_vec[i].iov_base);
301     size_t aad_length = aad_vec[i].iov_len;
302     if (aad_length == 0) {
303       continue;
304     }
305     size_t aad_bytes_read = 0;
306     if (aad == nullptr) {
307       aes_gcm_format_errors("aad is nullptr.", error_details);
308       return GRPC_STATUS_INVALID_ARGUMENT;
309     }
310     if (!EVP_EncryptUpdate(aes_gcm_crypter->ctx, nullptr,
311                            reinterpret_cast<int*>(&aad_bytes_read), aad,
312                            static_cast<int>(aad_length)) ||
313         aad_bytes_read != aad_length) {
314       aes_gcm_format_errors("Setting authenticated associated data failed",
315                             error_details);
316       return GRPC_STATUS_INTERNAL;
317     }
318   }
319   uint8_t* ciphertext = static_cast<uint8_t*>(ciphertext_vec.iov_base);
320   size_t ciphertext_length = ciphertext_vec.iov_len;
321   if (ciphertext == nullptr) {
322     aes_gcm_format_errors("ciphertext is nullptr.", error_details);
323     return GRPC_STATUS_INVALID_ARGUMENT;
324   }
325   // process plaintext
326   for (i = 0; i < plaintext_vec_length; i++) {
327     const uint8_t* plaintext = static_cast<uint8_t*>(plaintext_vec[i].iov_base);
328     size_t plaintext_length = plaintext_vec[i].iov_len;
329     if (plaintext == nullptr) {
330       if (plaintext_length == 0) {
331         continue;
332       }
333       aes_gcm_format_errors("plaintext is nullptr.", error_details);
334       return GRPC_STATUS_INVALID_ARGUMENT;
335     }
336     if (ciphertext_length < plaintext_length) {
337       aes_gcm_format_errors(
338           "ciphertext is not large enough to hold the result.", error_details);
339       return GRPC_STATUS_INVALID_ARGUMENT;
340     }
341     int bytes_written = 0;
342     int bytes_to_write = static_cast<int>(plaintext_length);
343     if (!EVP_EncryptUpdate(aes_gcm_crypter->ctx, ciphertext, &bytes_written,
344                            plaintext, bytes_to_write)) {
345       aes_gcm_format_errors("Encrypting plaintext failed.", error_details);
346       return GRPC_STATUS_INTERNAL;
347     }
348     if (bytes_written > bytes_to_write) {
349       aes_gcm_format_errors("More bytes written than expected.", error_details);
350       return GRPC_STATUS_INTERNAL;
351     }
352     ciphertext += bytes_written;
353     ciphertext_length -= bytes_written;
354   }
355   int bytes_written_temp = 0;
356   if (!EVP_EncryptFinal_ex(aes_gcm_crypter->ctx, nullptr,
357                            &bytes_written_temp)) {
358     aes_gcm_format_errors("Finalizing encryption failed.", error_details);
359     return GRPC_STATUS_INTERNAL;
360   }
361   if (bytes_written_temp != 0) {
362     aes_gcm_format_errors("Openssl wrote some unexpected bytes.",
363                           error_details);
364     return GRPC_STATUS_INTERNAL;
365   }
366   if (ciphertext_length < kAesGcmTagLength) {
367     aes_gcm_format_errors("ciphertext is too small to hold a tag.",
368                           error_details);
369     return GRPC_STATUS_INVALID_ARGUMENT;
370   }
371 
372   if (!EVP_CIPHER_CTX_ctrl(aes_gcm_crypter->ctx, EVP_CTRL_GCM_GET_TAG,
373                            kAesGcmTagLength, ciphertext)) {
374     aes_gcm_format_errors("Writing tag failed.", error_details);
375     return GRPC_STATUS_INTERNAL;
376   }
377   ciphertext += kAesGcmTagLength;
378   ciphertext_length -= kAesGcmTagLength;
379   *ciphertext_bytes_written = ciphertext_vec.iov_len - ciphertext_length;
380   return GRPC_STATUS_OK;
381 }
382 
gsec_aes_gcm_aead_crypter_decrypt_iovec(gsec_aead_crypter * crypter,const uint8_t * nonce,size_t nonce_length,const struct iovec * aad_vec,size_t aad_vec_length,const struct iovec * ciphertext_vec,size_t ciphertext_vec_length,struct iovec plaintext_vec,size_t * plaintext_bytes_written,char ** error_details)383 static grpc_status_code gsec_aes_gcm_aead_crypter_decrypt_iovec(
384     gsec_aead_crypter* crypter, const uint8_t* nonce, size_t nonce_length,
385     const struct iovec* aad_vec, size_t aad_vec_length,
386     const struct iovec* ciphertext_vec, size_t ciphertext_vec_length,
387     struct iovec plaintext_vec, size_t* plaintext_bytes_written,
388     char** error_details) {
389   gsec_aes_gcm_aead_crypter* aes_gcm_crypter =
390       reinterpret_cast<gsec_aes_gcm_aead_crypter*>(
391           const_cast<gsec_aead_crypter*>(crypter));
392   if (nonce == nullptr) {
393     aes_gcm_format_errors("Nonce buffer is nullptr.", error_details);
394     return GRPC_STATUS_INVALID_ARGUMENT;
395   }
396   if (kAesGcmNonceLength != nonce_length) {
397     aes_gcm_format_errors("Nonce buffer has the wrong length.", error_details);
398     return GRPC_STATUS_INVALID_ARGUMENT;
399   }
400   if (aad_vec_length > 0 && aad_vec == nullptr) {
401     aes_gcm_format_errors("Non-zero aad_vec_length but aad_vec is nullptr.",
402                           error_details);
403     return GRPC_STATUS_INVALID_ARGUMENT;
404   }
405   if (ciphertext_vec_length > 0 && ciphertext_vec == nullptr) {
406     aes_gcm_format_errors(
407         "Non-zero plaintext_vec_length but plaintext_vec is nullptr.",
408         error_details);
409     return GRPC_STATUS_INVALID_ARGUMENT;
410   }
411   // Compute the total length so we can ensure we don't pass the tag into
412   // EVP_decrypt.
413   size_t total_ciphertext_length = 0;
414   size_t i;
415   for (i = 0; i < ciphertext_vec_length; i++) {
416     total_ciphertext_length += ciphertext_vec[i].iov_len;
417   }
418   if (total_ciphertext_length < kAesGcmTagLength) {
419     aes_gcm_format_errors("ciphertext is too small to hold a tag.",
420                           error_details);
421     return GRPC_STATUS_INVALID_ARGUMENT;
422   }
423   if (plaintext_bytes_written == nullptr) {
424     aes_gcm_format_errors("bytes_written is nullptr.", error_details);
425     return GRPC_STATUS_INVALID_ARGUMENT;
426   }
427   *plaintext_bytes_written = 0;
428   // rekey if required
429   if (aes_gcm_rekey_if_required(aes_gcm_crypter, nonce, error_details) !=
430       GRPC_STATUS_OK) {
431     aes_gcm_format_errors("Rekeying failed.", error_details);
432     return GRPC_STATUS_INTERNAL;
433   }
434   // mask nonce if required
435   const uint8_t* nonce_aead = nonce;
436   uint8_t nonce_masked[kAesGcmNonceLength];
437   if (aes_gcm_crypter->rekey_data != nullptr) {
438     aes_gcm_mask_nonce(nonce_masked, aes_gcm_crypter->rekey_data->nonce_mask,
439                        nonce);
440     nonce_aead = nonce_masked;
441   }
442   // init openssl context
443   if (!EVP_DecryptInit_ex(aes_gcm_crypter->ctx, nullptr, nullptr, nullptr,
444                           nonce_aead)) {
445     aes_gcm_format_errors("Initializing nonce failed.", error_details);
446     return GRPC_STATUS_INTERNAL;
447   }
448   // process aad
449   for (i = 0; i < aad_vec_length; i++) {
450     const uint8_t* aad = static_cast<uint8_t*>(aad_vec[i].iov_base);
451     size_t aad_length = aad_vec[i].iov_len;
452     if (aad_length == 0) {
453       continue;
454     }
455     size_t aad_bytes_read = 0;
456     if (aad == nullptr) {
457       aes_gcm_format_errors("aad is nullptr.", error_details);
458       return GRPC_STATUS_INVALID_ARGUMENT;
459     }
460     if (!EVP_DecryptUpdate(aes_gcm_crypter->ctx, nullptr,
461                            reinterpret_cast<int*>(&aad_bytes_read), aad,
462                            static_cast<int>(aad_length)) ||
463         aad_bytes_read != aad_length) {
464       aes_gcm_format_errors("Setting authenticated associated data failed.",
465                             error_details);
466       return GRPC_STATUS_INTERNAL;
467     }
468   }
469   // process ciphertext
470   uint8_t* plaintext = static_cast<uint8_t*>(plaintext_vec.iov_base);
471   size_t plaintext_length = plaintext_vec.iov_len;
472   if (plaintext_length > 0 && plaintext == nullptr) {
473     aes_gcm_format_errors(
474         "plaintext is nullptr, but plaintext_length is positive.",
475         error_details);
476     return GRPC_STATUS_INVALID_ARGUMENT;
477   }
478   const uint8_t* ciphertext = nullptr;
479   size_t ciphertext_length = 0;
480   for (i = 0;
481        i < ciphertext_vec_length && total_ciphertext_length > kAesGcmTagLength;
482        i++) {
483     ciphertext = static_cast<uint8_t*>(ciphertext_vec[i].iov_base);
484     ciphertext_length = ciphertext_vec[i].iov_len;
485     if (ciphertext == nullptr) {
486       if (ciphertext_length == 0) {
487         continue;
488       }
489       aes_gcm_format_errors("ciphertext is nullptr.", error_details);
490       memset(plaintext_vec.iov_base, 0x00, plaintext_vec.iov_len);
491       return GRPC_STATUS_INVALID_ARGUMENT;
492     }
493     size_t bytes_written = 0;
494     size_t bytes_to_write = ciphertext_length;
495     // Don't include the tag
496     if (bytes_to_write > total_ciphertext_length - kAesGcmTagLength) {
497       bytes_to_write = total_ciphertext_length - kAesGcmTagLength;
498     }
499     if (plaintext_length < bytes_to_write) {
500       aes_gcm_format_errors(
501           "Not enough plaintext buffer to hold encrypted ciphertext.",
502           error_details);
503       return GRPC_STATUS_INVALID_ARGUMENT;
504     }
505     if (!EVP_DecryptUpdate(aes_gcm_crypter->ctx, plaintext,
506                            reinterpret_cast<int*>(&bytes_written), ciphertext,
507                            static_cast<int>(bytes_to_write))) {
508       aes_gcm_format_errors("Decrypting ciphertext failed.", error_details);
509       memset(plaintext_vec.iov_base, 0x00, plaintext_vec.iov_len);
510       return GRPC_STATUS_INTERNAL;
511     }
512     if (bytes_written > ciphertext_length) {
513       aes_gcm_format_errors("More bytes written than expected.", error_details);
514       memset(plaintext_vec.iov_base, 0x00, plaintext_vec.iov_len);
515       return GRPC_STATUS_INTERNAL;
516     }
517     ciphertext += bytes_written;
518     ciphertext_length -= bytes_written;
519     total_ciphertext_length -= bytes_written;
520     plaintext += bytes_written;
521     plaintext_length -= bytes_written;
522   }
523   if (total_ciphertext_length > kAesGcmTagLength) {
524     aes_gcm_format_errors(
525         "Not enough plaintext buffer to hold encrypted ciphertext.",
526         error_details);
527     memset(plaintext_vec.iov_base, 0x00, plaintext_vec.iov_len);
528     return GRPC_STATUS_INVALID_ARGUMENT;
529   }
530   uint8_t tag[kAesGcmTagLength];
531   uint8_t* tag_tmp = tag;
532   if (ciphertext_length > 0) {
533     memcpy(tag_tmp, ciphertext, ciphertext_length);
534     tag_tmp += ciphertext_length;
535     total_ciphertext_length -= ciphertext_length;
536   }
537   for (; i < ciphertext_vec_length; i++) {
538     ciphertext = static_cast<uint8_t*>(ciphertext_vec[i].iov_base);
539     ciphertext_length = ciphertext_vec[i].iov_len;
540     if (ciphertext == nullptr) {
541       if (ciphertext_length == 0) {
542         continue;
543       }
544       aes_gcm_format_errors("ciphertext is nullptr.", error_details);
545       memset(plaintext_vec.iov_base, 0x00, plaintext_vec.iov_len);
546       return GRPC_STATUS_INVALID_ARGUMENT;
547     }
548     memcpy(tag_tmp, ciphertext, ciphertext_length);
549     tag_tmp += ciphertext_length;
550     total_ciphertext_length -= ciphertext_length;
551   }
552   if (!EVP_CIPHER_CTX_ctrl(aes_gcm_crypter->ctx, EVP_CTRL_GCM_SET_TAG,
553                            kAesGcmTagLength, reinterpret_cast<void*>(tag))) {
554     aes_gcm_format_errors("Setting tag failed.", error_details);
555     memset(plaintext_vec.iov_base, 0x00, plaintext_vec.iov_len);
556     return GRPC_STATUS_INTERNAL;
557   }
558   int bytes_written_temp = 0;
559   if (!EVP_DecryptFinal_ex(aes_gcm_crypter->ctx, nullptr,
560                            &bytes_written_temp)) {
561     aes_gcm_format_errors("Checking tag failed.", error_details);
562     if (plaintext_vec.iov_base != nullptr) {
563       memset(plaintext_vec.iov_base, 0x00, plaintext_vec.iov_len);
564     }
565     return GRPC_STATUS_FAILED_PRECONDITION;
566   }
567   if (bytes_written_temp != 0) {
568     aes_gcm_format_errors("Openssl wrote some unexpected bytes.",
569                           error_details);
570     memset(plaintext_vec.iov_base, 0x00, plaintext_vec.iov_len);
571     return GRPC_STATUS_INTERNAL;
572   }
573   *plaintext_bytes_written = plaintext_vec.iov_len - plaintext_length;
574   return GRPC_STATUS_OK;
575 }
576 
gsec_aes_gcm_aead_crypter_destroy(gsec_aead_crypter * crypter)577 static void gsec_aes_gcm_aead_crypter_destroy(gsec_aead_crypter* crypter) {
578   gsec_aes_gcm_aead_crypter* aes_gcm_crypter =
579       reinterpret_cast<gsec_aes_gcm_aead_crypter*>(
580           const_cast<gsec_aead_crypter*>(crypter));
581   gpr_free(aes_gcm_crypter->key);
582   gpr_free(aes_gcm_crypter->rekey_data);
583   EVP_CIPHER_CTX_free(aes_gcm_crypter->ctx);
584 }
585 
586 static const gsec_aead_crypter_vtable vtable = {
587     gsec_aes_gcm_aead_crypter_encrypt_iovec,
588     gsec_aes_gcm_aead_crypter_decrypt_iovec,
589     gsec_aes_gcm_aead_crypter_max_ciphertext_and_tag_length,
590     gsec_aes_gcm_aead_crypter_max_plaintext_length,
591     gsec_aes_gcm_aead_crypter_nonce_length,
592     gsec_aes_gcm_aead_crypter_key_length,
593     gsec_aes_gcm_aead_crypter_tag_length,
594     gsec_aes_gcm_aead_crypter_destroy};
595 
aes_gcm_new_evp_cipher_ctx(gsec_aes_gcm_aead_crypter * aes_gcm_crypter,char ** error_details)596 static grpc_status_code aes_gcm_new_evp_cipher_ctx(
597     gsec_aes_gcm_aead_crypter* aes_gcm_crypter, char** error_details) {
598   const EVP_CIPHER* cipher = nullptr;
599   bool is_rekey = aes_gcm_crypter->rekey_data != nullptr;
600   switch (is_rekey ? kRekeyAeadKeyLen : aes_gcm_crypter->key_length) {
601     case kAes128GcmKeyLength:
602       cipher = EVP_aes_128_gcm();
603       break;
604     case kAes256GcmKeyLength:
605       cipher = EVP_aes_256_gcm();
606       break;
607   }
608   const uint8_t* aead_key = aes_gcm_crypter->key;
609   uint8_t aead_key_rekey[kRekeyAeadKeyLen];
610   if (is_rekey) {
611     if (aes_gcm_derive_aead_key(aead_key_rekey, aes_gcm_crypter->key,
612                                 aes_gcm_crypter->rekey_data->kdf_counter) !=
613         GRPC_STATUS_OK) {
614       aes_gcm_format_errors("Deriving key failed.", error_details);
615       return GRPC_STATUS_INTERNAL;
616     }
617     aead_key = aead_key_rekey;
618   }
619   if (!EVP_DecryptInit_ex(aes_gcm_crypter->ctx, cipher, nullptr, aead_key,
620                           nullptr)) {
621     aes_gcm_format_errors("Setting key failed.", error_details);
622     return GRPC_STATUS_INTERNAL;
623   }
624   if (!EVP_CIPHER_CTX_ctrl(aes_gcm_crypter->ctx, EVP_CTRL_GCM_SET_IVLEN,
625                            static_cast<int>(aes_gcm_crypter->nonce_length),
626                            nullptr)) {
627     aes_gcm_format_errors("Setting nonce length failed.", error_details);
628     return GRPC_STATUS_INTERNAL;
629   }
630   return GRPC_STATUS_OK;
631 }
632 
gsec_aes_gcm_aead_crypter_create(const uint8_t * key,size_t key_length,size_t nonce_length,size_t tag_length,bool rekey,gsec_aead_crypter ** crypter,char ** error_details)633 grpc_status_code gsec_aes_gcm_aead_crypter_create(const uint8_t* key,
634                                                   size_t key_length,
635                                                   size_t nonce_length,
636                                                   size_t tag_length, bool rekey,
637                                                   gsec_aead_crypter** crypter,
638                                                   char** error_details) {
639   if (key == nullptr) {
640     aes_gcm_format_errors("key is nullptr.", error_details);
641     return GRPC_STATUS_FAILED_PRECONDITION;
642   }
643   if (crypter == nullptr) {
644     aes_gcm_format_errors("crypter is nullptr.", error_details);
645     return GRPC_STATUS_FAILED_PRECONDITION;
646   }
647   *crypter = nullptr;
648   if ((rekey && key_length != kAes128GcmRekeyKeyLength) ||
649       (!rekey && key_length != kAes128GcmKeyLength &&
650        key_length != kAes256GcmKeyLength) ||
651       (tag_length != kAesGcmTagLength) ||
652       (nonce_length != kAesGcmNonceLength)) {
653     aes_gcm_format_errors(
654         "Invalid key and/or nonce and/or tag length are provided at AEAD "
655         "crypter instance construction time.",
656         error_details);
657     return GRPC_STATUS_FAILED_PRECONDITION;
658   }
659   gsec_aes_gcm_aead_crypter* aes_gcm_crypter =
660       static_cast<gsec_aes_gcm_aead_crypter*>(
661           gpr_malloc(sizeof(gsec_aes_gcm_aead_crypter)));
662   aes_gcm_crypter->crypter.vtable = &vtable;
663   aes_gcm_crypter->nonce_length = nonce_length;
664   aes_gcm_crypter->tag_length = tag_length;
665   if (rekey) {
666     aes_gcm_crypter->key_length = kKdfKeyLen;
667     aes_gcm_crypter->rekey_data = static_cast<gsec_aes_gcm_aead_rekey_data*>(
668         gpr_malloc(sizeof(gsec_aes_gcm_aead_rekey_data)));
669     memcpy(aes_gcm_crypter->rekey_data->nonce_mask, key + kKdfKeyLen,
670            kAesGcmNonceLength);
671     // Set kdf_counter to all-zero for initial key derivation.
672     memset(aes_gcm_crypter->rekey_data->kdf_counter, 0, kKdfCounterLen);
673   } else {
674     aes_gcm_crypter->key_length = key_length;
675     aes_gcm_crypter->rekey_data = nullptr;
676   }
677   aes_gcm_crypter->key =
678       static_cast<uint8_t*>(gpr_malloc(aes_gcm_crypter->key_length));
679   memcpy(aes_gcm_crypter->key, key, aes_gcm_crypter->key_length);
680   aes_gcm_crypter->ctx = EVP_CIPHER_CTX_new();
681   grpc_status_code status =
682       aes_gcm_new_evp_cipher_ctx(aes_gcm_crypter, error_details);
683   if (status != GRPC_STATUS_OK) {
684     gsec_aes_gcm_aead_crypter_destroy(&aes_gcm_crypter->crypter);
685     gpr_free(aes_gcm_crypter);
686     return status;
687   }
688   *crypter = &aes_gcm_crypter->crypter;
689   return GRPC_STATUS_OK;
690 }
691