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


grpc
Author(s):
autogenerated on Fri May 16 2025 02:57:40