From 23f624599f4f72b9e07a051104ccbfcaaaeda3d9 Mon Sep 17 00:00:00 2001 From: Seth Moore Date: Fri, 25 Jun 2021 14:20:15 -0700 Subject: [PATCH] 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 --- .../keymint/aidl/vts/functional/Android.bp | 54 +++++++------------ security/keymint/support/Android.bp | 4 ++ .../include/remote_prov/remote_prov_utils.h | 22 ++++++++ .../keymint/support/remote_prov_utils.cpp | 42 +++++++++++++-- .../support/remote_prov_utils_test.cpp | 17 ++++++ 5 files changed, 101 insertions(+), 38 deletions(-) diff --git a/security/keymint/aidl/vts/functional/Android.bp b/security/keymint/aidl/vts/functional/Android.bp index ff08ce626e..386029f306 100644 --- a/security/keymint/aidl/vts/functional/Android.bp +++ b/security/keymint/aidl/vts/functional/Android.bp @@ -23,16 +23,11 @@ package { default_applicable_licenses: ["hardware_interfaces_license"], } -cc_test { - name: "VtsAidlKeyMintTargetTest", +cc_defaults { + name: "keymint_vts_defaults", defaults: [ - "VtsHalTargetTestDefaults", "use_libaidlvintf_gtest_helper_static", - ], - srcs: [ - "AttestKeyTest.cpp", - "DeviceUniqueAttestationTest.cpp", - "KeyMintTest.cpp", + "VtsHalTargetTestDefaults", ], shared_libs: [ "libbinder_ndk", @@ -43,9 +38,24 @@ cc_test { "android.hardware.security.secureclock-V1-ndk_platform", "libcppbor_external", "libcppcose_rkp", + "libjsoncpp", "libkeymint", "libkeymint_remote_prov_support", "libkeymint_support", + ], +} + +cc_test { + name: "VtsAidlKeyMintTargetTest", + defaults: [ + "keymint_vts_defaults", + ], + srcs: [ + "AttestKeyTest.cpp", + "DeviceUniqueAttestationTest.cpp", + "KeyMintTest.cpp", + ], + static_libs: [ "libkeymint_vts_test_utils", ], test_suites: [ @@ -57,8 +67,7 @@ cc_test { cc_test_library { name: "libkeymint_vts_test_utils", defaults: [ - "VtsHalTargetTestDefaults", - "use_libaidlvintf_gtest_helper_static", + "keymint_vts_defaults", ], srcs: [ "KeyMintAidlTestBase.cpp", @@ -66,45 +75,22 @@ cc_test_library { export_include_dirs: [ ".", ], - shared_libs: [ - "libbinder_ndk", - "libcrypto", - ], static_libs: [ - "android.hardware.security.keymint-V1-ndk_platform", - "android.hardware.security.secureclock-V1-ndk_platform", - "libcppbor_external", - "libcppcose_rkp", "libgmock_ndk", - "libkeymint", - "libkeymint_remote_prov_support", - "libkeymint_support", ], } cc_test { name: "VtsHalRemotelyProvisionedComponentTargetTest", defaults: [ - "VtsHalTargetTestDefaults", - "use_libaidlvintf_gtest_helper_static", + "keymint_vts_defaults", ], srcs: [ "VtsRemotelyProvisionedComponentTests.cpp", ], - shared_libs: [ - "libbinder_ndk", - "libcrypto", - ], static_libs: [ - "android.hardware.security.keymint-V1-ndk_platform", - "android.hardware.security.secureclock-V1-ndk_platform", - "libcppbor_external", - "libcppcose_rkp", "libgmock_ndk", "libkeymaster_portable", - "libkeymint", - "libkeymint_support", - "libkeymint_remote_prov_support", "libkeymint_vts_test_utils", "libpuresoftkeymasterdevice", ], diff --git a/security/keymint/support/Android.bp b/security/keymint/support/Android.bp index c2dba044bf..9e218b6a3d 100644 --- a/security/keymint/support/Android.bp +++ b/security/keymint/support/Android.bp @@ -57,9 +57,11 @@ cc_library { "include", ], shared_libs: [ + "libbase", "libcppbor_external", "libcppcose_rkp", "libcrypto", + "libjsoncpp", ], } @@ -71,9 +73,11 @@ cc_test { "libgtest_main", ], shared_libs: [ + "libbase", "libcppbor_external", "libcppcose_rkp", "libcrypto", + "libjsoncpp", "libkeymaster_portable", "libkeymint_remote_prov_support", ], diff --git a/security/keymint/support/include/remote_prov/remote_prov_utils.h b/security/keymint/support/include/remote_prov/remote_prov_utils.h index b02d273fde..406b7a9b79 100644 --- a/security/keymint/support/include/remote_prov/remote_prov_utils.h +++ b/security/keymint/support/include/remote_prov/remote_prov_utils.h @@ -87,4 +87,26 @@ struct BccEntryData { */ ErrMsgOr> 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": + * "csr": + * } + */ +JsonOutput jsonEncodeCsrWithBuild(const cppbor::Array& csr); + } // namespace aidl::android::hardware::security::keymint::remote_prov diff --git a/security/keymint/support/remote_prov_utils.cpp b/security/keymint/support/remote_prov_utils.cpp index 982a1eb7b1..0cbee51044 100644 --- a/security/keymint/support/remote_prov_utils.cpp +++ b/security/keymint/support/remote_prov_utils.cpp @@ -14,13 +14,15 @@ * limitations under the License. */ +#include #include -#include - -#include - +#include #include +#include +#include +#include +#include namespace aidl::android::hardware::security::keymint::remote_prov { @@ -180,4 +182,36 @@ ErrMsgOr> validateBcc(const cppbor::Array* bcc) { 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 base64(base64Length); + rc = EVP_EncodeBlock(reinterpret_cast(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 diff --git a/security/keymint/support/remote_prov_utils_test.cpp b/security/keymint/support/remote_prov_utils_test.cpp index c360c06506..8697c5190f 100644 --- a/security/keymint/support/remote_prov_utils_test.cpp +++ b/security/keymint/support/remote_prov_utils_test.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include #include #include #include @@ -23,6 +24,7 @@ #include #include #include +#include "cppbor.h" #include "keymaster/cppcose/cppcose.h" 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))); } +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 aidl::android::hardware::security::keymint::remote_prov