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