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