Add (fake) CompOS key generation.
Note: the CompOS work here is all still behind an if (false).
Added a new class, FakeCompOs, to allow prototyping of the interface
and implementation of the key management work that will be in CompOS.
Extensive refactoring of the certificate generation code to support
both a self-signed cert and our certificate for the CompOS key.
Bug: 190166662
Test: presubmits
Test: manual - certificate gets generated on first boot
Test: manual - certificate verifies ok on second boot
Test: manual inspection of the generated certs' text form
Change-Id: I2f2f043427774c0805e963dfe582feb8d3eac3a4
diff --git a/ondevice-signing/Android.bp b/ondevice-signing/Android.bp
index 432e585..9085d81 100644
--- a/ondevice-signing/Android.bp
+++ b/ondevice-signing/Android.bp
@@ -84,6 +84,7 @@
srcs: [
"odsign_main.cpp",
"CertUtils.cpp",
+ "FakeCompOs.cpp",
"KeystoreKey.cpp",
"KeystoreHmacKey.cpp",
"VerityUtils.cpp",
diff --git a/ondevice-signing/CertUtils.cpp b/ondevice-signing/CertUtils.cpp
index 9867f62..ce2b0fd 100644
--- a/ondevice-signing/CertUtils.cpp
+++ b/ondevice-signing/CertUtils.cpp
@@ -26,39 +26,55 @@
#include <openssl/x509.h>
#include <openssl/x509v3.h>
-#include <fcntl.h>
+#include <optional>
#include <vector>
#include "KeyConstants.h"
-const char kBasicConstraints[] = "CA:TRUE";
-const char kKeyUsage[] = "critical,keyCertSign,cRLSign,digitalSignature";
-const char kSubjectKeyIdentifier[] = "hash";
-const char kAuthorityKeyIdentifier[] = "keyid:always";
+const char kRootCommonName[] = "ODS";
constexpr int kCertLifetimeSeconds = 10 * 365 * 24 * 60 * 60;
-using android::base::Result;
-// using android::base::ErrnoError;
+using android::base::ErrnoError;
using android::base::Error;
+using android::base::Result;
-static bool add_ext(X509* cert, int nid, const char* value) {
- size_t len = strlen(value) + 1;
- std::vector<char> mutableValue(value, value + len);
- X509V3_CTX context;
+static Result<bssl::UniquePtr<X509>> loadX509(const std::string& path) {
+ X509* rawCert;
+ auto f = fopen(path.c_str(), "re");
+ if (f == nullptr) {
+ return Error() << "Failed to open " << path;
+ }
+ if (!d2i_X509_fp(f, &rawCert)) {
+ fclose(f);
+ return Error() << "Unable to decode x509 cert at " << path;
+ }
+ bssl::UniquePtr<X509> cert(rawCert);
- X509V3_set_ctx_nodb(&context);
+ fclose(f);
+ return cert;
+}
- X509V3_set_ctx(&context, cert, cert, nullptr, nullptr, 0);
- X509_EXTENSION* ex = X509V3_EXT_nconf_nid(nullptr, &context, nid, mutableValue.data());
+static X509V3_CTX makeContext(X509* issuer, X509* subject) {
+ X509V3_CTX context = {};
+ X509V3_set_ctx(&context, issuer, subject, nullptr, nullptr, 0);
+ return context;
+}
+
+static bool add_ext(X509V3_CTX* context, X509* cert, int nid, const char* value) {
+ bssl::UniquePtr<X509_EXTENSION> ex(X509V3_EXT_nconf_nid(nullptr, context, nid, value));
if (!ex) {
return false;
}
- X509_add_ext(cert, ex, -1);
- X509_EXTENSION_free(ex);
+ X509_add_ext(cert, ex.get(), -1);
return true;
}
+static void addNameEntry(X509_NAME* name, const char* field, const char* value) {
+ X509_NAME_add_entry_by_txt(name, field, MBSTRING_ASC,
+ reinterpret_cast<const unsigned char*>(value), -1, -1, 0);
+}
+
Result<bssl::UniquePtr<RSA>> getRsa(const std::vector<uint8_t>& publicKey) {
bssl::UniquePtr<BIGNUM> n(BN_new());
bssl::UniquePtr<BIGNUM> e(BN_new());
@@ -109,19 +125,31 @@
return public_key;
}
-Result<void> createSelfSignedCertificate(
- const std::vector<uint8_t>& publicKey,
- const std::function<Result<std::string>(const std::string&)>& signFunction,
- const std::string& path) {
+static Result<void> createCertificate(
+ const char* commonName, const std::vector<uint8_t>& publicKey,
+ const std::function<android::base::Result<std::string>(const std::string&)>& signFunction,
+ const std::optional<std::string>& issuerCertPath, const std::string& path) {
+
+ // If an issuer cert is specified, we are signing someone else's key.
+ // Otherwise we are signing our key - a self-signed certificate.
+ bool selfSigned = !issuerCertPath;
+
bssl::UniquePtr<X509> x509(X509_new());
if (!x509) {
return Error() << "Unable to allocate x509 container";
}
X509_set_version(x509.get(), 2);
-
- ASN1_INTEGER_set(X509_get_serialNumber(x509.get()), 1);
X509_gmtime_adj(X509_get_notBefore(x509.get()), 0);
X509_gmtime_adj(X509_get_notAfter(x509.get()), kCertLifetimeSeconds);
+ ASN1_INTEGER_set(X509_get_serialNumber(x509.get()), selfSigned ? 1 : 2);
+
+ bssl::UniquePtr<X509_ALGOR> algor(X509_ALGOR_new());
+ if (!algor ||
+ !X509_ALGOR_set0(algor.get(), OBJ_nid2obj(NID_sha256WithRSAEncryption), V_ASN1_NULL,
+ NULL) ||
+ !X509_set1_signature_algo(x509.get(), algor.get())) {
+ return Error() << "Unable to set x509 signature algorithm";
+ }
auto public_key = toRsaPkey(publicKey);
if (!public_key.ok()) {
@@ -132,33 +160,53 @@
return Error() << "Unable to set x509 public key";
}
- X509_NAME* name = X509_get_subject_name(x509.get());
- if (!name) {
+ X509_NAME* subjectName = X509_get_subject_name(x509.get());
+ if (!subjectName) {
return Error() << "Unable to get x509 subject name";
}
- X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC,
- reinterpret_cast<const unsigned char*>("US"), -1, -1, 0);
- X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC,
- reinterpret_cast<const unsigned char*>("Android"), -1, -1, 0);
- X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
- reinterpret_cast<const unsigned char*>("ODS"), -1, -1, 0);
- if (!X509_set_issuer_name(x509.get(), name)) {
- return Error() << "Unable to set x509 issuer name";
+ addNameEntry(subjectName, "C", "US");
+ addNameEntry(subjectName, "O", "Android");
+ addNameEntry(subjectName, "CN", commonName);
+
+ if (selfSigned) {
+ if (!X509_set_issuer_name(x509.get(), subjectName)) {
+ return Error() << "Unable to set x509 issuer name";
+ }
+ } else {
+ X509_NAME* issuerName = X509_get_issuer_name(x509.get());
+ if (!issuerName) {
+ return Error() << "Unable to get x509 issuer name";
+ }
+ addNameEntry(issuerName, "C", "US");
+ addNameEntry(issuerName, "O", "Android");
+ addNameEntry(issuerName, "CN", kRootCommonName);
}
- add_ext(x509.get(), NID_basic_constraints, kBasicConstraints);
- add_ext(x509.get(), NID_key_usage, kKeyUsage);
- add_ext(x509.get(), NID_subject_key_identifier, kSubjectKeyIdentifier);
- add_ext(x509.get(), NID_authority_key_identifier, kAuthorityKeyIdentifier);
+ // Beware: context contains a pointer to issuerCert, so we need to keep it alive.
+ bssl::UniquePtr<X509> issuerCert;
+ X509V3_CTX context;
- bssl::UniquePtr<X509_ALGOR> algor(X509_ALGOR_new());
- if (!algor ||
- !X509_ALGOR_set0(algor.get(), OBJ_nid2obj(NID_sha256WithRSAEncryption), V_ASN1_NULL,
- NULL) ||
- !X509_set1_signature_algo(x509.get(), algor.get())) {
- return Error() << "Unable to set x509 signature algorithm";
+ if (selfSigned) {
+ context = makeContext(x509.get(), x509.get());
+ } else {
+ auto certStatus = loadX509(*issuerCertPath);
+ if (!certStatus.ok()) {
+ return Error() << "Unable to load issuer cert: " << certStatus.error();
+ }
+ issuerCert = std::move(certStatus.value());
+ context = makeContext(issuerCert.get(), x509.get());
}
+ // If it's a self-signed cert we use it for signing certs, otherwise only for signing data.
+ const char* basicConstraints = selfSigned ? "CA:TRUE" : "CA:FALSE";
+ const char* keyUsage =
+ selfSigned ? "critical,keyCertSign,cRLSign,digitalSignature" : "critical,digitalSignature";
+
+ add_ext(&context, x509.get(), NID_basic_constraints, basicConstraints);
+ add_ext(&context, x509.get(), NID_key_usage, keyUsage);
+ add_ext(&context, x509.get(), NID_subject_key_identifier, "hash");
+ add_ext(&context, x509.get(), NID_authority_key_identifier, "keyid:always");
+
// Get the data to be signed
unsigned char* to_be_signed_buf(nullptr);
size_t to_be_signed_length = i2d_re_X509_tbs(x509.get(), &to_be_signed_buf);
@@ -177,14 +225,30 @@
auto f = fopen(path.c_str(), "wbe");
if (f == nullptr) {
- return Error() << "Failed to open " << path;
+ return ErrnoError() << "Failed to open " << path;
}
i2d_X509_fp(f, x509.get());
- fclose(f);
+ if (fclose(f) != 0) {
+ return ErrnoError() << "Failed to close " << path;
+ }
return {};
}
+Result<void> createSelfSignedCertificate(
+ const std::vector<uint8_t>& publicKey,
+ const std::function<Result<std::string>(const std::string&)>& signFunction,
+ const std::string& path) {
+ return createCertificate(kRootCommonName, publicKey, signFunction, {}, path);
+}
+
+android::base::Result<void> createLeafCertificate(
+ const char* commonName, const std::vector<uint8_t>& publicKey,
+ const std::function<android::base::Result<std::string>(const std::string&)>& signFunction,
+ const std::string& issuerCertPath, const std::string& path) {
+ return createCertificate(commonName, publicKey, signFunction, issuerCertPath, path);
+}
+
Result<std::vector<uint8_t>> extractPublicKey(EVP_PKEY* pkey) {
if (pkey == nullptr) {
return Error() << "Failed to extract public key from x509 cert";
@@ -225,22 +289,6 @@
return extractPublicKey(decoded_pkey.get());
}
-static Result<bssl::UniquePtr<X509>> loadX509(const std::string& path) {
- X509* rawCert;
- auto f = fopen(path.c_str(), "re");
- if (f == nullptr) {
- return Error() << "Failed to open " << path;
- }
- if (!d2i_X509_fp(f, &rawCert)) {
- fclose(f);
- return Error() << "Unable to decode x509 cert at " << path;
- }
- bssl::UniquePtr<X509> cert(rawCert);
-
- fclose(f);
- return cert;
-}
-
Result<std::vector<uint8_t>> extractPublicKeyFromX509(const std::string& path) {
auto cert = loadX509(path);
if (!cert.ok()) {
diff --git a/ondevice-signing/CertUtils.h b/ondevice-signing/CertUtils.h
index d202fbc..b412d21 100644
--- a/ondevice-signing/CertUtils.h
+++ b/ondevice-signing/CertUtils.h
@@ -16,6 +16,10 @@
#pragma once
+#include <functional>
+#include <string>
+#include <vector>
+
#include <android-base/result.h>
struct CertInfo {
@@ -27,6 +31,12 @@
const std::vector<uint8_t>& publicKey,
const std::function<android::base::Result<std::string>(const std::string&)>& signFunction,
const std::string& path);
+
+android::base::Result<void> createLeafCertificate(
+ const char* commonName, const std::vector<uint8_t>& publicKey,
+ const std::function<android::base::Result<std::string>(const std::string&)>& signFunction,
+ const std::string& issuerCertPath, const std::string& outPath);
+
android::base::Result<std::vector<uint8_t>> createPkcs7(const std::vector<uint8_t>& signedData);
android::base::Result<std::vector<uint8_t>>
diff --git a/ondevice-signing/FakeCompOs.cpp b/ondevice-signing/FakeCompOs.cpp
new file mode 100644
index 0000000..9a01f12
--- /dev/null
+++ b/ondevice-signing/FakeCompOs.cpp
@@ -0,0 +1,138 @@
+/*
+ * 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 "FakeCompOs.h"
+#include "KeyConstants.h"
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/result.h>
+#include <binder/IServiceManager.h>
+
+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::Domain;
+
+using android::base::Error;
+using android::base::Result;
+
+Result<std::unique_ptr<FakeCompOs>> FakeCompOs::newInstance() {
+ std::unique_ptr<FakeCompOs> compOs(new FakeCompOs);
+ auto init = compOs->initialize();
+ if (init.ok()) {
+ return compOs;
+ } else {
+ return init.error();
+ }
+}
+
+FakeCompOs::FakeCompOs() {}
+
+Result<void> FakeCompOs::initialize() {
+ auto sm = android::defaultServiceManager();
+ if (!sm) {
+ return Error() << "No ServiceManager";
+ }
+ auto rawService = sm->getService(String16("android.system.keystore2.IKeystoreService/default"));
+ if (!rawService) {
+ return Error() << "No Keystore service";
+ }
+ mService = interface_cast<android::system::keystore2::IKeystoreService>(rawService);
+ if (!mService) {
+ return Error() << "Bad Keystore service";
+ }
+
+ // TODO: We probably want SecurityLevel::SOFTWARE here, in the VM, but Keystore doesn't do it
+ auto status = mService->getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT, &mSecurityLevel);
+ if (!status.isOk()) {
+ return Error() << status;
+ }
+
+ return {};
+}
+
+Result<FakeCompOs::KeyData> FakeCompOs::generateKey() {
+ 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);
+
+ KeyDescriptor descriptor;
+ descriptor.domain = Domain::BLOB;
+ // TODO: Allocate a namespace for CompOS
+ descriptor.nspace = 101;
+
+ KeyMetadata metadata;
+ auto status = mSecurityLevel->generateKey(descriptor, {}, params, 0, {}, &metadata);
+ if (!status.isOk()) {
+ return Error() << "Failed to generate key";
+ }
+
+ auto& cert = metadata.certificate;
+ if (!cert) {
+ return Error() << "No certificate.";
+ }
+
+ auto& blob = metadata.key.blob;
+ if (!blob) {
+ return Error() << "No blob.";
+ }
+
+ KeyData key_data{std::move(metadata.certificate.value()), std::move(metadata.key.blob.value())};
+ return key_data;
+}
diff --git a/ondevice-signing/FakeCompOs.h b/ondevice-signing/FakeCompOs.h
new file mode 100644
index 0000000..10c357c
--- /dev/null
+++ b/ondevice-signing/FakeCompOs.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 <memory>
+#include <string>
+#include <vector>
+
+#include <android-base/result.h>
+
+#include <utils/StrongPointer.h>
+
+#include <android/system/keystore2/IKeystoreService.h>
+
+class FakeCompOs {
+ 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:
+ struct KeyData {
+ std::vector<uint8_t> cert;
+ std::vector<uint8_t> blob;
+ };
+
+ static android::base::Result<std::unique_ptr<FakeCompOs>> newInstance();
+
+ android::base::Result<KeyData> generateKey();
+
+ private:
+ FakeCompOs();
+ android::base::Result<void> initialize();
+
+ KeyDescriptor mDescriptor;
+ android::sp<IKeystoreService> mService;
+ android::sp<IKeystoreSecurityLevel> mSecurityLevel;
+};
diff --git a/ondevice-signing/KeystoreKey.h b/ondevice-signing/KeystoreKey.h
index 1257cbb..f2fbb70 100644
--- a/ondevice-signing/KeystoreKey.h
+++ b/ondevice-signing/KeystoreKey.h
@@ -20,7 +20,6 @@
#include <android-base/macros.h>
#include <android-base/result.h>
-#include <android-base/unique_fd.h>
#include <utils/StrongPointer.h>
diff --git a/ondevice-signing/odsign_main.cpp b/ondevice-signing/odsign_main.cpp
index 135c4a0..f50df64 100644
--- a/ondevice-signing/odsign_main.cpp
+++ b/ondevice-signing/odsign_main.cpp
@@ -32,6 +32,7 @@
#include <odrefresh/odrefresh.h>
#include "CertUtils.h"
+#include "FakeCompOs.h"
#include "KeystoreKey.h"
#include "VerityUtils.h"
@@ -58,7 +59,10 @@
static const bool kUseCompOs = false; // STOPSHIP if true
static const char* kVirtApexPath = "/apex/com.android.virt";
+static const char* kCompOsCommonName = "CompOS";
const std::string kCompOsCert = "/data/misc/odsign/compos_key.cert";
+const std::string kCompOsPublicKey = "/data/misc/odsign/compos_key.pubkey";
+const std::string kCompOsKeyBlob = "/data/misc/odsign/compos_key.blob";
static const char* kOdsignVerificationDoneProp = "odsign.verification.done";
static const char* kOdsignKeyDoneProp = "odsign.key.done";
@@ -67,6 +71,11 @@
static const char* kOdsignVerificationStatusValid = "1";
static const char* kOdsignVerificationStatusError = "0";
+static void writeBytesToFile(const std::vector<uint8_t>& bytes, const std::string& path) {
+ std::string str(bytes.begin(), bytes.end());
+ android::base::WriteStringToFile(str, path);
+}
+
bool compOsPresent() {
return access(kVirtApexPath, F_OK) == 0;
}
@@ -102,8 +111,7 @@
}
auto keySignFunction = [&](const std::string& to_be_signed) { return key.sign(to_be_signed); };
- createSelfSignedCertificate(*publicKey, keySignFunction, outPath);
- return {};
+ return createSelfSignedCertificate(*publicKey, keySignFunction, outPath);
}
Result<std::vector<uint8_t>> extractPublicKeyFromLeafCert(const SigningKey& key,
@@ -132,6 +140,34 @@
return existingCertInfo.value().subjectKey;
}
+Result<void> generateCompOsKey(const SigningKey& key) {
+ auto compOs = FakeCompOs::newInstance();
+ if (!compOs.ok()) {
+ return Error() << "Failed to start CompOs: " << compOs.error();
+ }
+ auto keyData = compOs.value()->generateKey();
+ if (!keyData.ok()) {
+ return Error() << "Failed to generate key: " << keyData.error();
+ }
+ auto publicKey = extractPublicKeyFromX509(keyData.value().cert);
+ if (!publicKey.ok()) {
+ return Error() << "Failed to extract CompOs public key" << publicKey.error();
+ }
+
+ auto keySignFunction = [&](const std::string& to_be_signed) { return key.sign(to_be_signed); };
+ auto certStatus = createLeafCertificate(kCompOsCommonName, publicKey.value(), keySignFunction,
+ kSigningKeyCert, kCompOsCert);
+ if (!certStatus.ok()) {
+ return Error() << "Failed to create CompOs cert: " << certStatus.error();
+ }
+
+ // TODO: Make use of these
+ writeBytesToFile(keyData.value().blob, kCompOsKeyBlob);
+ writeBytesToFile(publicKey.value(), kCompOsPublicKey);
+
+ return {};
+}
+
art::odrefresh::ExitCode compileArtifacts(bool force) {
const char* const argv[] = {kOdrefreshPath, force ? "--force-compile" : "--compile"};
const int exit_code =
@@ -334,7 +370,7 @@
auto keystoreResult = KeystoreKey::getInstance();
if (!keystoreResult.ok()) {
- LOG(ERROR) << "Could not create keystore key: " << keystoreResult.error().message();
+ LOG(ERROR) << "Could not create keystore key: " << keystoreResult.error();
return -1;
}
SigningKey* key = keystoreResult.value();
@@ -349,12 +385,12 @@
if (supportsFsVerity) {
auto existing_cert = verifyExistingRootCert(*key);
if (!existing_cert.ok()) {
- LOG(WARNING) << existing_cert.error().message();
+ LOG(WARNING) << existing_cert.error();
// Try to create a new cert
auto new_cert = createX509RootCert(*key, kSigningKeyCert);
if (!new_cert.ok()) {
- LOG(ERROR) << "Failed to create X509 certificate: " << new_cert.error().message();
+ LOG(ERROR) << "Failed to create X509 certificate: " << new_cert.error();
// TODO apparently the key become invalid - delete the blob / cert
return -1;
}
@@ -364,29 +400,34 @@
auto cert_add_result = addCertToFsVerityKeyring(kSigningKeyCert, "fsv_ods");
if (!cert_add_result.ok()) {
LOG(ERROR) << "Failed to add certificate to fs-verity keyring: "
- << cert_add_result.error().message();
+ << cert_add_result.error();
return -1;
}
}
if (supportsCompOs) {
- auto compos_key = extractPublicKeyFromLeafCert(*key, kCompOsCert, "CompOS");
- if (compos_key.ok()) {
- auto cert_add_result = addCertToFsVerityKeyring(kCompOsCert, "fsv_compos");
- if (cert_add_result.ok()) {
- LOG(INFO) << "Added CompOs key to fs-verity keyring";
+ auto compos_key = extractPublicKeyFromLeafCert(*key, kCompOsCert, kCompOsCommonName);
+ if (!compos_key.ok()) {
+ LOG(WARNING) << compos_key.error();
+
+ auto status = generateCompOsKey(*key);
+ if (!status.ok()) {
+ LOG(ERROR) << status.error();
} else {
- LOG(ERROR) << "Failed to add CompOs certificate to fs-verity keyring: "
- << cert_add_result.error().message();
- // TODO - what do we do now?
- // return -1;
+ LOG(INFO) << "Generated new CompOs public key certificate";
}
} else {
- LOG(ERROR) << "Failed to retrieve key from CompOs certificate: "
- << compos_key.error().message();
+ LOG(INFO) << "Found and verified existing CompOs public key certificate: "
+ << kCompOsCert;
+ };
+ auto cert_add_result = addCertToFsVerityKeyring(kCompOsCert, "fsv_compos");
+ if (!cert_add_result.ok()) {
+ LOG(ERROR) << "Failed to add CompOs certificate to fs-verity keyring: "
+ << cert_add_result.error();
// Best efforts only - nothing we can do if deletion fails.
unlink(kCompOsCert.c_str());
// TODO - what do we do now?
+ // return -1;
}
}
@@ -402,7 +443,7 @@
if (artifactsPresent) {
auto verificationResult = verifyArtifacts(*key, supportsFsVerity);
if (!verificationResult.ok()) {
- LOG(ERROR) << verificationResult.error().message();
+ LOG(ERROR) << verificationResult.error();
return -1;
}
}
@@ -420,12 +461,12 @@
digests = computeDigests(kArtArtifactsDir);
}
if (!digests.ok()) {
- LOG(ERROR) << digests.error().message();
+ LOG(ERROR) << digests.error();
return -1;
}
auto persistStatus = persistDigests(*digests, *key);
if (!persistStatus.ok()) {
- LOG(ERROR) << persistStatus.error().message();
+ LOG(ERROR) << persistStatus.error();
return -1;
}
} else if (odrefresh_status == art::odrefresh::ExitCode::kCleanupFailed) {
@@ -444,5 +485,6 @@
// And we did a successful verification
SetProperty(kOdsignVerificationDoneProp, "1");
SetProperty(kOdsignVerificationStatusProp, kOdsignVerificationStatusValid);
+
return 0;
}