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
This commit is contained in:
parent
b3dd8af067
commit
7c6e4185bb
|
@ -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<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;
|
||||
|
|
|
@ -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 @@ struct Ed25519KeyPair {
|
|||
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);
|
||||
|
|
|
@ -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<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 @@ int sign_input() {
|
|||
return 1;
|
||||
}
|
||||
|
||||
auto key_pair = deriveKeyFromDice();
|
||||
auto key_pair = getSigningKey();
|
||||
if (!key_pair.ok()) {
|
||||
LOG(ERROR) << key_pair.error();
|
||||
return 1;
|
||||
|
|
|
@ -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, 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());
|
||||
|
|
Loading…
Reference in New Issue