Merge "android.security.*: use versions for imports (2)"
diff --git a/keystore/Android.bp b/keystore/Android.bp
index 39208c6..ad4b4b1 100644
--- a/keystore/Android.bp
+++ b/keystore/Android.bp
@@ -102,5 +102,5 @@
export_include_dirs: ["include"],
- vendor_available: true,
+ vendor: true,
}
diff --git a/keystore2/aidl/Android.bp b/keystore2/aidl/Android.bp
index 63e19b0..4a7b7b4 100644
--- a/keystore2/aidl/Android.bp
+++ b/keystore2/aidl/Android.bp
@@ -24,7 +24,7 @@
aidl_interface {
name: "android.security.attestationmanager",
srcs: [ "android/security/attestationmanager/*.aidl", ],
- imports: [ "android.hardware.security.keymint" ],
+ imports: [ "android.hardware.security.keymint-V1" ],
unstable: true,
backend: {
java: {
@@ -45,8 +45,8 @@
name: "android.security.authorization",
srcs: [ "android/security/authorization/*.aidl" ],
imports: [
- "android.hardware.security.keymint",
- "android.hardware.security.secureclock",
+ "android.hardware.security.keymint-V1",
+ "android.hardware.security.secureclock-V1",
],
unstable: true,
backend: {
@@ -86,9 +86,9 @@
name: "android.security.compat",
srcs: [ "android/security/compat/*.aidl" ],
imports: [
- "android.hardware.security.keymint",
- "android.hardware.security.secureclock",
- "android.hardware.security.sharedsecret",
+ "android.hardware.security.keymint-V1",
+ "android.hardware.security.secureclock-V1",
+ "android.hardware.security.sharedsecret-V1",
],
unstable: true,
backend: {
@@ -110,7 +110,7 @@
name: "android.security.remoteprovisioning",
srcs: [ "android/security/remoteprovisioning/*.aidl" ],
imports: [
- "android.hardware.security.keymint",
+ "android.hardware.security.keymint-V1",
],
unstable: true,
backend: {
diff --git a/keystore2/src/async_task.rs b/keystore2/src/async_task.rs
index e130024..0515c8f 100644
--- a/keystore2/src/async_task.rs
+++ b/keystore2/src/async_task.rs
@@ -417,7 +417,9 @@
Err(RecvTimeoutError::Timeout)
);
done_receiver.recv().unwrap();
- idle_done_receiver.recv_timeout(Duration::from_millis(1)).unwrap();
+ // Now that the last low-priority job has completed, the idle task should
+ // fire pretty much immediately.
+ idle_done_receiver.recv_timeout(Duration::from_millis(50)).unwrap();
// Idle callback not executed again even if we wait for a while.
assert_eq!(
@@ -438,7 +440,7 @@
Err(RecvTimeoutError::Timeout)
);
done_receiver.recv().unwrap();
- idle_done_receiver.recv_timeout(Duration::from_millis(1)).unwrap();
+ idle_done_receiver.recv_timeout(Duration::from_millis(50)).unwrap();
}
#[test]
diff --git a/keystore2/src/fuzzers/legacy_blob_fuzzer.rs b/keystore2/src/fuzzers/legacy_blob_fuzzer.rs
index 5c89ca4..7e3e848 100644
--- a/keystore2/src/fuzzers/legacy_blob_fuzzer.rs
+++ b/keystore2/src/fuzzers/legacy_blob_fuzzer.rs
@@ -19,6 +19,8 @@
use keystore2::legacy_blob::LegacyBlobLoader;
fuzz_target!(|data: &[u8]| {
- let string = data.iter().filter_map(|c| std::char::from_u32(*c as u32)).collect::<String>();
- let _res = LegacyBlobLoader::decode_alias(&string);
+ if !data.is_empty() {
+ let string = data.iter().filter_map(|c| std::char::from_u32(*c as u32)).collect::<String>();
+ let _res = LegacyBlobLoader::decode_alias(&string);
+ }
});
diff --git a/ondevice-signing/Android.bp b/ondevice-signing/Android.bp
index 5219240..efa0389 100644
--- a/ondevice-signing/Android.bp
+++ b/ondevice-signing/Android.bp
@@ -84,7 +84,6 @@
srcs: [
"odsign_main.cpp",
"CertUtils.cpp",
- "FakeCompOs.cpp",
"KeystoreKey.cpp",
"KeystoreHmacKey.cpp",
"VerityUtils.cpp",
diff --git a/ondevice-signing/FakeCompOs.cpp b/ondevice-signing/FakeCompOs.cpp
deleted file mode 100644
index 596d6e2..0000000
--- a/ondevice-signing/FakeCompOs.cpp
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * 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 "CertUtils.h"
-#include "KeyConstants.h"
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/result.h>
-#include <android-base/scopeguard.h>
-
-#include <binder/IServiceManager.h>
-
-#include <openssl/nid.h>
-#include <openssl/rand.h>
-#include <openssl/rsa.h>
-#include <openssl/sha.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::CreateOperationResponse;
-using android::system::keystore2::Domain;
-
-using android::base::Error;
-using android::base::Result;
-
-using android::binder::Status;
-
-// TODO: Allocate a namespace for CompOS
-const int64_t kCompOsNamespace = 101;
-
-Result<std::unique_ptr<FakeCompOs>>
-FakeCompOs::startInstance(const std::string& /*instanceImagePath*/) {
- 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::ByteVector> FakeCompOs::signData(const ByteVector& keyBlob,
- const ByteVector& data) const {
- KeyDescriptor descriptor;
- descriptor.domain = Domain::BLOB;
- descriptor.nspace = kCompOsNamespace;
- descriptor.blob = keyBlob;
-
- std::vector<KeyParameter> parameters;
-
- {
- KeyParameter algo;
- algo.tag = Tag::ALGORITHM;
- algo.value = KeyParameterValue::make<KeyParameterValue::algorithm>(Algorithm::RSA);
- parameters.push_back(algo);
-
- KeyParameter digest;
- digest.tag = Tag::DIGEST;
- digest.value = KeyParameterValue::make<KeyParameterValue::digest>(Digest::SHA_2_256);
- parameters.push_back(digest);
-
- KeyParameter padding;
- padding.tag = Tag::PADDING;
- padding.value = KeyParameterValue::make<KeyParameterValue::paddingMode>(
- PaddingMode::RSA_PKCS1_1_5_SIGN);
- parameters.push_back(padding);
-
- KeyParameter purpose;
- purpose.tag = Tag::PURPOSE;
- purpose.value = KeyParameterValue::make<KeyParameterValue::keyPurpose>(KeyPurpose::SIGN);
- parameters.push_back(purpose);
- }
-
- Status status;
-
- CreateOperationResponse response;
- status = mSecurityLevel->createOperation(descriptor, parameters, /*forced=*/false, &response);
- if (!status.isOk()) {
- return Error() << "Failed to create operation: " << status;
- }
-
- auto operation = response.iOperation;
- auto abort_guard = android::base::make_scope_guard([&] { operation->abort(); });
-
- if (response.operationChallenge.has_value()) {
- return Error() << "Key requires user authorization";
- }
-
- std::optional<ByteVector> signature;
- status = operation->finish(data, {}, &signature);
- if (!status.isOk()) {
- return Error() << "Failed to sign data: " << status;
- }
-
- abort_guard.Disable();
-
- if (!signature.has_value()) {
- return Error() << "No signature received from keystore.";
- }
-
- return signature.value();
-}
-
-Result<void> FakeCompOs::loadAndVerifyKey(const ByteVector& keyBlob,
- const ByteVector& publicKey) const {
- // To verify the key is valid, we use it to sign some data, and then verify the signature using
- // the supplied public key.
-
- ByteVector data(32);
- if (RAND_bytes(data.data(), data.size()) != 1) {
- return Error() << "No random bytes";
- }
-
- auto signature = signData(keyBlob, data);
- if (!signature.ok()) {
- return signature.error();
- }
-
- std::string signatureString(reinterpret_cast<char*>(signature.value().data()),
- signature.value().size());
- std::string dataString(reinterpret_cast<char*>(data.data()), data.size());
- return verifyRsaPublicKeySignature(dataString, signatureString, publicKey);
-}
diff --git a/ondevice-signing/FakeCompOs.h b/ondevice-signing/FakeCompOs.h
deleted file mode 100644
index 6c7a445..0000000
--- a/ondevice-signing/FakeCompOs.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.
- */
-
-#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:
- using ByteVector = std::vector<uint8_t>;
-
- static android::base::Result<std::unique_ptr<FakeCompOs>>
- startInstance(const std::string& instanceImagePath);
-
- android::base::Result<void> loadAndVerifyKey(const ByteVector& keyBlob,
- const ByteVector& publicKey) const;
-
- private:
- FakeCompOs();
-
- android::base::Result<void> initialize();
-
- android::base::Result<ByteVector> signData(const ByteVector& keyBlob,
- const ByteVector& data) const;
-
- KeyDescriptor mDescriptor;
- android::sp<IKeystoreService> mService;
- android::sp<IKeystoreSecurityLevel> mSecurityLevel;
-};
diff --git a/ondevice-signing/odsign_main.cpp b/ondevice-signing/odsign_main.cpp
index bba39b8..4a7baad 100644
--- a/ondevice-signing/odsign_main.cpp
+++ b/ondevice-signing/odsign_main.cpp
@@ -32,7 +32,6 @@
#include <odrefresh/odrefresh.h>
#include "CertUtils.h"
-#include "FakeCompOs.h"
#include "KeystoreKey.h"
#include "VerityUtils.h"
@@ -40,6 +39,7 @@
using android::base::ErrnoError;
using android::base::Error;
+using android::base::GetProperty;
using android::base::Result;
using android::base::SetProperty;
@@ -52,24 +52,20 @@
const std::string kArtArtifactsDir = "/data/misc/apexdata/com.android.art/dalvik-cache";
constexpr const char* kOdrefreshPath = "/apex/com.android.art/bin/odrefresh";
-
+constexpr const char* kCompOsVerifyPath = "/apex/com.android.compos/bin/compos_verify_key";
constexpr const char* kFsVerityProcPath = "/proc/sys/fs/verity";
+constexpr const char* kKvmDevicePath = "/dev/kvm";
constexpr bool kForceCompilation = false;
-constexpr bool kUseCompOs = false; // STOPSHIP if true
+constexpr bool kUseCompOs = true;
-constexpr const char* kCompOsApexPath = "/apex/com.android.compos";
const std::string kCompOsCert = "/data/misc/odsign/compos_key.cert";
-const std::string kCompOsPublicKey = "/data/misc/apexdata/com.android.compos/compos_key.pubkey";
-const std::string kCompOsKeyBlob = "/data/misc/apexdata/com.android.compos/compos_key.blob";
-const std::string kCompOsInstance = "/data/misc/apexdata/com.android.compos/compos_instance.img";
+const std::string kCompOsCurrentPublicKey =
+ "/data/misc/apexdata/com.android.compos/current/key.pubkey";
const std::string kCompOsPendingPublicKey =
- "/data/misc/apexdata/com.android.compos/compos_pending_key.pubkey";
-const std::string kCompOsPendingKeyBlob =
- "/data/misc/apexdata/com.android.compos/compos_pending_key.blob";
-const std::string kCompOsPendingInstance =
- "/data/misc/apexdata/com.android.compos/compos_pending_instance.img";
+ "/data/misc/apexdata/com.android.compos/pending/key.pubkey";
+
const std::string kCompOsPendingArtifactsDir = "/data/misc/apexdata/com.android.art/compos-pending";
constexpr const char* kOdsignVerificationDoneProp = "odsign.verification.done";
@@ -81,6 +77,8 @@
constexpr const char* kStopServiceProp = "ctl.stop";
+enum class CompOsInstance { kCurrent, kPending };
+
static std::vector<uint8_t> readBytesFromFile(const std::string& path) {
std::string str;
android::base::ReadFileToString(path, &str);
@@ -140,7 +138,12 @@
}
bool compOsPresent() {
- return access(kCompOsApexPath, F_OK) == 0;
+ return access(kCompOsVerifyPath, X_OK) == 0 && access(kKvmDevicePath, F_OK) == 0;
+}
+
+bool isDebugBuild() {
+ std::string build_type = GetProperty("ro.build.type", "");
+ return build_type == "userdebug" || build_type == "eng";
}
Result<void> verifyExistingRootCert(const SigningKey& key) {
@@ -203,62 +206,36 @@
return existingCertInfo.value().subjectRsaPublicKey;
}
-// Attempt to start a CompOS VM from the given instance image and then get it to
-// verify the public key & key blob. Returns the RsaPublicKey bytes if
-// successful, an empty vector if any of the files are not present, or an error
-// otherwise.
-Result<std::vector<uint8_t>> loadAndVerifyCompOsKey(const std::string& instanceFile,
- const std::string& publicKeyFile,
- const std::string& keyBlobFile) {
- if (access(instanceFile.c_str(), F_OK) != 0 || access(publicKeyFile.c_str(), F_OK) != 0 ||
- access(keyBlobFile.c_str(), F_OK) != 0) {
- return {};
+// Attempt to start a CompOS VM for the specified instance to get it to
+// verify ita public key & key blob.
+bool startCompOsAndVerifyKey(CompOsInstance instance) {
+ bool isCurrent = instance == CompOsInstance::kCurrent;
+ const std::string& keyPath = isCurrent ? kCompOsCurrentPublicKey : kCompOsPendingPublicKey;
+ if (access(keyPath.c_str(), R_OK) != 0) {
+ return false;
}
- auto compOsStatus = FakeCompOs::startInstance(instanceFile);
- if (!compOsStatus.ok()) {
- return Error() << "Failed to start CompOs instance " << instanceFile << ": "
- << compOsStatus.error();
- }
- auto& compOs = compOsStatus.value();
-
- auto publicKey = readBytesFromFile(publicKeyFile);
- auto keyBlob = readBytesFromFile(keyBlobFile);
- auto response = compOs->loadAndVerifyKey(keyBlob, publicKey);
- if (!response.ok()) {
- return response.error();
+ const char* const argv[] = {kCompOsVerifyPath, "--instance", isCurrent ? "current" : "pending"};
+ int result =
+ logwrap_fork_execvp(arraysize(argv), argv, nullptr, false, LOG_ALOG, false, nullptr);
+ if (result == 0) {
+ return true;
}
- return publicKey;
+ LOG(ERROR) << kCompOsVerifyPath << " returned " << result;
+ return false;
}
Result<std::vector<uint8_t>> verifyCompOsKey(const SigningKey& signingKey) {
- std::vector<uint8_t> publicKey;
+ bool verified = false;
// If a pending key has been generated we don't know if it is the correct
// one for the pending CompOS VM, so we need to start it and ask it.
- auto pendingPublicKey = loadAndVerifyCompOsKey(kCompOsPendingInstance, kCompOsPendingPublicKey,
- kCompOsPendingKeyBlob);
- if (pendingPublicKey.ok()) {
- if (!pendingPublicKey->empty()) {
- LOG(INFO) << "Verified pending CompOs key";
-
- if (rename(kCompOsPendingInstance, kCompOsInstance) &&
- rename(kCompOsPendingPublicKey, kCompOsPublicKey) &&
- rename(kCompOsPendingKeyBlob, kCompOsKeyBlob)) {
- publicKey = std::move(*pendingPublicKey);
- }
- }
- } else {
- LOG(WARNING) << "Failed to verify pending CompOs key: " << pendingPublicKey.error();
- // And fall through to dealing with any current key.
+ if (startCompOsAndVerifyKey(CompOsInstance::kPending)) {
+ verified = true;
}
- // Whether good or bad, we've finished with these files.
- unlink(kCompOsPendingInstance.c_str());
- unlink(kCompOsPendingKeyBlob.c_str());
- unlink(kCompOsPendingPublicKey.c_str());
- if (publicKey.empty()) {
+ if (!verified) {
// Alternatively if we signed a cert for the key on a previous boot, then we
// can use that straight away.
auto existing_key =
@@ -270,30 +247,25 @@
}
}
- // Otherwise, if there is an existing key that we haven't signed yet, then we can sign it
- // now if CompOS confirms it's OK.
- if (publicKey.empty()) {
- auto currentPublicKey =
- loadAndVerifyCompOsKey(kCompOsInstance, kCompOsPublicKey, kCompOsKeyBlob);
- if (currentPublicKey.ok()) {
- if (!currentPublicKey->empty()) {
- LOG(INFO) << "Verified existing CompOs key";
- publicKey = std::move(*currentPublicKey);
- }
- } else {
- LOG(WARNING) << "Failed to verify existing CompOs key: " << currentPublicKey.error();
- // Delete so we won't try again on next boot.
- unlink(kCompOsInstance.c_str());
- unlink(kCompOsKeyBlob.c_str());
- unlink(kCompOsPublicKey.c_str());
- }
+ // Otherwise, if there is an existing key that we haven't signed yet, then we can sign
+ // it now if CompOS confirms it's OK.
+ if (!verified && startCompOsAndVerifyKey(CompOsInstance::kCurrent)) {
+ verified = true;
}
- if (publicKey.empty()) {
+ if (!verified) {
return Error() << "No valid CompOs key present.";
}
- // One way or another we now have a valid key pair. Persist a certificate so
+ // If the pending key was verified it will have been promoted to current, so
+ // at this stage if there is a key it will be the current one.
+ auto publicKey = readBytesFromFile(kCompOsCurrentPublicKey);
+ if (publicKey.empty()) {
+ // This shouldn`t really happen.
+ return Error() << "Failed to read CompOs key.";
+ }
+
+ // One way or another we now have a valid public key. Persist a certificate so
// we can simplify the checks on subsequent boots.
auto signFunction = [&](const std::string& to_be_signed) {
@@ -305,6 +277,8 @@
return Error() << "Failed to create CompOs cert: " << certStatus.error();
}
+ LOG(INFO) << "Verified key, wrote new CompOs cert";
+
return publicKey;
}
@@ -546,7 +520,8 @@
int main(int /* argc */, char** /* argv */) {
auto errorScopeGuard = []() {
- // In case we hit any error, remove the artifacts and tell Zygote not to use anything
+ // In case we hit any error, remove the artifacts and tell Zygote not to use
+ // anything
removeDirectory(kArtArtifactsDir);
removeDirectory(kCompOsPendingArtifactsDir);
// Tell init we don't need to use our key anymore
@@ -576,7 +551,7 @@
LOG(INFO) << "Device doesn't support fsverity. Falling back to full verification.";
}
- bool supportsCompOs = kUseCompOs && supportsFsVerity && compOsPresent();
+ bool useCompOs = kUseCompOs && supportsFsVerity && compOsPresent() && isDebugBuild();
if (supportsFsVerity) {
auto existing_cert = verifyExistingRootCert(*key);
@@ -604,7 +579,7 @@
art::odrefresh::ExitCode odrefresh_status = art::odrefresh::ExitCode::kCompilationRequired;
bool digests_verified = false;
- if (supportsCompOs) {
+ if (useCompOs) {
auto compos_key = addCompOsCertToFsVerityKeyring(*key);
if (!compos_key.ok()) {
LOG(WARNING) << compos_key.error();