Support CompOS Key Service in a VM
Add the ability to start the service in a VM, and to then communicate
with it from the host via RPC Binder. Update command-line syntax.
Also revert my recent client naming change, since one tool that can
handle both host & VM seems better than two different ones.
Bug: 193603140
Test: Manual: start service in VM, connect to it, generate & verify keys.
Change-Id: I3cdb25395537e29bbfaa957eeac0c16ba4de93de
diff --git a/compos/compos_key_cmd/Android.bp b/compos/compos_key_cmd/Android.bp
index 460b96f..00d1035 100644
--- a/compos/compos_key_cmd/Android.bp
+++ b/compos/compos_key_cmd/Android.bp
@@ -14,6 +14,7 @@
shared_libs: [
"compos_aidl_interface-ndk_platform",
"libbase",
+ "libbinder_rpc_unstable",
"libbinder_ndk",
"libcrypto",
"libfsverity",
diff --git a/compos/compos_key_cmd/compos_key_cmd.cpp b/compos/compos_key_cmd/compos_key_cmd.cpp
index 3fe843a..bee9de1 100644
--- a/compos/compos_key_cmd/compos_key_cmd.cpp
+++ b/compos/compos_key_cmd/compos_key_cmd.cpp
@@ -35,6 +35,11 @@
#include "compos_signature.pb.h"
+// From frameworks/native/libs/binder/rust/src/binder_rpc_unstable.hpp
+extern "C" {
+AIBinder* RpcClient(unsigned int cid, unsigned int port);
+}
+
using namespace std::literals;
using aidl::com::android::compos::CompOsKeyData;
@@ -45,6 +50,8 @@
using android::base::unique_fd;
using compos::proto::Signature;
+const unsigned int kRpcPort = 3142;
+
static bool writeBytesToFile(const std::vector<uint8_t>& bytes, const std::string& path) {
std::string str(bytes.begin(), bytes.end());
return android::base::WriteStringToFile(str, path);
@@ -58,6 +65,12 @@
return std::vector<uint8_t>(str.begin(), str.end());
}
+static std::shared_ptr<ICompOsKeyService> getService(int cid) {
+ ndk::SpAIBinder binder(cid == 0 ? AServiceManager_getService("android.system.composkeyservice")
+ : RpcClient(cid, kRpcPort));
+ return ICompOsKeyService::fromBinder(binder);
+}
+
static Result<std::vector<uint8_t>> extractRsaPublicKey(
const std::vector<uint8_t>& der_certificate) {
auto data = der_certificate.data();
@@ -89,9 +102,9 @@
return result;
}
-static Result<void> generate(const std::string& blob_file, const std::string& public_key_file) {
- ndk::SpAIBinder binder(AServiceManager_getService("android.system.composkeyservice"));
- auto service = ICompOsKeyService::fromBinder(binder);
+static Result<void> generate(int cid, const std::string& blob_file,
+ const std::string& public_key_file) {
+ auto service = getService(cid);
if (!service) {
return Error() << "No service";
}
@@ -117,9 +130,9 @@
return {};
}
-static Result<bool> verify(const std::string& blob_file, const std::string& public_key_file) {
- ndk::SpAIBinder binder(AServiceManager_getService("android.system.composkeyservice"));
- auto service = ICompOsKeyService::fromBinder(binder);
+static Result<bool> verify(int cid, const std::string& blob_file,
+ const std::string& public_key_file) {
+ auto service = getService(cid);
if (!service) {
return Error() << "No service";
}
@@ -210,9 +223,9 @@
return {};
}
-static Result<void> sign(const std::string& blob_file, const std::vector<std::string>& files) {
- ndk::SpAIBinder binder(AServiceManager_getService("android.system.composkeyservice"));
- auto service = ICompOsKeyService::fromBinder(binder);
+static Result<void> sign(int cid, const std::string& blob_file,
+ const std::vector<std::string>& files) {
+ auto service = getService(cid);
if (!service) {
return Error() << "No service";
}
@@ -235,15 +248,26 @@
// Restrict access to our outputs to the current user.
umask(077);
- if (argc == 4 && argv[1] == "--generate"sv) {
- auto result = generate(argv[2], argv[3]);
+ int cid = 0;
+ if (argc >= 3 && argv[1] == "--cid"sv) {
+ cid = atoi(argv[2]);
+ if (cid == 0) {
+ std::cerr << "Invalid cid\n";
+ return 1;
+ }
+ argc -= 2;
+ argv += 2;
+ }
+
+ if (argc == 4 && argv[1] == "generate"sv) {
+ auto result = generate(cid, argv[2], argv[3]);
if (result.ok()) {
return 0;
} else {
std::cerr << result.error() << '\n';
}
- } else if (argc == 4 && argv[1] == "--verify"sv) {
- auto result = verify(argv[2], argv[3]);
+ } else if (argc == 4 && argv[1] == "verify"sv) {
+ auto result = verify(cid, argv[2], argv[3]);
if (result.ok()) {
if (result.value()) {
std::cerr << "Key files are valid.\n";
@@ -254,9 +278,9 @@
} else {
std::cerr << result.error() << '\n';
}
- } else if (argc >= 4 && argv[1] == "--sign"sv) {
+ } else if (argc >= 4 && argv[1] == "sign"sv) {
const std::vector<std::string> files{&argv[3], &argv[argc]};
- auto result = sign(argv[2], files);
+ auto result = sign(cid, argv[2], files);
if (result.ok()) {
std::cerr << "All signatures generated.\n";
return 0;
@@ -264,14 +288,15 @@
std::cerr << result.error() << '\n';
}
} else {
- std::cerr << "Usage: \n"
- << " --generate <blob file> <public key file> Generate new key pair and "
+ std::cerr << "Usage: compos_key_cmd [--cid <cid>] generate|verify|sign\n"
+ << " generate <blob file> <public key file> Generate new key pair and "
"write\n"
<< " the private key blob and public key to the specified files.\n "
- << " --verify <blob file> <public key file> Verify that the content of the\n"
+ << " verify <blob file> <public key file> Verify that the content of the\n"
<< " specified private key blob and public key files are valid.\n "
- << " --sign <blob file> <files to be signed> Generate signatures for one or\n"
- << " more files using the supplied private key blob.\n";
+ << " sign <blob file> <files to be signed> Generate signatures for one or\n"
+ << " more files using the supplied private key blob.\n"
+ << "Specify --cid to connect to a VM rather than the host\n";
}
return 1;
}