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
diff --git a/compos/compos_key_helper/compos_key.cpp b/compos/compos_key_helper/compos_key.cpp
index 2e3252c..34b931a 100644
--- a/compos/compos_key_helper/compos_key.cpp
+++ b/compos/compos_key_helper/compos_key.cpp
@@ -24,25 +24,11 @@
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<Ed25519KeyPair> 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<uint8_t, 32> 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<const uint8_t*>(kSigningKeyInfo),
- strlen(kSigningKeyInfo))) {
- return Error() << "HKDF failed";
- }
-
+Result<Ed25519KeyPair> 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 e9c6061..8629cf6 100644
--- a/compos/compos_key_helper/compos_key.h
+++ b/compos/compos_key_helper/compos_key.h
@@ -22,8 +22,11 @@
#include <array>
namespace compos_key {
+constexpr size_t ED25519_SEED_LEN = 32;
+
using PrivateKey = std::array<uint8_t, ED25519_PRIVATE_KEY_LEN>;
using PublicKey = std::array<uint8_t, ED25519_PUBLIC_KEY_LEN>;
+using Seed = std::array<uint8_t, ED25519_SEED_LEN>;
using Signature = std::array<uint8_t, ED25519_SIGNATURE_LEN>;
struct Ed25519KeyPair {
@@ -31,8 +34,7 @@
PublicKey public_key;
};
-android::base::Result<Ed25519KeyPair> deriveKeyFromSecret(const uint8_t* secret,
- size_t secret_size);
+android::base::Result<Ed25519KeyPair> keyFromSeed(const Seed& seed);
android::base::Result<Signature> 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 6c4fc1f..224e42b 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::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<Ed25519KeyPair> 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<Ed25519KeyPair> 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 @@
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 e4c3e8a..37aefcf 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<uint8_t> secret = {1, 2, 3};
-const std::vector<uint8_t> 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<uint8_t> 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, 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());