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