From 7c6e4185bb7a869eaf21ba1fbee916abbb2777a1 Mon Sep 17 00:00:00 2001 From: Andrew Scull Date: Fri, 7 Oct 2022 19:47:53 +0000 Subject: [PATCH] Simplify compos key handling The new interface to the VM instance secrets already provides a context-specific secret so it can be used directly as the seed for the key without requiring another derivation. Bug: 243514248 Test: atest ComposHostTestCases Test: atest compos_key_tests Change-Id: Ibbff27cc6e4e8f499bf70ff6ce171f6cd7765288 --- compos/compos_key_helper/compos_key.cpp | 18 ++---------------- compos/compos_key_helper/compos_key.h | 6 ++++-- compos/compos_key_helper/compos_key_main.cpp | 19 ++++++++++--------- compos/compos_key_helper/compos_key_test.cpp | 18 ++++++++++-------- 4 files changed, 26 insertions(+), 35 deletions(-) diff --git a/compos/compos_key_helper/compos_key.cpp b/compos/compos_key_helper/compos_key.cpp index 2e3252c4..34b931a7 100644 --- a/compos/compos_key_helper/compos_key.cpp +++ b/compos/compos_key_helper/compos_key.cpp @@ -24,25 +24,11 @@ using android::base::ErrnoError; using android::base::Error; using android::base::Result; using compos_key::Ed25519KeyPair; +using compos_key::Seed; using compos_key::Signature; -// Used to ensure the key we derive is distinct from any other. -constexpr const char* kSigningKeyInfo = "CompOS signing key"; - namespace compos_key { -Result deriveKeyFromSecret(const uint8_t* secret, size_t secret_size) { - // Ed25519 private keys are derived from a 32 byte seed: - // https://datatracker.ietf.org/doc/html/rfc8032#section-5.1.5 - std::array seed; - - // We derive the seed from the secret using HKDF - see - // https://datatracker.ietf.org/doc/html/rfc5869#section-2. - if (!HKDF(seed.data(), seed.size(), EVP_sha256(), secret, secret_size, /*salt=*/nullptr, - /*salt_len=*/0, reinterpret_cast(kSigningKeyInfo), - strlen(kSigningKeyInfo))) { - return Error() << "HKDF failed"; - } - +Result keyFromSeed(const Seed& seed) { Ed25519KeyPair result; ED25519_keypair_from_seed(result.public_key.data(), result.private_key.data(), seed.data()); return result; diff --git a/compos/compos_key_helper/compos_key.h b/compos/compos_key_helper/compos_key.h index e9c6061d..8629cf66 100644 --- a/compos/compos_key_helper/compos_key.h +++ b/compos/compos_key_helper/compos_key.h @@ -22,8 +22,11 @@ #include namespace compos_key { +constexpr size_t ED25519_SEED_LEN = 32; + using PrivateKey = std::array; using PublicKey = std::array; +using Seed = std::array; using Signature = std::array; struct Ed25519KeyPair { @@ -31,8 +34,7 @@ struct Ed25519KeyPair { PublicKey public_key; }; -android::base::Result deriveKeyFromSecret(const uint8_t* secret, - size_t secret_size); +android::base::Result keyFromSeed(const Seed& seed); android::base::Result sign(const PrivateKey& private_key, const uint8_t* data, size_t data_size); diff --git a/compos/compos_key_helper/compos_key_main.cpp b/compos/compos_key_helper/compos_key_main.cpp index 6c4fc1fa..224e42b7 100644 --- a/compos/compos_key_helper/compos_key_main.cpp +++ b/compos/compos_key_helper/compos_key_main.cpp @@ -29,22 +29,23 @@ using android::base::Result; using android::base::WriteFully; using namespace std::literals; using compos_key::Ed25519KeyPair; +using compos_key::Seed; namespace { -constexpr const char* kSigningKeySecretIdentifier = "CompOS signing key secret"; +constexpr const char* kSigningKeySeedIdentifier = "CompOS signing key seed"; -Result deriveKeyFromDice() { - uint8_t secret[32]; - if (!get_vm_instance_secret(kSigningKeySecretIdentifier, strlen(kSigningKeySecretIdentifier), - secret, sizeof(secret))) { - return Error() << "Failed to get signing key secret"; +Result getSigningKey() { + Seed seed; + if (!get_vm_instance_secret(kSigningKeySeedIdentifier, strlen(kSigningKeySeedIdentifier), + seed.data(), seed.size())) { + return Error() << "Failed to get signing key seed"; } - return compos_key::deriveKeyFromSecret(secret, sizeof(secret)); + return compos_key::keyFromSeed(seed); } int write_public_key() { - auto key_pair = deriveKeyFromDice(); + auto key_pair = getSigningKey(); if (!key_pair.ok()) { LOG(ERROR) << key_pair.error(); return 1; @@ -79,7 +80,7 @@ int sign_input() { return 1; } - auto key_pair = deriveKeyFromDice(); + auto key_pair = getSigningKey(); if (!key_pair.ok()) { LOG(ERROR) << key_pair.error(); return 1; diff --git a/compos/compos_key_helper/compos_key_test.cpp b/compos/compos_key_helper/compos_key_test.cpp index e4c3e8aa..37aefcfe 100644 --- a/compos/compos_key_helper/compos_key_test.cpp +++ b/compos/compos_key_helper/compos_key_test.cpp @@ -22,30 +22,32 @@ using namespace compos_key; -const std::vector secret = {1, 2, 3}; -const std::vector other_secret = {3, 2, 3}; +constexpr Seed seed = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32}; +constexpr Seed other_seed = {3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, + 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2}; const std::vector data = {42, 180, 65, 0}; struct ComposKeyTest : public testing::Test { Ed25519KeyPair key_pair; void SetUp() override { - auto key_pair = deriveKeyFromSecret(secret.data(), secret.size()); + auto key_pair = keyFromSeed(seed); ASSERT_TRUE(key_pair.ok()) << key_pair.error(); this->key_pair = *key_pair; } }; -TEST_F(ComposKeyTest, SameSecretSameKey) { - auto other_key_pair = deriveKeyFromSecret(secret.data(), secret.size()); +TEST_F(ComposKeyTest, SameSeedSameKey) { + auto other_key_pair = keyFromSeed(seed); ASSERT_TRUE(other_key_pair.ok()) << other_key_pair.error(); ASSERT_EQ(key_pair.private_key, other_key_pair->private_key); ASSERT_EQ(key_pair.public_key, other_key_pair->public_key); } -TEST_F(ComposKeyTest, DifferentSecretDifferentKey) { - auto other_key_pair = deriveKeyFromSecret(other_secret.data(), other_secret.size()); +TEST_F(ComposKeyTest, DifferentSeedDifferentKey) { + auto other_key_pair = keyFromSeed(other_seed); ASSERT_TRUE(other_key_pair.ok()) << other_key_pair.error(); ASSERT_NE(key_pair.private_key, other_key_pair->private_key); @@ -84,7 +86,7 @@ TEST_F(ComposKeyTest, WrongDataDoesNotVerify) { TEST_F(ComposKeyTest, WrongKeyDoesNotVerify) { auto signature = sign(key_pair.private_key, data.data(), data.size()); - auto other_key_pair = deriveKeyFromSecret(other_secret.data(), other_secret.size()); + auto other_key_pair = keyFromSeed(other_seed); ASSERT_TRUE(other_key_pair.ok()) << other_key_pair.error(); bool verified = verify(other_key_pair->public_key, *signature, data.data(), data.size());