cryptohome: Refuse empty plain-/ciphertexts in AES
Change the AES encryption/decryption helpers to bail out when the
supplied plaintext/ciphertext is empty. It seems to most likely indicate
a bug, since such encryption/decryption is effectively a no-op.
Also emit a fatal failure in Debug builds, so that such mistakes are
more visible on test bots. Additionally do the same for other existing
DCHECKs in the AES helpers, i.e., logging + crashing in Debug builds and
logging + returning false in Release ones.
BUG=none
TEST=cros_workon_make --board=$BOARD --test cryptohome
Change-Id: I6e93b086b702c0cf2bdb71618bd571dd1bf33cfe
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/3151841
Tested-by: Maksim Ivanov <emaxx@chromium.org>
Tested-by: Greg Kerr <kerrnel@chromium.org>
Reviewed-by: Betul Soysal <betuls@google.com>
Reviewed-by: Greg Kerr <kerrnel@chromium.org>
Auto-Submit: Maksim Ivanov <emaxx@chromium.org>
Commit-Queue: Maksim Ivanov <emaxx@chromium.org>
diff --git a/cryptohome/crypto/aes.cc b/cryptohome/crypto/aes.cc
index 78fea77..3d04288 100644
--- a/cryptohome/crypto/aes.cc
+++ b/cryptohome/crypto/aes.cc
@@ -13,6 +13,7 @@
#include "cryptohome/crypto/secure_blob_util.h"
#include <base/logging.h>
+#include <base/notreached.h>
namespace cryptohome {
@@ -94,9 +95,25 @@
const brillo::SecureBlob& key,
const brillo::SecureBlob& iv,
brillo::SecureBlob* plaintext) {
- DCHECK_EQ(key.size(), kAesGcm256KeySize);
- DCHECK_EQ(iv.size(), kAesGcmIVSize);
- DCHECK_EQ(tag.size(), kAesGcmTagSize);
+ if (ciphertext.empty()) {
+ NOTREACHED() << "Empty ciphertext passed to AesGcmDecrypt.";
+ return false;
+ }
+ if (tag.size() != kAesGcmTagSize) {
+ NOTREACHED() << "Wrong tag size passed to AesGcmDecrypt: " << tag.size()
+ << ", expected " << kAesGcmTagSize << ".";
+ return false;
+ }
+ if (key.size() != kAesGcm256KeySize) {
+ NOTREACHED() << "Wrong key size passed to AesGcmDecrypt: " << key.size()
+ << ", expected " << kAesGcm256KeySize << ".";
+ return false;
+ }
+ if (iv.size() != kAesGcmIVSize) {
+ NOTREACHED() << "Wrong iv size passed to AesGcmDecrypt: " << iv.size()
+ << ", expected " << kAesGcmIVSize << ".";
+ return false;
+ }
crypto::ScopedEVP_CIPHER_CTX ctx(EVP_CIPHER_CTX_new());
if (ctx.get() == nullptr) {
@@ -123,7 +140,10 @@
}
if (ad.has_value()) {
- DCHECK_NE(ad.value().size(), 0);
+ if (ad.value().empty()) {
+ NOTREACHED() << "Empty associated data passed to AesGcmDecrypt.";
+ return false;
+ }
int out_size = 0;
if (EVP_DecryptUpdate(ctx.get(), nullptr, &out_size, ad.value().data(),
ad.value().size()) != 1) {
@@ -171,7 +191,15 @@
brillo::SecureBlob* iv,
brillo::SecureBlob* tag,
brillo::SecureBlob* ciphertext) {
- DCHECK_EQ(key.size(), kAesGcm256KeySize);
+ if (plaintext.empty()) {
+ NOTREACHED() << "Empty plaintext passed to AesGcmEncrypt.";
+ return false;
+ }
+ if (key.size() != kAesGcm256KeySize) {
+ NOTREACHED() << "Wrong key size passed to AesGcmEncrypt: " << key.size()
+ << ", expected " << kAesGcm256KeySize << ".";
+ return false;
+ }
iv->resize(kAesGcmIVSize);
GetSecureRandom(iv->data(), kAesGcmIVSize);
@@ -201,7 +229,10 @@
}
if (ad.has_value()) {
- DCHECK_NE(ad.value().size(), 0);
+ if (ad.value().empty()) {
+ NOTREACHED() << "Empty associated data passed to AesGcmEncrypt.";
+ return false;
+ }
int out_size = 0;
if (EVP_EncryptUpdate(ctx.get(), nullptr, &out_size, ad.value().data(),
ad.value().size()) != 1) {