1 //
2 //
3 // Copyright 2018 gRPC authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 //
18
19 #include <grpc/support/port_platform.h>
20
21 #include <string.h>
22
23 #include <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
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 // Struct for additional data required if rekeying is enabled.
39 struct gsec_aes_gcm_aead_rekey_data {
40 uint8_t kdf_counter[kKdfCounterLen];
41 uint8_t nonce_mask[kAesGcmNonceLength];
42 };
43
44 // Main struct for AES_GCM crypter interface.
45 struct gsec_aes_gcm_aead_crypter {
46 gsec_aead_crypter crypter;
47 size_t key_length;
48 size_t nonce_length;
49 size_t tag_length;
50 uint8_t* key;
51 gsec_aes_gcm_aead_rekey_data* rekey_data;
52 EVP_CIPHER_CTX* ctx;
53 };
54
aes_gcm_get_openssl_errors()55 static char* aes_gcm_get_openssl_errors() {
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
aes_gcm_format_errors(const char * error_msg,char ** error_details)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
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)89 static grpc_status_code gsec_aes_gcm_aead_crypter_max_ciphertext_and_tag_length(
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);
95 return GRPC_STATUS_INVALID_ARGUMENT;
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
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)105 static grpc_status_code gsec_aes_gcm_aead_crypter_max_plaintext_length(
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);
110 return GRPC_STATUS_INVALID_ARGUMENT;
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;
117 aes_gcm_format_errors(
118 "ciphertext_and_tag_length is smaller than tag_length.", error_details);
119 return GRPC_STATUS_INVALID_ARGUMENT;
120 }
121 *max_plaintext_length =
122 ciphertext_and_tag_length - aes_gcm_crypter->tag_length;
123 return GRPC_STATUS_OK;
124 }
125
gsec_aes_gcm_aead_crypter_nonce_length(const gsec_aead_crypter * crypter,size_t * nonce_length,char ** error_details)126 static grpc_status_code gsec_aes_gcm_aead_crypter_nonce_length(
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);
131 return GRPC_STATUS_INVALID_ARGUMENT;
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
gsec_aes_gcm_aead_crypter_key_length(const gsec_aead_crypter * crypter,size_t * key_length,char ** error_details)140 static grpc_status_code gsec_aes_gcm_aead_crypter_key_length(
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);
145 return GRPC_STATUS_INVALID_ARGUMENT;
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
gsec_aes_gcm_aead_crypter_tag_length(const gsec_aead_crypter * crypter,size_t * tag_length,char ** error_details)154 static grpc_status_code gsec_aes_gcm_aead_crypter_tag_length(
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);
159 return GRPC_STATUS_INVALID_ARGUMENT;
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
aes_gcm_mask_nonce(uint8_t * dst,const uint8_t * nonce,const uint8_t * mask)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
aes_gcm_derive_aead_key(uint8_t * dst,const uint8_t * kdf_key,const uint8_t * kdf_counter)184 static grpc_status_code aes_gcm_derive_aead_key(uint8_t* dst,
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
212 memcpy(dst, buf, kRekeyAeadKeyLen);
213 return GRPC_STATUS_OK;
214 }
215
aes_gcm_rekey_if_required(gsec_aes_gcm_aead_crypter * aes_gcm_crypter,const uint8_t * nonce,char ** error_details)216 static grpc_status_code aes_gcm_rekey_if_required(
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,
229 kKdfCounterLen);
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
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)245 static grpc_status_code gsec_aes_gcm_aead_crypter_encrypt_iovec(
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);
256 return GRPC_STATUS_INVALID_ARGUMENT;
257 }
258 if (kAesGcmNonceLength != nonce_length) {
259 aes_gcm_format_errors("Nonce buffer has the wrong length.", error_details);
260 return GRPC_STATUS_INVALID_ARGUMENT;
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);
265 return GRPC_STATUS_INVALID_ARGUMENT;
266 }
267 if (plaintext_vec_length > 0 && plaintext_vec == nullptr) {
268 aes_gcm_format_errors(
269 "Non-zero plaintext_vec_length but plaintext_vec is nullptr.",
270 error_details);
271 return GRPC_STATUS_INVALID_ARGUMENT;
272 }
273 if (ciphertext_bytes_written == nullptr) {
274 aes_gcm_format_errors("bytes_written is nullptr.", error_details);
275 return GRPC_STATUS_INVALID_ARGUMENT;
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);
308 return GRPC_STATUS_INVALID_ARGUMENT;
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);
323 return GRPC_STATUS_INVALID_ARGUMENT;
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);
334 return GRPC_STATUS_INVALID_ARGUMENT;
335 }
336 if (ciphertext_length < plaintext_length) {
337 aes_gcm_format_errors(
338 "ciphertext is not large enough to hold the result.", error_details);
339 return GRPC_STATUS_INVALID_ARGUMENT;
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 }
352 ciphertext += bytes_written;
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);
369 return GRPC_STATUS_INVALID_ARGUMENT;
370 }
371
372 if (!EVP_CIPHER_CTX_ctrl(aes_gcm_crypter->ctx, EVP_CTRL_GCM_GET_TAG,
373 kAesGcmTagLength, ciphertext)) {
374 aes_gcm_format_errors("Writing tag failed.", error_details);
375 return GRPC_STATUS_INTERNAL;
376 }
377 ciphertext += kAesGcmTagLength;
378 ciphertext_length -= kAesGcmTagLength;
379 *ciphertext_bytes_written = ciphertext_vec.iov_len - ciphertext_length;
380 return GRPC_STATUS_OK;
381 }
382
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)383 static grpc_status_code gsec_aes_gcm_aead_crypter_decrypt_iovec(
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);
394 return GRPC_STATUS_INVALID_ARGUMENT;
395 }
396 if (kAesGcmNonceLength != nonce_length) {
397 aes_gcm_format_errors("Nonce buffer has the wrong length.", error_details);
398 return GRPC_STATUS_INVALID_ARGUMENT;
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);
403 return GRPC_STATUS_INVALID_ARGUMENT;
404 }
405 if (ciphertext_vec_length > 0 && ciphertext_vec == nullptr) {
406 aes_gcm_format_errors(
407 "Non-zero plaintext_vec_length but plaintext_vec is nullptr.",
408 error_details);
409 return GRPC_STATUS_INVALID_ARGUMENT;
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);
421 return GRPC_STATUS_INVALID_ARGUMENT;
422 }
423 if (plaintext_bytes_written == nullptr) {
424 aes_gcm_format_errors("bytes_written is nullptr.", error_details);
425 return GRPC_STATUS_INVALID_ARGUMENT;
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);
458 return GRPC_STATUS_INVALID_ARGUMENT;
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) {
473 aes_gcm_format_errors(
474 "plaintext is nullptr, but plaintext_length is positive.",
475 error_details);
476 return GRPC_STATUS_INVALID_ARGUMENT;
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);
491 return GRPC_STATUS_INVALID_ARGUMENT;
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) {
500 aes_gcm_format_errors(
501 "Not enough plaintext buffer to hold encrypted ciphertext.",
502 error_details);
503 return GRPC_STATUS_INVALID_ARGUMENT;
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 }
517 ciphertext += bytes_written;
518 ciphertext_length -= bytes_written;
519 total_ciphertext_length -= bytes_written;
520 plaintext += bytes_written;
521 plaintext_length -= bytes_written;
522 }
523 if (total_ciphertext_length > kAesGcmTagLength) {
524 aes_gcm_format_errors(
525 "Not enough plaintext buffer to hold encrypted ciphertext.",
526 error_details);
527 memset(plaintext_vec.iov_base, 0x00, plaintext_vec.iov_len);
528 return GRPC_STATUS_INVALID_ARGUMENT;
529 }
530 uint8_t tag[kAesGcmTagLength];
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);
546 return GRPC_STATUS_INVALID_ARGUMENT;
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 }
565 return GRPC_STATUS_FAILED_PRECONDITION;
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
gsec_aes_gcm_aead_crypter_destroy(gsec_aead_crypter * crypter)577 static void gsec_aes_gcm_aead_crypter_destroy(gsec_aead_crypter* crypter) {
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
586 static const gsec_aead_crypter_vtable vtable = {
587 gsec_aes_gcm_aead_crypter_encrypt_iovec,
588 gsec_aes_gcm_aead_crypter_decrypt_iovec,
589 gsec_aes_gcm_aead_crypter_max_ciphertext_and_tag_length,
590 gsec_aes_gcm_aead_crypter_max_plaintext_length,
591 gsec_aes_gcm_aead_crypter_nonce_length,
592 gsec_aes_gcm_aead_crypter_key_length,
593 gsec_aes_gcm_aead_crypter_tag_length,
594 gsec_aes_gcm_aead_crypter_destroy};
595
aes_gcm_new_evp_cipher_ctx(gsec_aes_gcm_aead_crypter * aes_gcm_crypter,char ** error_details)596 static grpc_status_code aes_gcm_new_evp_cipher_ctx(
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
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)633 grpc_status_code gsec_aes_gcm_aead_crypter_create(const uint8_t* key,
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);
641 return GRPC_STATUS_FAILED_PRECONDITION;
642 }
643 if (crypter == nullptr) {
644 aes_gcm_format_errors("crypter is nullptr.", error_details);
645 return GRPC_STATUS_FAILED_PRECONDITION;
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)) {
653 aes_gcm_format_errors(
654 "Invalid key and/or nonce and/or tag length are provided at AEAD "
655 "crypter instance construction time.",
656 error_details);
657 return GRPC_STATUS_FAILED_PRECONDITION;
658 }
659 gsec_aes_gcm_aead_crypter* aes_gcm_crypter =
660 static_cast<gsec_aes_gcm_aead_crypter*>(
661 gpr_malloc(sizeof(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*>(
668 gpr_malloc(sizeof(gsec_aes_gcm_aead_rekey_data)));
669 memcpy(aes_gcm_crypter->rekey_data->nonce_mask, key + kKdfKeyLen,
670 kAesGcmNonceLength);
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();
681 grpc_status_code status =
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 }
691