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