Merge changes from topic "rkp-factory-tool-redux" into sc-dev
* changes:
Generate random challenge in RKP factory tool
Add prod GEEK to rkp_factory_extraction_tool
Remove duplicate generateEekChain routine
diff --git a/provisioner/Android.bp b/provisioner/Android.bp
index ea84063..86f0f12 100644
--- a/provisioner/Android.bp
+++ b/provisioner/Android.bp
@@ -53,8 +53,9 @@
"libcppbor_external",
"libcppcose_rkp",
"libcrypto",
+ "libgflags",
"liblog",
+ "libkeymint_remote_prov_support",
"libvintf",
],
- //export_include_dirs: ["include"],
}
diff --git a/provisioner/rkp_factory_extraction_tool.cpp b/provisioner/rkp_factory_extraction_tool.cpp
index d4842b1..a6c7d72 100644
--- a/provisioner/rkp_factory_extraction_tool.cpp
+++ b/provisioner/rkp_factory_extraction_tool.cpp
@@ -20,8 +20,11 @@
#include <aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.h>
#include <android/binder_manager.h>
#include <cppbor.h>
+#include <gflags/gflags.h>
#include <keymaster/cppcose/cppcose.h>
#include <log/log.h>
+#include <remote_prov/remote_prov_utils.h>
+#include <sys/random.h>
#include <vintf/VintfObject.h>
using std::set;
@@ -32,6 +35,8 @@
using aidl::android::hardware::security::keymint::IRemotelyProvisionedComponent;
using aidl::android::hardware::security::keymint::MacedPublicKey;
using aidl::android::hardware::security::keymint::ProtectedData;
+using aidl::android::hardware::security::keymint::remote_prov::generateEekChain;
+using aidl::android::hardware::security::keymint::remote_prov::getProdEekChain;
using android::vintf::HalManifest;
using android::vintf::VintfObject;
@@ -39,66 +44,36 @@
using namespace cppbor;
using namespace cppcose;
+DEFINE_bool(test_mode, false, "If enabled, a fake EEK key/cert are used.");
+
namespace {
const string kPackage = "android.hardware.security.keymint";
const string kInterface = "IRemotelyProvisionedComponent";
const string kFormattedName = kPackage + "." + kInterface + "/";
-ErrMsgOr<vector<uint8_t>> generateEekChain(size_t length, const vector<uint8_t>& eekId) {
- auto eekChain = cppbor::Array();
+constexpr size_t kChallengeSize = 16;
- vector<uint8_t> prevPrivKey;
- for (size_t i = 0; i < length - 1; ++i) {
- vector<uint8_t> pubKey(ED25519_PUBLIC_KEY_LEN);
- vector<uint8_t> privKey(ED25519_PRIVATE_KEY_LEN);
+std::vector<uint8_t> generateChallenge() {
+ std::vector<uint8_t> challenge(kChallengeSize);
- ED25519_keypair(pubKey.data(), privKey.data());
-
- // The first signing key is self-signed.
- if (prevPrivKey.empty()) prevPrivKey = privKey;
-
- auto coseSign1 = constructCoseSign1(prevPrivKey,
- cppbor::Map() /* payload CoseKey */
- .add(CoseKey::KEY_TYPE, OCTET_KEY_PAIR)
- .add(CoseKey::ALGORITHM, EDDSA)
- .add(CoseKey::CURVE, ED25519)
- .add(CoseKey::PUBKEY_X, pubKey)
- .canonicalize()
- .encode(),
- {} /* AAD */);
- if (!coseSign1) return coseSign1.moveMessage();
- eekChain.add(coseSign1.moveValue());
-
- prevPrivKey = privKey;
+ ssize_t bytesRemaining = static_cast<ssize_t>(challenge.size());
+ uint8_t* writePtr = challenge.data();
+ while (bytesRemaining > 0) {
+ int bytesRead = getrandom(writePtr, bytesRemaining, /*flags=*/0);
+ if (bytesRead < 0) {
+ LOG_FATAL_IF(errno != EINTR, "%d - %s", errno, strerror(errno));
+ }
+ bytesRemaining -= bytesRead;
+ writePtr += bytesRead;
}
- vector<uint8_t> pubKey(X25519_PUBLIC_VALUE_LEN);
- vector<uint8_t> privKey(X25519_PRIVATE_KEY_LEN);
- X25519_keypair(pubKey.data(), privKey.data());
-
- auto coseSign1 = constructCoseSign1(prevPrivKey,
- cppbor::Map() /* payload CoseKey */
- .add(CoseKey::KEY_TYPE, OCTET_KEY_PAIR)
- .add(CoseKey::KEY_ID, eekId)
- .add(CoseKey::ALGORITHM, ECDH_ES_HKDF_256)
- .add(CoseKey::CURVE, cppcose::X25519)
- .add(CoseKey::PUBKEY_X, pubKey)
- .canonicalize()
- .encode(),
- {} /* AAD */);
- if (!coseSign1) return coseSign1.moveMessage();
- eekChain.add(coseSign1.moveValue());
-
- return eekChain.encode();
-}
-
-std::vector<uint8_t> getChallenge() {
- return std::vector<uint8_t>(0);
+ return challenge;
}
std::vector<uint8_t> composeCertificateRequest(ProtectedData&& protectedData,
- DeviceInfo&& deviceInfo) {
+ DeviceInfo&& deviceInfo,
+ const std::vector<uint8_t>& challenge) {
Array emptyMacedKeysToSign;
emptyMacedKeysToSign
.add(std::vector<uint8_t>(0)) // empty protected headers as bstr
@@ -107,7 +82,7 @@
.add(std::vector<uint8_t>(0)); // empty tag as bstr
Array certificateRequest;
certificateRequest.add(EncodedItem(std::move(deviceInfo.deviceInfo)))
- .add(getChallenge()) // fake challenge
+ .add(challenge)
.add(EncodedItem(std::move(protectedData.protectedData)))
.add(std::move(emptyMacedKeysToSign));
return certificateRequest.encode();
@@ -118,9 +93,27 @@
return -1;
}
+std::vector<uint8_t> getEekChain() {
+ if (FLAGS_test_mode) {
+ const std::vector<uint8_t> kFakeEekId = {'f', 'a', 'k', 'e', 0};
+ auto eekOrErr = generateEekChain(3 /* chainlength */, kFakeEekId);
+ LOG_FATAL_IF(!eekOrErr, "Failed to generate test EEK somehow: %s",
+ eekOrErr.message().c_str());
+ auto [eek, ignored_pubkey, ignored_privkey] = eekOrErr.moveValue();
+ return eek;
+ }
+
+ return getProdEekChain();
+}
+
} // namespace
-int main() {
+int main(int argc, char** argv) {
+ gflags::ParseCommandLineFlags(&argc, &argv, /*remove_flags=*/true);
+
+ const std::vector<uint8_t> eek_chain = getEekChain();
+ const std::vector<uint8_t> challenge = generateChallenge();
+
std::shared_ptr<const HalManifest> manifest = VintfObject::GetDeviceHalManifest();
set<string> rkpNames = manifest->getAidlInstances(kPackage, kInterface);
for (auto name : rkpNames) {
@@ -136,29 +129,19 @@
std::vector<uint8_t> keysToSignMac;
std::vector<MacedPublicKey> emptyKeys;
- // Replace this eek chain generation with the actual production GEEK
- std::vector<uint8_t> eekId(10); // replace with real KID later (EEK fingerprint)
- auto eekOrErr = generateEekChain(3 /* chainlength */, eekId);
- if (!eekOrErr) {
- ALOGE("Failed to generate test EEK somehow: %s", eekOrErr.message().c_str());
- return errorMsg(name);
- }
-
- std::vector<uint8_t> eek = eekOrErr.moveValue();
DeviceInfo deviceInfo;
ProtectedData protectedData;
if (rkp_service) {
ALOGE("extracting bundle");
::ndk::ScopedAStatus status = rkp_service->generateCertificateRequest(
- true /* testMode */, emptyKeys, eek, getChallenge(), &deviceInfo, &protectedData,
+ FLAGS_test_mode, emptyKeys, eek_chain, challenge, &deviceInfo, &protectedData,
&keysToSignMac);
if (!status.isOk()) {
ALOGE("Bundle extraction failed. Error code: %d", status.getServiceSpecificError());
return errorMsg(name);
}
- std::cout << "\n";
- std::vector<uint8_t> certificateRequest =
- composeCertificateRequest(std::move(protectedData), std::move(deviceInfo));
+ std::vector<uint8_t> certificateRequest = composeCertificateRequest(
+ std::move(protectedData), std::move(deviceInfo), challenge);
std::copy(certificateRequest.begin(), certificateRequest.end(),
std::ostream_iterator<char>(std::cout));
}