Merge "Enable sqlite3 logging in keystore2"
diff --git a/OWNERS b/OWNERS
index 4e214e8..93c024d 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,7 +1,8 @@
-swillden@google.com
cbrubaker@google.com
-jdanis@google.com
hasinitg@google.com
-kroot@google.com
-zeuthen@google.com
jbires@google.com
+jdanis@google.com
+kroot@google.com
+sethmo@google.com
+swillden@google.com
+zeuthen@google.com
diff --git a/keystore2/Android.bp b/keystore2/Android.bp
index 3f98cb5..9c3ce6e 100644
--- a/keystore2/Android.bp
+++ b/keystore2/Android.bp
@@ -134,7 +134,6 @@
"libkeystore2_aaid",
"libkeystore2_apc_compat",
"libkeystore2_crypto",
- "libkeystore2_vintf_cpp",
"libkm_compat_service",
"libkm_compat",
"libm",
diff --git a/keystore2/aidl/Android.bp b/keystore2/aidl/Android.bp
index 3bcec07..4a7b7b4 100644
--- a/keystore2/aidl/Android.bp
+++ b/keystore2/aidl/Android.bp
@@ -132,7 +132,7 @@
name: "android.security.maintenance",
srcs: [ "android/security/maintenance/*.aidl" ],
imports: [
- "android.system.keystore2",
+ "android.system.keystore2-V1",
],
unstable: true,
backend: {
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/keystore2/src/globals.rs b/keystore2/src/globals.rs
index a03a61c..eae5ad0 100644
--- a/keystore2/src/globals.rs
+++ b/keystore2/src/globals.rs
@@ -208,14 +208,14 @@
let service_name = match *security_level {
SecurityLevel::TRUSTED_ENVIRONMENT => {
- if keymint_instances.as_vec()?.iter().any(|instance| *instance == "default") {
+ if keymint_instances.iter().any(|instance| *instance == "default") {
Some(format!("{}/default", KEYMINT_SERVICE_NAME))
} else {
None
}
}
SecurityLevel::STRONGBOX => {
- if keymint_instances.as_vec()?.iter().any(|instance| *instance == "strongbox") {
+ if keymint_instances.iter().any(|instance| *instance == "strongbox") {
Some(format!("{}/strongbox", KEYMINT_SERVICE_NAME))
} else {
None
@@ -319,7 +319,7 @@
get_aidl_instances("android.hardware.security.secureclock", 1, "ISecureClock");
let secure_clock_available =
- secureclock_instances.as_vec()?.iter().any(|instance| *instance == "default");
+ secureclock_instances.iter().any(|instance| *instance == "default");
let default_time_stamp_service_name = format!("{}/default", TIME_STAMP_SERVICE_NAME);
@@ -372,14 +372,14 @@
let service_name = match *security_level {
SecurityLevel::TRUSTED_ENVIRONMENT => {
- if remotely_prov_instances.as_vec()?.iter().any(|instance| *instance == "default") {
+ if remotely_prov_instances.iter().any(|instance| *instance == "default") {
Some(format!("{}/default", REMOTE_PROVISIONING_HAL_SERVICE_NAME))
} else {
None
}
}
SecurityLevel::STRONGBOX => {
- if remotely_prov_instances.as_vec()?.iter().any(|instance| *instance == "strongbox") {
+ if remotely_prov_instances.iter().any(|instance| *instance == "strongbox") {
Some(format!("{}/strongbox", REMOTE_PROVISIONING_HAL_SERVICE_NAME))
} else {
None
diff --git a/keystore2/src/shared_secret_negotiation.rs b/keystore2/src/shared_secret_negotiation.rs
index e32b675..1862f73 100644
--- a/keystore2/src/shared_secret_negotiation.rs
+++ b/keystore2/src/shared_secret_negotiation.rs
@@ -21,7 +21,7 @@
ISharedSecret::ISharedSecret, SharedSecretParameters::SharedSecretParameters,
};
use android_security_compat::aidl::android::security::compat::IKeystoreCompatService::IKeystoreCompatService;
-use anyhow::{Context, Result};
+use anyhow::Result;
use keystore2_vintf::{get_aidl_instances, get_hidl_instances};
use std::fmt::{self, Display, Formatter};
use std::time::Duration;
@@ -118,48 +118,32 @@
.iter()
.map(|(ma, mi)| {
get_hidl_instances(KEYMASTER_PACKAGE_NAME, *ma, *mi, KEYMASTER_INTERFACE_NAME)
- .as_vec()
- .with_context(|| format!("Trying to convert KM{}.{} names to vector.", *ma, *mi))
- .map(|instances| {
- instances
- .into_iter()
- .filter_map(|name| {
- filter_map_legacy_km_instances(name.to_string(), (*ma, *mi)).and_then(
- |sp| {
- if let SharedSecretParticipant::Hidl {
- is_strongbox: true,
- ..
- } = &sp
- {
- if !legacy_strongbox_found {
- legacy_strongbox_found = true;
- return Some(sp);
- }
- } else if !legacy_default_found {
- legacy_default_found = true;
- return Some(sp);
- }
- None
- },
- )
- })
- .collect::<Vec<SharedSecretParticipant>>()
+ .into_iter()
+ .filter_map(|name| {
+ filter_map_legacy_km_instances(name, (*ma, *mi)).and_then(|sp| {
+ if let SharedSecretParticipant::Hidl { is_strongbox: true, .. } = &sp {
+ if !legacy_strongbox_found {
+ legacy_strongbox_found = true;
+ return Some(sp);
+ }
+ } else if !legacy_default_found {
+ legacy_default_found = true;
+ return Some(sp);
+ }
+ None
+ })
})
+ .collect::<Vec<SharedSecretParticipant>>()
})
- .collect::<Result<Vec<_>>>()
- .map(|v| v.into_iter().flatten())
- .and_then(|i| {
- Ok(i.chain(
- get_aidl_instances(SHARED_SECRET_PACKAGE_NAME, 1, SHARED_SECRET_INTERFACE_NAME)
- .as_vec()
- .context("In list_participants: Trying to convert KM1.0 names to vector.")?
- .into_iter()
- .map(|name| SharedSecretParticipant::Aidl(name.to_string()))
- .collect::<Vec<_>>()
- .into_iter(),
- ))
+ .into_iter()
+ .flatten()
+ .chain({
+ get_aidl_instances(SHARED_SECRET_PACKAGE_NAME, 1, SHARED_SECRET_INTERFACE_NAME)
+ .into_iter()
+ .map(SharedSecretParticipant::Aidl)
+ .collect::<Vec<_>>()
+ .into_iter()
})
- .context("In list_participants.")?
.collect())
}
diff --git a/keystore2/src/vintf/Android.bp b/keystore2/src/vintf/Android.bp
index 352f2be..34719aa 100644
--- a/keystore2/src/vintf/Android.bp
+++ b/keystore2/src/vintf/Android.bp
@@ -26,39 +26,32 @@
crate_name: "keystore2_vintf",
srcs: ["lib.rs"],
rustlibs: [
- "libkeystore2_vintf_bindgen",
+ "libcxx",
],
shared_libs: [
+ "libvintf",
+ ],
+ static_libs: [
"libkeystore2_vintf_cpp",
- "libvintf",
],
}
-cc_library {
+cc_library_static {
name: "libkeystore2_vintf_cpp",
- srcs: [
- "vintf.cpp",
- ],
+ srcs: ["vintf.cpp"],
+ generated_headers: ["cxx-bridge-header"],
+ generated_sources: ["vintf_bridge_code"],
shared_libs: [
"libvintf",
],
}
-rust_bindgen {
- name: "libkeystore2_vintf_bindgen",
- wrapper_src: "vintf.hpp",
- crate_name: "keystore2_vintf_bindgen",
- source_stem: "bindings",
- host_supported: true,
- shared_libs: ["libvintf"],
- bindgen_flags: [
- "--size_t-is-usize",
- "--allowlist-function", "getHalNames",
- "--allowlist-function", "getHalNamesAndVersions",
- "--allowlist-function", "getHidlInstances",
- "--allowlist-function", "getAidlInstances",
- "--allowlist-function", "freeNames",
- ],
+genrule {
+ name: "vintf_bridge_code",
+ tools: ["cxxbridge"],
+ cmd: "$(location cxxbridge) $(in) >> $(out)",
+ srcs: ["lib.rs"],
+ out: ["vintf_cxx_generated.cc"],
}
rust_test {
@@ -68,7 +61,7 @@
test_suites: ["general-tests"],
auto_gen_config: true,
rustlibs: [
- "libkeystore2_vintf_bindgen",
+ "libcxx",
],
static_libs: [
"libkeystore2_vintf_cpp",
@@ -78,13 +71,3 @@
"libvintf",
],
}
-
-rust_test {
- name: "libkeystore2_vintf_bindgen_test",
- srcs: [":libkeystore2_vintf_bindgen"],
- crate_name: "keystore2_vintf_bindgen_test",
- test_suites: ["general-tests"],
- auto_gen_config: true,
- clippy_lints: "none",
- lints: "none",
-}
diff --git a/keystore2/src/vintf/lib.rs b/keystore2/src/vintf/lib.rs
index 8730a3e..89e18eb 100644
--- a/keystore2/src/vintf/lib.rs
+++ b/keystore2/src/vintf/lib.rs
@@ -14,96 +14,35 @@
//! Bindings for getting the list of HALs.
-use keystore2_vintf_bindgen::{
- freeNames, getAidlInstances, getHalNames, getHalNamesAndVersions, getHidlInstances,
-};
-use std::ffi::{CStr, CString};
-use std::os::raw::c_char;
-use std::str::Utf8Error;
+#[cxx::bridge]
+mod ffi {
+ unsafe extern "C++" {
+ include!("vintf.hpp");
-/// A struct that contains a list of HALs (optionally with version numbers).
-/// To use it, call as_vec to get a Vec view of the data it contains.
-pub struct HalNames {
- data: *mut *mut c_char,
- len: usize,
-}
+ /// Gets all HAL names.
+ /// Note that this is not a zero-cost shim: it will make copies of the strings.
+ fn get_hal_names() -> Vec<String>;
-impl Drop for HalNames {
- fn drop(&mut self) {
- // Safety: The memory is allocated by our C shim so it must free it as well.
- unsafe { freeNames(self.data, self.len) }
+ /// Gets all HAL names and versions.
+ /// Note that this is not a zero-cost shim: it will make copies of the strings.
+ fn get_hal_names_and_versions() -> Vec<String>;
+
+ /// Gets the instances of the given package, version, and interface tuple.
+ /// Note that this is not a zero-cost shim: it will make copies of the strings.
+ fn get_hidl_instances(
+ package: &str,
+ major_version: usize,
+ minor_version: usize,
+ interface_name: &str,
+ ) -> Vec<String>;
+
+ /// Gets the instances of the given package, version, and interface tuple.
+ /// Note that this is not a zero-cost shim: it will make copies of the strings.
+ fn get_aidl_instances(package: &str, version: usize, interface_name: &str) -> Vec<String>;
}
}
-impl<'a> HalNames {
- /// Get a Vec view of the list of HALs.
- pub fn as_vec(&'a self) -> Result<Vec<&'a str>, Utf8Error> {
- // Safety: self.data contains self.len C strings.
- // The lifetimes ensure that the HalNames (and hence the strings) live
- // at least as long as the returned vector.
- unsafe { (0..self.len).map(|i| CStr::from_ptr(*self.data.add(i)).to_str()) }.collect()
- }
-}
-
-/// Gets all HAL names.
-/// Note that this is not a zero-cost shim: it will make copies of the strings.
-pub fn get_hal_names() -> HalNames {
- let mut len: usize = 0;
- // Safety: We'll wrap this in HalNames to free the memory it allocates.
- // It stores the size of the array it returns in len.
- let raw_strs = unsafe { getHalNames(&mut len) };
- HalNames { data: raw_strs, len }
-}
-
-/// Gets all HAL names and versions.
-/// Note that this is not a zero-cost shim: it will make copies of the strings.
-pub fn get_hal_names_and_versions() -> HalNames {
- let mut len: usize = 0;
- // Safety: We'll wrap this in HalNames to free the memory it allocates.
- // It stores the size of the array it returns in len.
- let raw_strs = unsafe { getHalNamesAndVersions(&mut len) };
- HalNames { data: raw_strs, len }
-}
-
-/// Gets the instances of the given package, version, and interface tuple.
-/// Note that this is not a zero-cost shim: it will make copies of the strings.
-pub fn get_hidl_instances(
- package: &str,
- major_version: usize,
- minor_version: usize,
- interface_name: &str,
-) -> HalNames {
- let mut len: usize = 0;
- let packages = CString::new(package).expect("Failed to make CString from package.");
- let interface_name =
- CString::new(interface_name).expect("Failed to make CString from interface_name.");
- // Safety: We'll wrap this in HalNames to free the memory it allocates.
- // It stores the size of the array it returns in len.
- let raw_strs = unsafe {
- getHidlInstances(
- &mut len,
- packages.as_ptr(),
- major_version,
- minor_version,
- interface_name.as_ptr(),
- )
- };
- HalNames { data: raw_strs, len }
-}
-
-/// Gets the instances of the given package, version, and interface tuple.
-/// Note that this is not a zero-cost shim: it will make copies of the strings.
-pub fn get_aidl_instances(package: &str, version: usize, interface_name: &str) -> HalNames {
- let mut len: usize = 0;
- let packages = CString::new(package).expect("Failed to make CString from package.");
- let interface_name =
- CString::new(interface_name).expect("Failed to make CString from interface_name.");
- // Safety: We'll wrap this in HalNames to free the memory it allocates.
- // It stores the size of the array it returns in len.
- let raw_strs =
- unsafe { getAidlInstances(&mut len, packages.as_ptr(), version, interface_name.as_ptr()) };
- HalNames { data: raw_strs, len }
-}
+pub use ffi::*;
#[cfg(test)]
mod tests {
@@ -111,17 +50,13 @@
use super::*;
#[test]
- fn test() -> Result<(), Utf8Error> {
- let result = get_hal_names();
- let names = result.as_vec()?;
+ fn test() {
+ let names = get_hal_names();
assert_ne!(names.len(), 0);
- let result = get_hal_names_and_versions();
- let names_and_versions = result.as_vec()?;
+ let names_and_versions = get_hal_names_and_versions();
assert_ne!(names_and_versions.len(), 0);
assert!(names_and_versions.len() >= names.len());
-
- Ok(())
}
}
diff --git a/keystore2/src/vintf/vintf.cpp b/keystore2/src/vintf/vintf.cpp
index e407efa..00625bf 100644
--- a/keystore2/src/vintf/vintf.cpp
+++ b/keystore2/src/vintf/vintf.cpp
@@ -14,55 +14,43 @@
* limitations under the License.
*/
-#include "vintf.hpp"
-
+#include <algorithm>
#include <vintf/HalManifest.h>
#include <vintf/VintfObject.h>
-// Converts a set<string> into a C-style array of C strings.
-static char** convert(const std::set<std::string>& names) {
- char** ret = new char*[names.size()];
- char** ptr = ret;
- for (const auto& name : names) {
- *(ptr++) = strdup(name.c_str());
- }
- return ret;
+#include "rust/cxx.h"
+
+rust::Vec<rust::String> convert(const std::set<std::string>& names) {
+ rust::Vec<rust::String> result;
+ std::copy(names.begin(), names.end(), std::back_inserter(result));
+ return result;
}
-char** getHalNames(size_t* len) {
- auto manifest = android::vintf::VintfObject::GetDeviceHalManifest();
+rust::Vec<rust::String> get_hal_names() {
+ const auto manifest = android::vintf::VintfObject::GetDeviceHalManifest();
const auto names = manifest->getHalNames();
- *len = names.size();
return convert(names);
}
-char** getHalNamesAndVersions(size_t* len) {
- auto manifest = android::vintf::VintfObject::GetDeviceHalManifest();
+rust::Vec<rust::String> get_hal_names_and_versions() {
+ const auto manifest = android::vintf::VintfObject::GetDeviceHalManifest();
const auto names = manifest->getHalNamesAndVersions();
- *len = names.size();
return convert(names);
}
-char** getHidlInstances(size_t* len, const char* package, size_t major_version,
- size_t minor_version, const char* interfaceName) {
+rust::Vec<rust::String> get_hidl_instances(rust::Str package, size_t major_version,
+ size_t minor_version, rust::Str interfaceName) {
android::vintf::Version version(major_version, minor_version);
- auto manifest = android::vintf::VintfObject::GetDeviceHalManifest();
- const auto names = manifest->getHidlInstances(package, version, interfaceName);
- *len = names.size();
+ const auto manifest = android::vintf::VintfObject::GetDeviceHalManifest();
+ const auto names = manifest->getHidlInstances(static_cast<std::string>(package), version,
+ static_cast<std::string>(interfaceName));
return convert(names);
}
-char** getAidlInstances(size_t* len, const char* package, size_t version,
- const char* interfaceName) {
- auto manifest = android::vintf::VintfObject::GetDeviceHalManifest();
- const auto names = manifest->getAidlInstances(package, version, interfaceName);
- *len = names.size();
+rust::Vec<rust::String> get_aidl_instances(rust::Str package, size_t version,
+ rust::Str interfaceName) {
+ const auto manifest = android::vintf::VintfObject::GetDeviceHalManifest();
+ const auto names = manifest->getAidlInstances(static_cast<std::string>(package), version,
+ static_cast<std::string>(interfaceName));
return convert(names);
}
-
-void freeNames(char** names, size_t len) {
- for (int i = 0; i < len; i++) {
- free(names[i]);
- }
- delete[] names;
-}
diff --git a/keystore2/src/vintf/vintf.hpp b/keystore2/src/vintf/vintf.hpp
index 091e8e8..dbc88f0 100644
--- a/keystore2/src/vintf/vintf.hpp
+++ b/keystore2/src/vintf/vintf.hpp
@@ -14,20 +14,13 @@
* limitations under the License.
*/
-#ifndef __VINTF_H__
-#define __VINTF_H__
+#pragma once
-#include <stddef.h>
+#include "rust/cxx.h"
-extern "C" {
-
-char** getHalNames(size_t* len);
-char** getHalNamesAndVersions(size_t* len);
-char** getHidlInstances(size_t* len, const char* package, size_t major_version,
- size_t minor_version, const char* interfaceName);
-char** getAidlInstances(size_t* len, const char* package, size_t version,
- const char* interfaceName);
-void freeNames(char** names, size_t len);
-}
-
-#endif // __VINTF_H__
+rust::Vec<rust::String> get_hal_names();
+rust::Vec<rust::String> get_hal_names_and_versions();
+rust::Vec<rust::String> get_hidl_instances(rust::Str package, size_t major_version,
+ size_t minor_version, rust::Str interfaceName);
+rust::Vec<rust::String> get_aidl_instances(rust::Str package, size_t version,
+ rust::Str interfaceName);
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();