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