blob: c886526108316f208347db557afcb3a000169b6d [file] [log] [blame]
// Copyright 2021 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "cryptohome/crypto/ecdh_hkdf.h"
#include <gtest/gtest.h>
#include "cryptohome/crypto/aes.h"
#include "cryptohome/crypto/big_num_util.h"
namespace cryptohome {
namespace {
constexpr EllipticCurve::CurveType kCurve = EllipticCurve::CurveType::kPrime256;
constexpr HkdfHash kHkdfHash = HkdfHash::kSha256;
const size_t kEcdhHkdfKeySize = kAesGcm256KeySize;
static const char kSaltHex[] = "0b0b0b0b";
static const char kInfoHex[] = "0b0b0b0b0b0b0b0b";
} // namespace
TEST(EcdhHkdfTest, CompareEcdhHkdfSymmetricKeys) {
ScopedBN_CTX context = CreateBigNumContext();
ASSERT_TRUE(context);
base::Optional<EllipticCurve> ec =
EllipticCurve::Create(kCurve, context.get());
ASSERT_TRUE(ec);
brillo::SecureBlob info;
ASSERT_TRUE(brillo::SecureBlob::HexStringToSecureBlob(kInfoHex, &info));
brillo::SecureBlob salt;
ASSERT_TRUE(brillo::SecureBlob::HexStringToSecureBlob(kSaltHex, &salt));
brillo::SecureBlob rec_pub_key;
brillo::SecureBlob rec_priv_key;
brillo::SecureBlob eph_pub_key;
brillo::SecureBlob eph_priv_key;
brillo::SecureBlob symmetric_key1;
brillo::SecureBlob symmetric_key2;
ASSERT_TRUE(ec->GenerateKeysAsSecureBlobs(&rec_pub_key, &rec_priv_key,
context.get()));
ASSERT_TRUE(ec->GenerateKeysAsSecureBlobs(&eph_pub_key, &eph_priv_key,
context.get()));
ASSERT_TRUE(GenerateEcdhHkdfSenderKey(*ec, rec_pub_key, eph_pub_key,
eph_priv_key, info, salt, kHkdfHash,
kEcdhHkdfKeySize, &symmetric_key1));
ASSERT_TRUE(GenerateEcdhHkdfRecipientKey(*ec, rec_priv_key, eph_pub_key, info,
salt, kHkdfHash, kEcdhHkdfKeySize,
&symmetric_key2));
EXPECT_EQ(symmetric_key1.size(), kAesGcm256KeySize);
EXPECT_EQ(symmetric_key2.size(), kAesGcm256KeySize);
// Symmetric keys generated for sender and recipient should be equal.
EXPECT_EQ(symmetric_key1, symmetric_key2);
}
TEST(EcdhHkdfTest, AesGcmEncryptionDecryption) {
ScopedBN_CTX context = CreateBigNumContext();
ASSERT_TRUE(context);
base::Optional<EllipticCurve> ec =
EllipticCurve::Create(kCurve, context.get());
ASSERT_TRUE(ec);
brillo::SecureBlob info;
ASSERT_TRUE(brillo::SecureBlob::HexStringToSecureBlob(kInfoHex, &info));
brillo::SecureBlob salt;
ASSERT_TRUE(brillo::SecureBlob::HexStringToSecureBlob(kSaltHex, &salt));
brillo::SecureBlob rec_pub_key;
brillo::SecureBlob rec_priv_key;
brillo::SecureBlob eph_pub_key;
brillo::SecureBlob eph_priv_key;
brillo::SecureBlob aes_gcm_key1;
brillo::SecureBlob aes_gcm_key2;
ASSERT_TRUE(ec->GenerateKeysAsSecureBlobs(&rec_pub_key, &rec_priv_key,
context.get()));
ASSERT_TRUE(ec->GenerateKeysAsSecureBlobs(&eph_pub_key, &eph_priv_key,
context.get()));
ASSERT_TRUE(GenerateEcdhHkdfSenderKey(*ec, rec_pub_key, eph_pub_key,
eph_priv_key, info, salt, kHkdfHash,
kEcdhHkdfKeySize, &aes_gcm_key1));
brillo::SecureBlob iv(kAesGcmIVSize);
brillo::SecureBlob tag(kAesGcmTagSize);
brillo::SecureBlob ciphertext;
brillo::SecureBlob plaintext("I am encrypting this message.");
// Encrypt using sender's `aes_gcm_key1`.
EXPECT_TRUE(AesGcmEncrypt(plaintext, /*ad=*/base::nullopt, aes_gcm_key1, &iv,
&tag, &ciphertext));
ASSERT_TRUE(GenerateEcdhHkdfRecipientKey(*ec, rec_priv_key, eph_pub_key, info,
salt, kHkdfHash, kEcdhHkdfKeySize,
&aes_gcm_key2));
// Symmetric keys generated for sender and recipient should be equal.
EXPECT_EQ(aes_gcm_key1, aes_gcm_key2);
EXPECT_NE(ciphertext, plaintext);
EXPECT_EQ(ciphertext.size(), plaintext.size());
// Decrypt using recipient's `aes_gcm_key2`.
brillo::SecureBlob decrypted_plaintext;
EXPECT_TRUE(AesGcmDecrypt(ciphertext, /*ad=*/base::nullopt, tag, aes_gcm_key2,
iv, &decrypted_plaintext));
EXPECT_EQ(plaintext, decrypted_plaintext);
}
} // namespace cryptohome