On-device signing: Support keystore2 for keys.

Add code to support Keystore2. Keystore2 will offer a feature similar to
EARLY_BOOT_KEYS in Keymaster 4.1, but it will also be hardware-enforced
in older Keymaster versions. For now, have the code support both paths,
and stick with Keymaster 4.1 until Keystore2 is merged.

Bug: 165630556
Test: Local
Change-Id: If62837bf6fb1398bd30ce9422cbf3082a5cbf1e2
diff --git a/ondevice-signing/Android.bp b/ondevice-signing/Android.bp
index 4cf0bd7..1c3706d 100644
--- a/ondevice-signing/Android.bp
+++ b/ondevice-signing/Android.bp
@@ -86,6 +86,7 @@
     "CertUtils.cpp",
     "Keymaster.cpp",
     "KeymasterSigningKey.cpp",
+    "KeystoreKey.cpp",
     "VerityUtils.cpp",
   ],
 
@@ -97,7 +98,10 @@
 
   shared_libs: [
     "android.hardware.keymaster@4.1",
+    "android.system.keystore2-V1-cpp",
+    "android.hardware.security.keymint-V1-cpp",
     "libbase",
+    "libbinder",
     "libcrypto",
     "libcrypto_utils",
     "libfsverity",
diff --git a/ondevice-signing/CertUtils.cpp b/ondevice-signing/CertUtils.cpp
index 6b24391..e74fe9d 100644
--- a/ondevice-signing/CertUtils.cpp
+++ b/ondevice-signing/CertUtils.cpp
@@ -25,6 +25,9 @@
 
 #include <fcntl.h>
 #include <vector>
+
+#include "KeyConstants.h"
+
 const char kBasicConstraints[] = "CA:TRUE";
 const char kKeyUsage[] = "critical,keyCertSign,cRLSign,digitalSignature";
 const char kSubjectKeyIdentifier[] = "hash";
@@ -66,8 +69,18 @@
     X509_gmtime_adj(X509_get_notBefore(x509.get()), 0);
     X509_gmtime_adj(X509_get_notAfter(x509.get()), kCertLifetimeSeconds);
 
-    auto pubKeyData = publicKey.data();
-    EVP_PKEY* public_key = d2i_PUBKEY(nullptr, &pubKeyData, publicKey.size());
+    // "publicKey" corresponds to the raw public key bytes - need to create
+    // a new RSA key with the correct exponent.
+    RSA* rsaPubkey = RSA_new();
+    rsaPubkey->n = BN_new();
+    rsaPubkey->e = BN_new();
+
+    BN_bin2bn(publicKey.data(), publicKey.size(), rsaPubkey->n);
+    BN_set_word(rsaPubkey->e, kRsaKeyExponent);
+
+    EVP_PKEY* public_key = EVP_PKEY_new();
+    EVP_PKEY_assign_RSA(public_key, rsaPubkey);
+
     if (!X509_set_pubkey(x509.get(), public_key)) {
         return Error() << "Unable to set x509 public key";
     }
@@ -117,6 +130,7 @@
     i2d_X509_fp(f, x509.get());
     fclose(f);
 
+    EVP_PKEY_free(public_key);
     return {};
 }
 
@@ -142,13 +156,25 @@
     return pubKey;
 }
 
