Loading keymaster/4.0/support/Keymaster.cpp +102 −9 Original line number Diff line number Diff line Loading @@ -16,24 +16,73 @@ #include <keymasterV4_0/Keymaster.h> #include <iomanip> #include <android-base/logging.h> #include <android/hidl/manager/1.0/IServiceManager.h> #include <keymasterV4_0/Keymaster3.h> #include <keymasterV4_0/Keymaster4.h> #include <keymasterV4_0/key_param_output.h> #include <keymasterV4_0/keymaster_utils.h> namespace android { namespace hardware { template <class T> std::ostream& operator<<(std::ostream& os, const hidl_vec<T>& vec) { os << "{ "; if (vec.size()) { for (size_t i = 0; i < vec.size() - 1; ++i) os << vec[i] << ", "; os << vec[vec.size() - 1]; } os << " }"; return os; } std::ostream& operator<<(std::ostream& os, const hidl_vec<uint8_t>& vec) { std::ios_base::fmtflags flags(os.flags()); os << std::setw(2) << std::setfill('0') << std::hex; for (uint8_t c : vec) os << static_cast<int>(c); os.flags(flags); return os; } template <size_t N> std::ostream& operator<<(std::ostream& os, const hidl_array<uint8_t, N>& vec) { std::ios_base::fmtflags flags(os.flags()); os << std::setw(2) << std::setfill('0') << std::hex; for (size_t i = 0; i < N; ++i) os << static_cast<int>(vec[i]); os.flags(flags); return os; } namespace keymaster { namespace V4_0 { std::ostream& operator<<(std::ostream& os, const HmacSharingParameters& params) { // Note that by design, although seed and nonce are used to compute a secret, they are // not secrets and it's just fine to log them. os << "(seed: " << params.seed << ", nonce: " << params.nonce << ')'; return os; } namespace support { using ::android::sp; using ::android::hidl::manager::V1_0::IServiceManager; std::ostream& operator<<(std::ostream& os, const Keymaster& keymaster) { auto& version = keymaster.halVersion(); os << version.keymasterName << " from " << version.authorName << " SecurityLevel: " << toString(version.securityLevel) << " HAL: " << keymaster.descriptor() << "/" << keymaster.instanceName(); return os; } template <typename Wrapper> std::vector<std::unique_ptr<Keymaster>> enumerateDevices( const sp<IServiceManager>& serviceManager) { std::vector<std::unique_ptr<Keymaster>> result; Keymaster::KeymasterSet result; bool foundDefault = false; auto& descriptor = Wrapper::WrappedIKeymasterDevice::descriptor; Loading @@ -57,7 +106,7 @@ std::vector<std::unique_ptr<Keymaster>> enumerateDevices( return result; } std::vector<std::unique_ptr<Keymaster>> Keymaster::enumerateAvailableDevices() { Keymaster::KeymasterSet Keymaster::enumerateAvailableDevices() { auto serviceManager = IServiceManager::getService(); CHECK(serviceManager) << "Could not retrieve ServiceManager"; Loading @@ -73,18 +122,62 @@ std::vector<std::unique_ptr<Keymaster>> Keymaster::enumerateAvailableDevices() { size_t i = 1; LOG(INFO) << "List of Keymaster HALs found:"; for (auto& hal : result) { auto& version = hal->halVersion(); LOG(INFO) << "Keymaster HAL #" << i << ": " << version.keymasterName << " from " << version.authorName << " SecurityLevel: " << toString(version.securityLevel) << " HAL : " << hal->descriptor() << " instance " << hal->instanceName(); } for (auto& hal : result) LOG(INFO) << "Keymaster HAL #" << i++ << ": " << *hal; return result; } static hidl_vec<HmacSharingParameters> getHmacParameters( const Keymaster::KeymasterSet& keymasters) { std::vector<HmacSharingParameters> params_vec; params_vec.reserve(keymasters.size()); for (auto& keymaster : keymasters) { if (keymaster->halVersion().majorVersion < 4) continue; auto rc = keymaster->getHmacSharingParameters([&](auto error, auto& params) { CHECK(error == ErrorCode::OK) << "Failed to get HMAC parameters from " << *keymaster << " error " << error; params_vec.push_back(params); }); CHECK(rc.isOk()) << "Failed to communicate with " << *keymaster << " error: " << rc.description(); } std::sort(params_vec.begin(), params_vec.end()); return params_vec; } static void computeHmac(const Keymaster::KeymasterSet& keymasters, const hidl_vec<HmacSharingParameters>& params) { if (!params.size()) return; hidl_vec<uint8_t> sharingCheck; bool firstKeymaster = true; LOG(DEBUG) << "Computing HMAC with params " << params; for (auto& keymaster : keymasters) { if (keymaster->halVersion().majorVersion < 4) continue; LOG(DEBUG) << "Computing HMAC for " << *keymaster; auto rc = keymaster->computeSharedHmac(params, [&](auto error, auto& curSharingCheck) { CHECK(error == ErrorCode::OK) << "Failed to get HMAC parameters from " << *keymaster << " error " << error; if (firstKeymaster) { sharingCheck = curSharingCheck; firstKeymaster = false; } // TODO: Validate that curSharingCheck == sharingCheck. b/77588764 // CHECK(curSharingCheck == sharingCheck) << "HMAC computation failed for " << // *keymaster; }); CHECK(rc.isOk()) << "Failed to communicate with " << *keymaster << " error: " << rc.description(); } } void Keymaster::performHmacKeyAgreement(const KeymasterSet& keymasters) { computeHmac(keymasters, getHmacParameters(keymasters)); } } // namespace support } // namespace V4_0 } // namespace keymaster } // namespace hardware }; // namespace android } // namespace android keymaster/4.0/support/include/keymasterV4_0/Keymaster.h +18 −4 Original line number Diff line number Diff line Loading @@ -37,6 +37,8 @@ namespace support { */ class Keymaster : public IKeymasterDevice { public: using KeymasterSet = std::vector<std::unique_ptr<Keymaster>>; Keymaster(const hidl_string& descriptor, const hidl_string& instanceName) : descriptor_(descriptor), instanceName_(instanceName) {} virtual ~Keymaster() {} Loading @@ -55,21 +57,33 @@ class Keymaster : public IKeymasterDevice { } }; virtual const VersionResult& halVersion() = 0; const hidl_string& descriptor() { return descriptor_; } const hidl_string& instanceName() { return instanceName_; } virtual const VersionResult& halVersion() const = 0; const hidl_string& descriptor() const { return descriptor_; } const hidl_string& instanceName() const { return instanceName_; } /** * Returns all available Keymaster3 and Keymaster4 instances, in order of most secure to least * secure (as defined by VersionResult::operator<). */ static std::vector<std::unique_ptr<Keymaster>> enumerateAvailableDevices(); static KeymasterSet enumerateAvailableDevices(); /** * Ask provided Keymaster instances to compute a shared HMAC key using * getHmacSharingParameters() and computeSharedHmac(). This computation is idempotent as long * as the same set of Keymaster instances is used each time (and if all of the instances work * correctly). It must be performed once per boot, but should do no harm to be repeated. * * If key agreement fails, this method will crash the process (with CHECK). */ static void performHmacKeyAgreement(const KeymasterSet& keymasters); private: hidl_string descriptor_; hidl_string instanceName_; }; std::ostream& operator<<(std::ostream& os, const Keymaster& keymaster); } // namespace support } // namespace V4_0 } // namespace keymaster Loading keymaster/4.0/support/include/keymasterV4_0/Keymaster3.h +2 −2 Original line number Diff line number Diff line Loading @@ -45,8 +45,8 @@ class Keymaster3 : public Keymaster { km3_dev_(km3_dev), haveVersion_(false) {} const VersionResult& halVersion() override { getVersionIfNeeded(); const VersionResult& halVersion() const override { const_cast<Keymaster3*>(this)->getVersionIfNeeded(); return version_; } Loading keymaster/4.0/support/include/keymasterV4_0/Keymaster4.h +2 −2 Original line number Diff line number Diff line Loading @@ -37,8 +37,8 @@ class Keymaster4 : public Keymaster { haveVersion_(false), dev_(km4_dev) {} const VersionResult& halVersion() override { getVersionIfNeeded(); const VersionResult& halVersion() const override { const_cast<Keymaster4*>(this)->getVersionIfNeeded(); return version_; } Loading keymaster/4.0/support/include/keymasterV4_0/keymaster_utils.h +8 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,14 @@ namespace android { namespace hardware { namespace keymaster { namespace V4_0 { /** * Define a lexicographical ordering on HmacSharingParameters. The parameters to * IKeymasterDevice::computeSharedHmac are required to be delivered in the order specified by this * comparison operator. */ bool operator<(const HmacSharingParameters& a, const HmacSharingParameters& b); namespace support { inline static hidl_vec<uint8_t> blob2hidlVec(const uint8_t* data, const size_t length, Loading Loading
keymaster/4.0/support/Keymaster.cpp +102 −9 Original line number Diff line number Diff line Loading @@ -16,24 +16,73 @@ #include <keymasterV4_0/Keymaster.h> #include <iomanip> #include <android-base/logging.h> #include <android/hidl/manager/1.0/IServiceManager.h> #include <keymasterV4_0/Keymaster3.h> #include <keymasterV4_0/Keymaster4.h> #include <keymasterV4_0/key_param_output.h> #include <keymasterV4_0/keymaster_utils.h> namespace android { namespace hardware { template <class T> std::ostream& operator<<(std::ostream& os, const hidl_vec<T>& vec) { os << "{ "; if (vec.size()) { for (size_t i = 0; i < vec.size() - 1; ++i) os << vec[i] << ", "; os << vec[vec.size() - 1]; } os << " }"; return os; } std::ostream& operator<<(std::ostream& os, const hidl_vec<uint8_t>& vec) { std::ios_base::fmtflags flags(os.flags()); os << std::setw(2) << std::setfill('0') << std::hex; for (uint8_t c : vec) os << static_cast<int>(c); os.flags(flags); return os; } template <size_t N> std::ostream& operator<<(std::ostream& os, const hidl_array<uint8_t, N>& vec) { std::ios_base::fmtflags flags(os.flags()); os << std::setw(2) << std::setfill('0') << std::hex; for (size_t i = 0; i < N; ++i) os << static_cast<int>(vec[i]); os.flags(flags); return os; } namespace keymaster { namespace V4_0 { std::ostream& operator<<(std::ostream& os, const HmacSharingParameters& params) { // Note that by design, although seed and nonce are used to compute a secret, they are // not secrets and it's just fine to log them. os << "(seed: " << params.seed << ", nonce: " << params.nonce << ')'; return os; } namespace support { using ::android::sp; using ::android::hidl::manager::V1_0::IServiceManager; std::ostream& operator<<(std::ostream& os, const Keymaster& keymaster) { auto& version = keymaster.halVersion(); os << version.keymasterName << " from " << version.authorName << " SecurityLevel: " << toString(version.securityLevel) << " HAL: " << keymaster.descriptor() << "/" << keymaster.instanceName(); return os; } template <typename Wrapper> std::vector<std::unique_ptr<Keymaster>> enumerateDevices( const sp<IServiceManager>& serviceManager) { std::vector<std::unique_ptr<Keymaster>> result; Keymaster::KeymasterSet result; bool foundDefault = false; auto& descriptor = Wrapper::WrappedIKeymasterDevice::descriptor; Loading @@ -57,7 +106,7 @@ std::vector<std::unique_ptr<Keymaster>> enumerateDevices( return result; } std::vector<std::unique_ptr<Keymaster>> Keymaster::enumerateAvailableDevices() { Keymaster::KeymasterSet Keymaster::enumerateAvailableDevices() { auto serviceManager = IServiceManager::getService(); CHECK(serviceManager) << "Could not retrieve ServiceManager"; Loading @@ -73,18 +122,62 @@ std::vector<std::unique_ptr<Keymaster>> Keymaster::enumerateAvailableDevices() { size_t i = 1; LOG(INFO) << "List of Keymaster HALs found:"; for (auto& hal : result) { auto& version = hal->halVersion(); LOG(INFO) << "Keymaster HAL #" << i << ": " << version.keymasterName << " from " << version.authorName << " SecurityLevel: " << toString(version.securityLevel) << " HAL : " << hal->descriptor() << " instance " << hal->instanceName(); } for (auto& hal : result) LOG(INFO) << "Keymaster HAL #" << i++ << ": " << *hal; return result; } static hidl_vec<HmacSharingParameters> getHmacParameters( const Keymaster::KeymasterSet& keymasters) { std::vector<HmacSharingParameters> params_vec; params_vec.reserve(keymasters.size()); for (auto& keymaster : keymasters) { if (keymaster->halVersion().majorVersion < 4) continue; auto rc = keymaster->getHmacSharingParameters([&](auto error, auto& params) { CHECK(error == ErrorCode::OK) << "Failed to get HMAC parameters from " << *keymaster << " error " << error; params_vec.push_back(params); }); CHECK(rc.isOk()) << "Failed to communicate with " << *keymaster << " error: " << rc.description(); } std::sort(params_vec.begin(), params_vec.end()); return params_vec; } static void computeHmac(const Keymaster::KeymasterSet& keymasters, const hidl_vec<HmacSharingParameters>& params) { if (!params.size()) return; hidl_vec<uint8_t> sharingCheck; bool firstKeymaster = true; LOG(DEBUG) << "Computing HMAC with params " << params; for (auto& keymaster : keymasters) { if (keymaster->halVersion().majorVersion < 4) continue; LOG(DEBUG) << "Computing HMAC for " << *keymaster; auto rc = keymaster->computeSharedHmac(params, [&](auto error, auto& curSharingCheck) { CHECK(error == ErrorCode::OK) << "Failed to get HMAC parameters from " << *keymaster << " error " << error; if (firstKeymaster) { sharingCheck = curSharingCheck; firstKeymaster = false; } // TODO: Validate that curSharingCheck == sharingCheck. b/77588764 // CHECK(curSharingCheck == sharingCheck) << "HMAC computation failed for " << // *keymaster; }); CHECK(rc.isOk()) << "Failed to communicate with " << *keymaster << " error: " << rc.description(); } } void Keymaster::performHmacKeyAgreement(const KeymasterSet& keymasters) { computeHmac(keymasters, getHmacParameters(keymasters)); } } // namespace support } // namespace V4_0 } // namespace keymaster } // namespace hardware }; // namespace android } // namespace android
keymaster/4.0/support/include/keymasterV4_0/Keymaster.h +18 −4 Original line number Diff line number Diff line Loading @@ -37,6 +37,8 @@ namespace support { */ class Keymaster : public IKeymasterDevice { public: using KeymasterSet = std::vector<std::unique_ptr<Keymaster>>; Keymaster(const hidl_string& descriptor, const hidl_string& instanceName) : descriptor_(descriptor), instanceName_(instanceName) {} virtual ~Keymaster() {} Loading @@ -55,21 +57,33 @@ class Keymaster : public IKeymasterDevice { } }; virtual const VersionResult& halVersion() = 0; const hidl_string& descriptor() { return descriptor_; } const hidl_string& instanceName() { return instanceName_; } virtual const VersionResult& halVersion() const = 0; const hidl_string& descriptor() const { return descriptor_; } const hidl_string& instanceName() const { return instanceName_; } /** * Returns all available Keymaster3 and Keymaster4 instances, in order of most secure to least * secure (as defined by VersionResult::operator<). */ static std::vector<std::unique_ptr<Keymaster>> enumerateAvailableDevices(); static KeymasterSet enumerateAvailableDevices(); /** * Ask provided Keymaster instances to compute a shared HMAC key using * getHmacSharingParameters() and computeSharedHmac(). This computation is idempotent as long * as the same set of Keymaster instances is used each time (and if all of the instances work * correctly). It must be performed once per boot, but should do no harm to be repeated. * * If key agreement fails, this method will crash the process (with CHECK). */ static void performHmacKeyAgreement(const KeymasterSet& keymasters); private: hidl_string descriptor_; hidl_string instanceName_; }; std::ostream& operator<<(std::ostream& os, const Keymaster& keymaster); } // namespace support } // namespace V4_0 } // namespace keymaster Loading
keymaster/4.0/support/include/keymasterV4_0/Keymaster3.h +2 −2 Original line number Diff line number Diff line Loading @@ -45,8 +45,8 @@ class Keymaster3 : public Keymaster { km3_dev_(km3_dev), haveVersion_(false) {} const VersionResult& halVersion() override { getVersionIfNeeded(); const VersionResult& halVersion() const override { const_cast<Keymaster3*>(this)->getVersionIfNeeded(); return version_; } Loading
keymaster/4.0/support/include/keymasterV4_0/Keymaster4.h +2 −2 Original line number Diff line number Diff line Loading @@ -37,8 +37,8 @@ class Keymaster4 : public Keymaster { haveVersion_(false), dev_(km4_dev) {} const VersionResult& halVersion() override { getVersionIfNeeded(); const VersionResult& halVersion() const override { const_cast<Keymaster4*>(this)->getVersionIfNeeded(); return version_; } Loading
keymaster/4.0/support/include/keymasterV4_0/keymaster_utils.h +8 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,14 @@ namespace android { namespace hardware { namespace keymaster { namespace V4_0 { /** * Define a lexicographical ordering on HmacSharingParameters. The parameters to * IKeymasterDevice::computeSharedHmac are required to be delivered in the order specified by this * comparison operator. */ bool operator<(const HmacSharingParameters& a, const HmacSharingParameters& b); namespace support { inline static hidl_vec<uint8_t> blob2hidlVec(const uint8_t* data, const size_t length, Loading