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