Add a utility to JSON-format a CSR with build info

We need both the build fingerprint as well as the CSR when uploading
data to the APFE provisioning server. Add a utility function to format
the output as a JSON blob so that it may be easily collected in the
factory in a serialized data format, then later uploaded.

Test: libkeymint_remote_prov_support_test
Test: VtsAidlKeyMintTargetTest
Test: VtsHalRemotelyProvisionedComponentTargetTest
Bug: 191301285
Change-Id: I751c5461876d83251869539f1a395ba13cb5cf84
This commit is contained in:
Seth Moore
2021-06-25 14:20:15 -07:00
parent 0ab5ef3ff7
commit f4c8ff9bef
5 changed files with 101 additions and 38 deletions

View File

@@ -23,16 +23,11 @@ package {
default_applicable_licenses: ["hardware_interfaces_license"], default_applicable_licenses: ["hardware_interfaces_license"],
} }
cc_test { cc_defaults {
name: "VtsAidlKeyMintTargetTest", name: "keymint_vts_defaults",
defaults: [ defaults: [
"VtsHalTargetTestDefaults",
"use_libaidlvintf_gtest_helper_static", "use_libaidlvintf_gtest_helper_static",
], "VtsHalTargetTestDefaults",
srcs: [
"AttestKeyTest.cpp",
"DeviceUniqueAttestationTest.cpp",
"KeyMintTest.cpp",
], ],
shared_libs: [ shared_libs: [
"libbinder_ndk", "libbinder_ndk",
@@ -43,9 +38,24 @@ cc_test {
"android.hardware.security.secureclock-V1-ndk_platform", "android.hardware.security.secureclock-V1-ndk_platform",
"libcppbor_external", "libcppbor_external",
"libcppcose_rkp", "libcppcose_rkp",
"libjsoncpp",
"libkeymint", "libkeymint",
"libkeymint_remote_prov_support", "libkeymint_remote_prov_support",
"libkeymint_support", "libkeymint_support",
],
}
cc_test {
name: "VtsAidlKeyMintTargetTest",
defaults: [
"keymint_vts_defaults",
],
srcs: [
"AttestKeyTest.cpp",
"DeviceUniqueAttestationTest.cpp",
"KeyMintTest.cpp",
],
static_libs: [
"libkeymint_vts_test_utils", "libkeymint_vts_test_utils",
], ],
test_suites: [ test_suites: [
@@ -57,8 +67,7 @@ cc_test {
cc_test_library { cc_test_library {
name: "libkeymint_vts_test_utils", name: "libkeymint_vts_test_utils",
defaults: [ defaults: [
"VtsHalTargetTestDefaults", "keymint_vts_defaults",
"use_libaidlvintf_gtest_helper_static",
], ],
srcs: [ srcs: [
"KeyMintAidlTestBase.cpp", "KeyMintAidlTestBase.cpp",
@@ -66,45 +75,22 @@ cc_test_library {
export_include_dirs: [ export_include_dirs: [
".", ".",
], ],
shared_libs: [
"libbinder_ndk",
"libcrypto",
],
static_libs: [ static_libs: [
"android.hardware.security.keymint-V1-ndk_platform",
"android.hardware.security.secureclock-V1-ndk_platform",
"libcppbor_external",
"libcppcose_rkp",
"libgmock_ndk", "libgmock_ndk",
"libkeymint",
"libkeymint_remote_prov_support",
"libkeymint_support",
], ],
} }
cc_test { cc_test {
name: "VtsHalRemotelyProvisionedComponentTargetTest", name: "VtsHalRemotelyProvisionedComponentTargetTest",
defaults: [ defaults: [
"VtsHalTargetTestDefaults", "keymint_vts_defaults",
"use_libaidlvintf_gtest_helper_static",
], ],
srcs: [ srcs: [
"VtsRemotelyProvisionedComponentTests.cpp", "VtsRemotelyProvisionedComponentTests.cpp",
], ],
shared_libs: [
"libbinder_ndk",
"libcrypto",
],
static_libs: [ static_libs: [
"android.hardware.security.keymint-V1-ndk_platform",
"android.hardware.security.secureclock-V1-ndk_platform",
"libcppbor_external",
"libcppcose_rkp",
"libgmock_ndk", "libgmock_ndk",
"libkeymaster_portable", "libkeymaster_portable",
"libkeymint",
"libkeymint_support",
"libkeymint_remote_prov_support",
"libkeymint_vts_test_utils", "libkeymint_vts_test_utils",
"libpuresoftkeymasterdevice", "libpuresoftkeymasterdevice",
], ],

View File

@@ -57,9 +57,11 @@ cc_library {
"include", "include",
], ],
shared_libs: [ shared_libs: [
"libbase",
"libcppbor_external", "libcppbor_external",
"libcppcose_rkp", "libcppcose_rkp",
"libcrypto", "libcrypto",
"libjsoncpp",
], ],
} }
@@ -71,9 +73,11 @@ cc_test {
"libgtest_main", "libgtest_main",
], ],
shared_libs: [ shared_libs: [
"libbase",
"libcppbor_external", "libcppbor_external",
"libcppcose_rkp", "libcppcose_rkp",
"libcrypto", "libcrypto",
"libjsoncpp",
"libkeymaster_portable", "libkeymaster_portable",
"libkeymint_remote_prov_support", "libkeymint_remote_prov_support",
], ],

View File

@@ -87,4 +87,26 @@ struct BccEntryData {
*/ */
ErrMsgOr<std::vector<BccEntryData>> validateBcc(const cppbor::Array* bcc); ErrMsgOr<std::vector<BccEntryData>> validateBcc(const cppbor::Array* bcc);
struct JsonOutput {
static JsonOutput Ok(std::string json) { return {std::move(json), ""}; }
static JsonOutput Error(std::string error) { return {"", std::move(error)}; }
std::string output;
std::string error; // if non-empty, this describes what went wrong
};
/**
* Take a given certificate request and output a JSON blob containing both the
* build fingerprint and certificate request. This data may be serialized, then
* later uploaded to the remote provisioning service. The input csr is not
* validated, only encoded.
*
* Output format:
* {
* "build_fingerprint": <string>
* "csr": <base64 CBOR CSR>
* }
*/
JsonOutput jsonEncodeCsrWithBuild(const cppbor::Array& csr);
} // namespace aidl::android::hardware::security::keymint::remote_prov } // namespace aidl::android::hardware::security::keymint::remote_prov

View File

@@ -14,13 +14,15 @@
* limitations under the License. * limitations under the License.
*/ */
#include <iterator>
#include <tuple> #include <tuple>
#include <remote_prov/remote_prov_utils.h> #include <android-base/properties.h>
#include <openssl/rand.h>
#include <cppbor.h> #include <cppbor.h>
#include <json/json.h>
#include <openssl/base64.h>
#include <openssl/rand.h>
#include <remote_prov/remote_prov_utils.h>
namespace aidl::android::hardware::security::keymint::remote_prov { namespace aidl::android::hardware::security::keymint::remote_prov {
@@ -180,4 +182,36 @@ ErrMsgOr<std::vector<BccEntryData>> validateBcc(const cppbor::Array* bcc) {
return result; return result;
} }
JsonOutput jsonEncodeCsrWithBuild(const cppbor::Array& csr) {
const std::string kFingerprintProp = "ro.build.fingerprint";
if (!::android::base::WaitForPropertyCreation(kFingerprintProp)) {
return JsonOutput::Error("Unable to read build fingerprint");
}
bytevec csrCbor = csr.encode();
size_t base64Length;
int rc = EVP_EncodedLength(&base64Length, csrCbor.size());
if (!rc) {
return JsonOutput::Error("Error getting base64 length. Size overflow?");
}
std::vector<char> base64(base64Length);
rc = EVP_EncodeBlock(reinterpret_cast<uint8_t*>(base64.data()), csrCbor.data(), csrCbor.size());
++rc; // Account for NUL, which BoringSSL does not for some reason.
if (rc != base64Length) {
return JsonOutput::Error("Error writing base64. Expected " + std::to_string(base64Length) +
" bytes to be written, but " + std::to_string(rc) +
" bytes were actually written.");
}
Json::Value json(Json::objectValue);
json["build_fingerprint"] = ::android::base::GetProperty(kFingerprintProp, /*default=*/"");
json["csr"] = base64.data(); // Boring writes a NUL-terminated c-string
Json::StreamWriterBuilder factory;
factory["indentation"] = ""; // disable pretty formatting
return JsonOutput::Ok(Json::writeString(factory, json));
}
} // namespace aidl::android::hardware::security::keymint::remote_prov } // namespace aidl::android::hardware::security::keymint::remote_prov

View File

@@ -14,6 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
#include <android-base/properties.h>
#include <cppbor_parse.h> #include <cppbor_parse.h>
#include <gmock/gmock.h> #include <gmock/gmock.h>
#include <gtest/gtest.h> #include <gtest/gtest.h>
@@ -23,6 +24,7 @@
#include <openssl/curve25519.h> #include <openssl/curve25519.h>
#include <remote_prov/remote_prov_utils.h> #include <remote_prov/remote_prov_utils.h>
#include <cstdint> #include <cstdint>
#include "cppbor.h"
#include "keymaster/cppcose/cppcose.h" #include "keymaster/cppcose/cppcose.h"
namespace aidl::android::hardware::security::keymint::remote_prov { namespace aidl::android::hardware::security::keymint::remote_prov {
@@ -80,5 +82,20 @@ TEST(RemoteProvUtilsTest, GetProdEekChain) {
EXPECT_THAT(eekPub, ElementsAreArray(geek->getBstrValue(CoseKey::PUBKEY_X).value_or(empty))); EXPECT_THAT(eekPub, ElementsAreArray(geek->getBstrValue(CoseKey::PUBKEY_X).value_or(empty)));
} }
TEST(RemoteProvUtilsTest, JsonEncodeCsr) {
cppbor::Array array;
array.add(1);
auto [json, error] = jsonEncodeCsrWithBuild(array);
ASSERT_TRUE(error.empty()) << error;
std::string expected = R"({"build_fingerprint":")" +
::android::base::GetProperty("ro.build.fingerprint", /*default=*/"") +
R"(","csr":"gQE="})";
ASSERT_EQ(json, expected);
}
} // namespace } // namespace
} // namespace aidl::android::hardware::security::keymint::remote_prov } // namespace aidl::android::hardware::security::keymint::remote_prov