-Result<std::vector<uint8_t>> extractPublicKeyFromX509(const std::vector<uint8_t>& keyData) {
+Result<std::vector<uint8_t>>
+extractPublicKeyFromSubjectPublicKeyInfo(const std::vector<uint8_t>& keyData) {
     auto keyDataBytes = keyData.data();
     EVP_PKEY* public_key = d2i_PUBKEY(nullptr, &keyDataBytes, keyData.size());
 
     return extractPublicKey(public_key);
 }
 
+Result<std::vector<uint8_t>> extractPublicKeyFromX509(const std::vector<uint8_t>& keyData) {
+    auto keyDataBytes = keyData.data();
+    bssl::UniquePtr<X509> decoded_cert(d2i_X509(nullptr, &keyDataBytes, keyData.size()));
+    if (decoded_cert.get() == nullptr) {
+        return Error() << "Failed to decode X509 certificate.";
+    }
+    bssl::UniquePtr<EVP_PKEY> decoded_pkey(X509_get_pubkey(decoded_cert.get()));
+
+    return extractPublicKey(decoded_pkey.get());
+}
+
 Result<std::vector<uint8_t>> extractPublicKeyFromX509(const std::string& path) {
     X509* cert;
     auto f = fopen(path.c_str(), "r");
diff --git a/ondevice-signing/CertUtils.h b/ondevice-signing/CertUtils.h
index d9172d0..ca06f33 100644
--- a/ondevice-signing/CertUtils.h
+++ b/ondevice-signing/CertUtils.h
@@ -25,5 +25,7 @@
 android::base::Result<std::vector<uint8_t>> createPkcs7(const std::vector<uint8_t>& signedData);
 
 android::base::Result<std::vector<uint8_t>>
-extractPublicKeyFromX509(const std::vector<uint8_t>& path);
+extractPublicKeyFromX509(const std::vector<uint8_t>& x509);
+android::base::Result<std::vector<uint8_t>>
+extractPublicKeyFromSubjectPublicKeyInfo(const std::vector<uint8_t>& subjectKeyInfo);
 android::base::Result<std::vector<uint8_t>> extractPublicKeyFromX509(const std::string& path);
diff --git a/ondevice-signing/KeyConstants.h b/ondevice-signing/KeyConstants.h
new file mode 100644
index 0000000..9e1a513
--- /dev/null
+++ b/ondevice-signing/KeyConstants.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+static constexpr int kRsaKeySize = 2048;
+static constexpr int kRsaKeyExponent = 65537;
diff --git a/ondevice-signing/KeymasterSigningKey.cpp b/ondevice-signing/KeymasterSigningKey.cpp
index 2b748e4..dc3ef8a 100644
--- a/ondevice-signing/KeymasterSigningKey.cpp
+++ b/ondevice-signing/KeymasterSigningKey.cpp
@@ -33,30 +33,36 @@
 using android::base::Result;
 using android::base::unique_fd;
 
+const std::string kSigningKeyBlob = "/data/misc/odsign/key.blob";
+
 KeymasterSigningKey::KeymasterSigningKey() {}
 
-Result<KeymasterSigningKey> KeymasterSigningKey::loadFromBlobAndVerify(const std::string& path) {
-    KeymasterSigningKey signingKey;
+Result<std::unique_ptr<KeymasterSigningKey>>
+KeymasterSigningKey::loadFromBlobAndVerify(const std::string& path) {
+    auto signingKey = std::make_unique<KeymasterSigningKey>();
 
-    auto status = signingKey.initializeFromKeyblob(path);
+    auto status = signingKey->initializeFromKeyblob(path);
 
     if (!status.ok()) {
         return status.error();
     }
 
-    return std::move(signingKey);
+    return signingKey;
 }
 
-Result<KeymasterSigningKey> KeymasterSigningKey::createNewKey() {
-    KeymasterSigningKey signingKey;
+Result<void> KeymasterSigningKey::saveKeyblob(const std::string& path) const {
+    int flags = O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC;
 
-    auto status = signingKey.createSigningKey();
-
-    if (!status.ok()) {
-        return status.error();
+    unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), flags, 0600)));
+    if (fd == -1) {
+        return ErrnoError() << "Error creating key blob file " << path;
     }
 
-    return std::move(signingKey);
+    if (!android::base::WriteFully(fd, mVerifiedKeyBlob.data(), mVerifiedKeyBlob.size())) {
+        return ErrnoError() << "Error writing key blob file " << path;
+    } else {
+        return {};
+    }
 }
 
 Result<void> KeymasterSigningKey::createSigningKey() {
@@ -78,41 +84,45 @@
     return {};
 }
 
-Result<void> KeymasterSigningKey::saveKeyblob(const std::string& path) const {
-    int flags = O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC;
+Result<std::unique_ptr<KeymasterSigningKey>> KeymasterSigningKey::createAndPersistNewKey() {
+    auto signingKey = std::make_unique<KeymasterSigningKey>();
 
-    unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), flags, 0600)));
-    if (fd == -1) {
-        return ErrnoError() << "Error creating key blob file " << path;
+    auto status = signingKey->createSigningKey();
+
+    if (!status.ok()) {
+        return status.error();
     }
 
-    if (!android::base::WriteFully(fd, mVerifiedKeyBlob.data(), mVerifiedKeyBlob.size())) {
-        return ErrnoError() << "Error writing key blob file " << path;
-    } else {
-        return {};
+    status = signingKey->saveKeyblob(kSigningKeyBlob);
+    if (!status.ok()) {
+        return status.error();
     }
+
+    return signingKey;
+}
+
+Result<SigningKey*> KeymasterSigningKey::getInstance() {
+    auto key = loadFromBlobAndVerify(kSigningKeyBlob);
+
+    if (!key.ok()) {
+        key = createAndPersistNewKey();
+        if (!key.ok()) {
+            return key.error();
+        }
+    }
+
+    return key->release();
 }
 
 Result<std::vector<uint8_t>> KeymasterSigningKey::getPublicKey() const {
-    auto publicKeyX509 = mKeymaster->extractPublicKey(mVerifiedKeyBlob);
-    if (!publicKeyX509.ok()) {
-        return publicKeyX509.error();
-    }
-    return extractPublicKeyFromX509(publicKeyX509.value());
-}
-
-Result<void> KeymasterSigningKey::createX509Cert(const std::string& outPath) const {
     auto publicKey = mKeymaster->extractPublicKey(mVerifiedKeyBlob);
-
     if (!publicKey.ok()) {
         return publicKey.error();
     }
 
-    auto keymasterSignFunction = [&](const std::string& to_be_signed) {
-        return this->sign(to_be_signed);
-    };
-    createSelfSignedCertificate(*publicKey, keymasterSignFunction, outPath);
-    return {};
+    // Keymaster returns the public key not in a full X509 cert, but just the
+    // "SubjectPublicKeyInfo"
+    return extractPublicKeyFromSubjectPublicKeyInfo(publicKey.value());
 }
 
 Result<void> KeymasterSigningKey::initializeFromKeyblob(const std::string& path) {
diff --git a/ondevice-signing/KeymasterSigningKey.h b/ondevice-signing/KeymasterSigningKey.h
index 7631059..e66781f 100644
--- a/ondevice-signing/KeymasterSigningKey.h
+++ b/ondevice-signing/KeymasterSigningKey.h
@@ -23,30 +23,36 @@
 #include <utils/StrongPointer.h>
 
 #include "Keymaster.h"
+#include "SigningKey.h"
 
-class KeymasterSigningKey {
+class KeymasterSigningKey : public SigningKey {
     using KmDevice = ::android::hardware::keymaster::V4_1::IKeymasterDevice;
 
   public:
+    friend std::unique_ptr<KeymasterSigningKey> std::make_unique<KeymasterSigningKey>();
+    virtual ~KeymasterSigningKey(){};
+
     // Allow the key to be moved around
     KeymasterSigningKey& operator=(KeymasterSigningKey&& other) = default;
     KeymasterSigningKey(KeymasterSigningKey&& other) = default;
 
-    static android::base::Result<KeymasterSigningKey>
-    loadFromBlobAndVerify(const std::string& path);
-    static android::base::Result<KeymasterSigningKey> createNewKey();
+    static android::base::Result<SigningKey*> getInstance();
 
-    /* Sign a message with an initialized signing key */
-    android::base::Result<std::string> sign(const std::string& message) const;
-    android::base::Result<void> saveKeyblob(const std::string& path) const;
-    android::base::Result<std::vector<uint8_t>> getPublicKey() const;
-    android::base::Result<void> createX509Cert(const std::string& path) const;
+    virtual android::base::Result<std::string> sign(const std::string& message) const;
+    virtual android::base::Result<std::vector<uint8_t>> getPublicKey() const;
 
   private:
     KeymasterSigningKey();
 
+    static android::base::Result<std::unique_ptr<KeymasterSigningKey>> createAndPersistNewKey();
+    static android::base::Result<std::unique_ptr<KeymasterSigningKey>>
+    loadFromBlobAndVerify(const std::string& path);
+
     android::base::Result<void> createSigningKey();
     android::base::Result<void> initializeFromKeyblob(const std::string& path);
+    android::base::Result<void> saveKeyblob(const std::string& path) const;
+
+    static android::base::Result<KeymasterSigningKey> createNewKey();
 
     std::optional<Keymaster> mKeymaster;
     std::vector<uint8_t> mVerifiedKeyBlob;
diff --git a/ondevice-signing/KeystoreKey.cpp b/ondevice-signing/KeystoreKey.cpp
new file mode 100644
index 0000000..ea84183
--- /dev/null
+++ b/ondevice-signing/KeystoreKey.cpp
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <binder/IServiceManager.h>
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "CertUtils.h"
+#include "KeyConstants.h"
+#include "KeystoreKey.h"
+
+using android::defaultServiceManager;
+using android::IServiceManager;
+using android::sp;
+using android::String16;
+
+using android::hardware::security::keymint::Algorithm;
+using android::hardware::security::keymint::Digest;
+using android::hardware::security::keymint::KeyParameter;
+using android::hardware::security::keymint::KeyParameterValue;
+using android::hardware::security::keymint::KeyPurpose;
+using android::hardware::security::keymint::PaddingMode;
+using android::hardware::security::keymint::SecurityLevel;
+using android::hardware::security::keymint::Tag;
+
+using android::system::keystore2::CreateOperationResponse;
+using android::system::keystore2::Domain;
+using android::system::keystore2::KeyDescriptor;
+using android::system::keystore2::KeyEntryResponse;
+using android::system::keystore2::KeyMetadata;
+
+using android::base::Error;
+using android::base::Result;
+
+using android::base::unique_fd;
+
+static KeyDescriptor getKeyDescriptor() {
+    // AIDL parcelable objects don't have constructor
+    static KeyDescriptor descriptor;
+    static std::once_flag flag;
+    std::call_once(flag, [&]() {
+        descriptor.domain = Domain::SELINUX;
+        descriptor.alias = String16("ondevice-signing");
+        descriptor.nspace = 101;  // odsign_key
+    });
+
+    return descriptor;
+}
+
+KeystoreKey::KeystoreKey() {}
+
+Result<KeyMetadata> KeystoreKey::createNewKey(const KeyDescriptor& descriptor) {
+    std::vector<KeyParameter> params;
+
+    KeyParameter algo;
+    algo.tag = Tag::ALGORITHM;
+    algo.value = KeyParameterValue::make<KeyParameterValue::algorithm>(Algorithm::RSA);
+    params.push_back(algo);
+
+    KeyParameter key_size;
+    key_size.tag = Tag::KEY_SIZE;
+    key_size.value = KeyParameterValue::make<KeyParameterValue::integer>(kRsaKeySize);
+    params.push_back(key_size);
+
+    KeyParameter digest;
+    digest.tag = Tag::DIGEST;
+    digest.value = KeyParameterValue::make<KeyParameterValue::digest>(Digest::SHA_2_256);
+    params.push_back(digest);
+
+    KeyParameter padding;
+    padding.tag = Tag::PADDING;
+    padding.value =
+        KeyParameterValue::make<KeyParameterValue::paddingMode>(PaddingMode::RSA_PKCS1_1_5_SIGN);
+    params.push_back(padding);
+
+    KeyParameter exponent;
+    exponent.tag = Tag::RSA_PUBLIC_EXPONENT;
+    exponent.value = KeyParameterValue::make<KeyParameterValue::longInteger>(kRsaKeyExponent);
+    params.push_back(exponent);
+
+    KeyParameter purpose;
+    purpose.tag = Tag::PURPOSE;
+    purpose.value = KeyParameterValue::make<KeyParameterValue::keyPurpose>(KeyPurpose::SIGN);
+    params.push_back(purpose);
+
+    KeyParameter auth;
+    auth.tag = Tag::NO_AUTH_REQUIRED;
+    auth.value = KeyParameterValue::make<KeyParameterValue::boolValue>(true);
+    params.push_back(auth);
+
+    KeyMetadata metadata;
+    auto status = mSecurityLevel->generateKey(descriptor, {}, params, 0, {}, &metadata);
+    if (!status.isOk()) {
+        return Error() << "Failed to create new key";
+    }
+
+    return metadata;
+}
+
+bool KeystoreKey::initialize() {
+    sp<IServiceManager> sm = defaultServiceManager();
+    if (sm == nullptr) {
+        return false;
+    }
+    auto service = sm->getService(String16("android.system.keystore2"));
+    if (service == nullptr) {
+        return false;
+    }
+    mService = interface_cast<android::system::keystore2::IKeystoreService>(service);
+    if (mService == nullptr) {
+        return false;
+    }
+
+    auto status = mService->getSecurityLevel(SecurityLevel::STRONGBOX, &mSecurityLevel);
+    if (!status.isOk()) {
+        // TODO fallback to TEE
+        return false;
+    }
+
+    auto descriptor = getKeyDescriptor();
+    // See if we can fetch an existing key
+    KeyEntryResponse keyEntryResponse;
+    LOG(INFO) << "Trying to retrieve existing keystore key...";
+    status = mService->getKeyEntry(descriptor, &keyEntryResponse);
+    if (!status.isOk()) {
+        LOG(INFO) << "Existing keystore key not found, creating new key";
+        auto newKeyStatus = createNewKey(descriptor);
+        if (!newKeyStatus.ok()) {
+            LOG(ERROR) << "Failed to create new key";
+            return false;
+        }
+        mKeyMetadata = *newKeyStatus;
+    } else {
+        mKeyMetadata = keyEntryResponse.metadata;
+    }
+
+    LOG(ERROR) << "Initialized Keystore key.";
+    return true;
+}
+
+Result<SigningKey*> KeystoreKey::getInstance() {
+    static KeystoreKey keystoreKey;
+
+    if (!keystoreKey.initialize()) {
+        return Error() << "Failed to initialize keystore key.";
+    } else {
+        return &keystoreKey;
+    }
+}
+
+static std::vector<KeyParameter> getSignOpParameters() {
+    std::vector<KeyParameter> opParameters;
+
+    KeyParameter algo;
+    algo.tag = Tag::ALGORITHM;
+    algo.value = KeyParameterValue::make<KeyParameterValue::algorithm>(Algorithm::RSA);
+    opParameters.push_back(algo);
+
+    KeyParameter digest;
+    digest.tag = Tag::DIGEST;
+    digest.value = KeyParameterValue::make<KeyParameterValue::digest>(Digest::SHA_2_256);
+    opParameters.push_back(digest);
+
+    KeyParameter padding;
+    padding.tag = Tag::PADDING;
+    padding.value =
+        KeyParameterValue::make<KeyParameterValue::paddingMode>(PaddingMode::RSA_PKCS1_1_5_SIGN);
+    opParameters.push_back(padding);
+
+    KeyParameter purpose;
+    purpose.tag = Tag::PURPOSE;
+    purpose.value = KeyParameterValue::make<KeyParameterValue::keyPurpose>(KeyPurpose::SIGN);
+    opParameters.push_back(purpose);
+
+    return opParameters;
+}
+
+Result<std::string> KeystoreKey::sign(const std::string& message) const {
+    static auto opParameters = getSignOpParameters();
+
+    CreateOperationResponse opResponse;
+
+    auto status =
+        mSecurityLevel->createOperation(getKeyDescriptor(), opParameters, false, &opResponse);
+    if (!status.isOk()) {
+        return Error() << "Failed to create keystore signing operation: "
+                       << status.serviceSpecificErrorCode();
+    }
+    auto operation = opResponse.iOperation;
+
+    std::optional<std::vector<uint8_t>> out;
+    status = operation->update({message.begin(), message.end()}, &out);
+    if (!status.isOk()) {
+        return Error() << "Failed to call keystore update operation.";
+    }
+
+    std::optional<std::vector<uint8_t>> signature;
+    status = operation->finish({}, {}, &signature);
+    if (!status.isOk()) {
+        return Error() << "Failed to call keystore finish operation.";
+    }
+
+    if (!signature.has_value()) {
+        return Error() << "Didn't receive a signature from keystore finish operation.";
+    }
+
+    std::string result{signature.value().begin(), signature.value().end()};
+
+    return result;
+}
+
+Result<std::vector<uint8_t>> KeystoreKey::getPublicKey() const {
+    return extractPublicKeyFromX509(mKeyMetadata.certificate.value());
+}
diff --git a/ondevice-signing/KeystoreKey.h b/ondevice-signing/KeystoreKey.h
new file mode 100644
index 0000000..6b9cb57
--- /dev/null
+++ b/ondevice-signing/KeystoreKey.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <optional>
+
+#include <android-base/macros.h>
+#include <android-base/result.h>
+#include <android-base/unique_fd.h>
+
+#include <utils/StrongPointer.h>
+
+#include <android/system/keystore2/IKeystoreService.h>
+
+#include "SigningKey.h"
+
+class KeystoreKey : public SigningKey {
+    using IKeystoreService = ::android::system::keystore2::IKeystoreService;
+    using IKeystoreSecurityLevel = ::android::system::keystore2::IKeystoreSecurityLevel;
+    using KeyDescriptor = ::android::system::keystore2::KeyDescriptor;
+    using KeyMetadata = ::android::system::keystore2::KeyMetadata;
+
+  public:
+    virtual ~KeystoreKey(){};
+    static android::base::Result<SigningKey*> getInstance();
+
+    virtual android::base::Result<std::string> sign(const std::string& message) const;
+    virtual android::base::Result<std::vector<uint8_t>> getPublicKey() const;
+
+  private:
+    KeystoreKey();
+    bool initialize();
+    android::base::Result<KeyMetadata> createNewKey(const KeyDescriptor& descriptor);
+
+    android::sp<IKeystoreService> mService;
+    android::sp<IKeystoreSecurityLevel> mSecurityLevel;
+    KeyMetadata mKeyMetadata;
+};
diff --git a/ondevice-signing/SigningKey.h b/ondevice-signing/SigningKey.h
new file mode 100644
index 0000000..89294fc
--- /dev/null
+++ b/ondevice-signing/SigningKey.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/macros.h>
+#include <android-base/result.h>
+
+class SigningKey {
+  public:
+    virtual ~SigningKey(){};
+    /* Sign a message with an initialized signing key */
+    virtual android::base::Result<std::string> sign(const std::string& message) const = 0;
+    /* Retrieve the associated public key */
+    virtual android::base::Result<std::vector<uint8_t>> getPublicKey() const = 0;
+};
diff --git a/ondevice-signing/VerityUtils.cpp b/ondevice-signing/VerityUtils.cpp
index 3d0b85a..71ba8f6 100644
--- a/ondevice-signing/VerityUtils.cpp
+++ b/ondevice-signing/VerityUtils.cpp
@@ -15,12 +15,14 @@
  */
 
 #include <filesystem>
+#include <map>
 #include <string>
 
 #include <fcntl.h>
 #include <linux/fs.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <sys/wait.h>
 
 #include <android-base/logging.h>
 #include <android-base/unique_fd.h>
@@ -28,7 +30,7 @@
 #include <linux/fsverity.h>
 
 #include "CertUtils.h"
-#include "KeymasterSigningKey.h"
+#include "SigningKey.h"
 
 #define FS_VERITY_MAX_DIGEST_SIZE 64
 
@@ -37,6 +39,8 @@
 using android::base::Result;
 using android::base::unique_fd;
 
+static const char* kFsVerityInitPath = "/system/bin/fsverity_init";
+
 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
 #define cpu_to_le16(v) ((__force __le16)(uint16_t)(v))
 #define le16_to_cpu(v) ((__force uint16_t)(__le16)(v))
@@ -84,7 +88,7 @@
     return std::vector<uint8_t>(&digest->digest[0], &digest->digest[32]);
 }
 
-static Result<std::vector<uint8_t>> signDigest(const KeymasterSigningKey& key,
+static Result<std::vector<uint8_t>> signDigest(const SigningKey& key,
                                                const std::vector<uint8_t>& digest) {
     fsverity_signed_digest* d;
     size_t signed_digest_size = sizeof(*d) + digest.size();
@@ -104,7 +108,7 @@
     return std::vector<uint8_t>(signed_digest->begin(), signed_digest->end());
 }
 
-Result<std::string> enableFsVerity(const std::string& path, const KeymasterSigningKey& key) {
+Result<std::string> enableFsVerity(const std::string& path, const SigningKey& key) {
     auto digest = createDigest(path);
     if (!digest.ok()) {
         return digest.error();
@@ -135,8 +139,8 @@
     return toHex(digest.value());
 }
 
-Result<std::map<std::string, std::string>>
-addFilesToVerityRecursive(const std::string& path, const KeymasterSigningKey& key) {
+Result<std::map<std::string, std::string>> addFilesToVerityRecursive(const std::string& path,
+                                                                     const SigningKey& key) {
     std::map<std::string, std::string> digests;
     std::error_code ec;
 
@@ -213,3 +217,40 @@
 
     return digests;
 }
+
+Result<void> addCertToFsVerityKeyring(const std::string& path) {
+    const char* const argv[] = {kFsVerityInitPath, "--load-extra-key", "fsv_ods"};
+
+    int fd = open(path.c_str(), O_RDONLY | O_CLOEXEC);
+    pid_t pid = fork();
+    if (pid == 0) {
+        dup2(fd, STDIN_FILENO);
+        close(fd);
+        int argc = arraysize(argv);
+        char* argv_child[argc + 1];
+        memcpy(argv_child, argv, argc * sizeof(char*));
+        argv_child[argc] = nullptr;
+        execvp(argv_child[0], const_cast<char**>(argv_child));
+        PLOG(ERROR) << "exec in ForkExecvp";
+        _exit(EXIT_FAILURE);
+    } else {
+        close(fd);
+    }
+    if (pid == -1) {
+        return ErrnoError() << "Failed to fork.";
+    }
+    int status;
+    if (waitpid(pid, &status, 0) == -1) {
+        return ErrnoError() << "waitpid() failed.";
+    }
+    if (!WIFEXITED(status)) {
+        return Error() << kFsVerityInitPath << ": abnormal process exit";
+    }
+    if (WEXITSTATUS(status)) {
+        if (status != 0) {
+            return Error() << kFsVerityInitPath << " exited with " << status;
+        }
+    }
+
+    return {};
+}
diff --git a/ondevice-signing/VerityUtils.h b/ondevice-signing/VerityUtils.h
index d913073..84af319 100644
--- a/ondevice-signing/VerityUtils.h
+++ b/ondevice-signing/VerityUtils.h
@@ -18,10 +18,11 @@
 
 #include <android-base/result.h>
 
-#include "KeymasterSigningKey.h"
+#include "SigningKey.h"
 
+android::base::Result<void> addCertToFsVerityKeyring(const std::string& path);
 android::base::Result<std::vector<uint8_t>> createDigest(const std::string& path);
 android::base::Result<std::map<std::string, std::string>>
 verifyAllFilesInVerity(const std::string& path);
 android::base::Result<std::map<std::string, std::string>>
-addFilesToVerityRecursive(const std::string& path, const KeymasterSigningKey& key);
+addFilesToVerityRecursive(const std::string& path, const SigningKey& key);
diff --git a/ondevice-signing/odsign_main.cpp b/ondevice-signing/odsign_main.cpp
index 1c63ecb..853f349 100644
--- a/ondevice-signing/odsign_main.cpp
+++ b/ondevice-signing/odsign_main.cpp
@@ -22,7 +22,6 @@
 #include <iterator>
 #include <sys/stat.h>
 #include <sys/types.h>
-#include <sys/wait.h>
 #include <unistd.h>
 
 #include <android-base/file.h>
@@ -32,6 +31,7 @@
 
 #include "CertUtils.h"
 #include "KeymasterSigningKey.h"
+#include "KeystoreKey.h"
 #include "VerityUtils.h"
 
 #include "odsign_info.pb.h"
@@ -51,57 +51,12 @@
 
 static const char* kOdrefreshPath = "/apex/com.android.art/bin/odrefresh";
 
-static const char* kFsVerityInitPath = "/system/bin/fsverity_init";
 static const char* kFsVerityProcPath = "/proc/sys/fs/verity";
 
 static const bool kForceCompilation = false;
+static const bool kUseKeystore = false;
 
-Result<void> addCertToFsVerityKeyring(const std::string& path) {
-    const char* const argv[] = {kFsVerityInitPath, "--load-extra-key", "fsv_ods"};
-
-    // NOLINTNEXTLINE(android-cloexec-open): Deliberately not O_CLOEXEC
-    int fd = open(path.c_str(), O_RDONLY);
-    pid_t pid = fork();
-    if (pid == 0) {
-        dup2(fd, STDIN_FILENO);
-        close(fd);
-        int argc = arraysize(argv);
-        char* argv_child[argc + 1];
-        memcpy(argv_child, argv, argc * sizeof(char*));
-        argv_child[argc] = nullptr;
-        execvp(argv_child[0], const_cast<char**>(argv_child));
-        PLOG(ERROR) << "exec in ForkExecvp";
-        _exit(EXIT_FAILURE);
-    } else {
-        close(fd);
-    }
-    if (pid == -1) {
-        return ErrnoError() << "Failed to fork.";
-    }
-    int status;
-    if (waitpid(pid, &status, 0) == -1) {
-        return ErrnoError() << "waitpid() failed.";
-    }
-    if (!WIFEXITED(status)) {
-        return Error() << kFsVerityInitPath << ": abnormal process exit";
-    }
-    if (WEXITSTATUS(status)) {
-        if (status != 0) {
-            return Error() << kFsVerityInitPath << " exited with " << status;
-        }
-    }
-
-    return {};
-}
-
-Result<KeymasterSigningKey> loadAndVerifyExistingKey() {
-    if (access(kSigningKeyBlob.c_str(), F_OK) < 0) {
-        return ErrnoError() << "Key blob not found: " << kSigningKeyBlob;
-    }
-    return KeymasterSigningKey::loadFromBlobAndVerify(kSigningKeyBlob);
-}
-
-Result<void> verifyExistingCert(const KeymasterSigningKey& key) {
+Result<void> verifyExistingCert(const SigningKey& key) {
     if (access(kSigningKeyCert.c_str(), F_OK) < 0) {
         return ErrnoError() << "Key certificate not found: " << kSigningKeyCert;
     }
@@ -123,19 +78,18 @@
     return {};
 }
 
-Result<KeymasterSigningKey> createAndPersistKey(const std::string& path) {
-    auto key = KeymasterSigningKey::createNewKey();
+Result<void> createX509Cert(const SigningKey& key, const std::string& outPath) {
+    auto publicKey = key.getPublicKey();
 
-    if (!key.ok()) {
-        return key.error();
+    if (!publicKey.ok()) {
+        return publicKey.error();
     }
 
-    auto result = key->saveKeyblob(path);
-    if (!result.ok()) {
-        return result.error();
-    }
-
-    return key;
+    auto keymasterSignFunction = [&](const std::string& to_be_signed) {
+        return key.sign(to_be_signed);
+    };
+    createSelfSignedCertificate(*publicKey, keymasterSignFunction, outPath);
+    return {};
 }
 
 bool compileArtifacts(bool force) {
@@ -224,7 +178,7 @@
     return verifyDigests(*result, trusted_digests);
 }
 
-Result<OdsignInfo> getOdsignInfo(const KeymasterSigningKey& /* key */) {
+Result<OdsignInfo> getOdsignInfo(const SigningKey& /* key */) {
     std::string persistedSignature;
     OdsignInfo odsignInfo;
 
@@ -263,7 +217,7 @@
 }
 
 Result<void> persistDigests(const std::map<std::string, std::string>& digests,
-                            const KeymasterSigningKey& key) {
+                            const SigningKey& key) {
     OdsignInfo signInfo;
     google::protobuf::Map<std::string, std::string> proto_hashes(digests.begin(), digests.end());
     auto map = signInfo.mutable_file_hashes();
@@ -304,17 +258,22 @@
     // Make sure we delete the artifacts in all early (error) exit paths
     auto scope_guard = android::base::make_scope_guard(removeArtifacts);
 
-    auto key = loadAndVerifyExistingKey();
-    if (!key.ok()) {
-        LOG(WARNING) << key.error().message();
-
-        key = createAndPersistKey(kSigningKeyBlob);
-        if (!key.ok()) {
-            LOG(ERROR) << "Failed to create or persist new key: " << key.error().message();
+    SigningKey* key;
+    if (kUseKeystore) {
+        auto keystoreResult = KeystoreKey::getInstance();
+        if (!keystoreResult.ok()) {
+            LOG(ERROR) << "Could not create keystore key: " << keystoreResult.error().message();
             return -1;
         }
+        key = keystoreResult.value();
     } else {
-        LOG(INFO) << "Found and verified existing key: " << kSigningKeyBlob;
+        // TODO - keymaster will go away
+        auto keymasterResult = KeymasterSigningKey::getInstance();
+        if (!keymasterResult.ok()) {
+            LOG(ERROR) << "Failed to create keymaster key: " << keymasterResult.error().message();
+            return -1;
+        }
+        key = keymasterResult.value();
     }
 
     bool supportsFsVerity = access(kFsVerityProcPath, F_OK) == 0;
@@ -323,12 +282,12 @@
     }
 
     if (supportsFsVerity) {
-        auto existing_cert = verifyExistingCert(key.value());
+        auto existing_cert = verifyExistingCert(*key);
         if (!existing_cert.ok()) {
             LOG(WARNING) << existing_cert.error().message();
 
             // Try to create a new cert
-            auto new_cert = key->createX509Cert(kSigningKeyCert);
+            auto new_cert = createX509Cert(*key, kSigningKeyCert);
             if (!new_cert.ok()) {
                 LOG(ERROR) << "Failed to create X509 certificate: " << new_cert.error().message();
                 // TODO apparently the key become invalid - delete the blob / cert
@@ -345,7 +304,7 @@
         }
     }
 
-    auto signInfo = getOdsignInfo(key.value());
+    auto signInfo = getOdsignInfo(*key);
     if (!signInfo.ok()) {
         int num_removed = removeArtifacts();
         // Only a warning if there were artifacts to begin with, which suggests tampering or
@@ -381,7 +340,7 @@
 
         Result<std::map<std::string, std::string>> digests;
         if (supportsFsVerity) {
-            digests = addFilesToVerityRecursive(kArtArtifactsDir, key.value());
+            digests = addFilesToVerityRecursive(kArtArtifactsDir, *key);
         } else {
             // If we can't use verity, just compute the root hashes and store
             // those, so we can reverify them at the next boot.
@@ -392,7 +351,7 @@
             return -1;
         }
 
-        auto persistStatus = persistDigests(*digests, key.value());
+        auto persistStatus = persistDigests(*digests, *key);
         if (!persistStatus.ok()) {
             LOG(ERROR) << persistStatus.error().message();
             return -1;