Loading services/inputflinger/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ cc_library_shared { "libinputreporter", "libinputreader", "libbinder", "libcrypto", "libcutils", "libhidlbase", "libinput", Loading services/inputflinger/dispatcher/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ cc_library_static { ], shared_libs: [ "libbase", "libcrypto", "libcutils", "libinput", "libinputreporter", Loading services/inputflinger/dispatcher/InputDispatcher.cpp +51 −0 Original line number Diff line number Diff line Loading @@ -61,6 +61,8 @@ static constexpr bool DEBUG_FOCUS = false; #include <android-base/stringprintf.h> #include <binder/Binder.h> #include <log/log.h> #include <openssl/hmac.h> #include <openssl/rand.h> #include <powermanager/PowerManager.h> #include <utils/Trace.h> Loading Loading @@ -325,6 +327,55 @@ static std::unique_ptr<DispatchEntry> createDispatchEntry(const InputTarget& inp return dispatchEntry; } static std::array<uint8_t, 128> getRandomKey() { std::array<uint8_t, 128> key; if (RAND_bytes(key.data(), key.size()) != 1) { LOG_ALWAYS_FATAL("Can't generate HMAC key"); } return key; } // --- HmacKeyManager --- HmacKeyManager::HmacKeyManager() : mHmacKey(getRandomKey()) {} std::array<uint8_t, 32> HmacKeyManager::sign(const VerifiedInputEvent& event) const { size_t size; switch (event.type) { case VerifiedInputEvent::Type::KEY: { size = sizeof(VerifiedKeyEvent); break; } case VerifiedInputEvent::Type::MOTION: { size = sizeof(VerifiedMotionEvent); break; } } std::vector<uint8_t> data; const uint8_t* start = reinterpret_cast<const uint8_t*>(&event); data.assign(start, start + size); return sign(data); } std::array<uint8_t, 32> HmacKeyManager::sign(const std::vector<uint8_t>& data) const { // SHA256 always generates 32-bytes result std::array<uint8_t, 32> hash; unsigned int hashLen = 0; uint8_t* result = HMAC(EVP_sha256(), mHmacKey.data(), mHmacKey.size(), data.data(), data.size(), hash.data(), &hashLen); if (result == nullptr) { ALOGE("Could not sign the data using HMAC"); return INVALID_HMAC; } if (hashLen != hash.size()) { ALOGE("HMAC-SHA256 has unexpected length"); return INVALID_HMAC; } return hash; } // --- InputDispatcher --- InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) Loading services/inputflinger/dispatcher/InputDispatcher.h +10 −0 Original line number Diff line number Diff line Loading @@ -56,6 +56,16 @@ namespace android::inputdispatcher { class Connection; class HmacKeyManager { public: HmacKeyManager(); std::array<uint8_t, 32> sign(const VerifiedInputEvent& event) const; private: std::array<uint8_t, 32> sign(const std::vector<uint8_t>& data) const; const std::array<uint8_t, 128> mHmacKey; }; /* Dispatches events to input targets. Some functions of the input dispatcher, such as * identifying input targets, are controlled by a separate policy object. * Loading services/inputflinger/tests/InputDispatcher_test.cpp +75 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,18 @@ struct PointF { float y; }; /** * Return a DOWN key event with KEYCODE_A. */ static KeyEvent getTestKeyEvent() { KeyEvent event; event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME); return event; } // --- FakeInputDispatcherPolicy --- class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface { Loading Loading @@ -197,6 +209,69 @@ private: } }; // --- HmacKeyManagerTest --- class HmacKeyManagerTest : public testing::Test { protected: HmacKeyManager mHmacKeyManager; }; /** * Ensure that separate calls to sign the same data are generating the same key. * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky * tests. */ TEST_F(HmacKeyManagerTest, GeneratedHmac_IsConsistent) { KeyEvent event = getTestKeyEvent(); VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event); std::array<uint8_t, 32> hmac1 = mHmacKeyManager.sign(verifiedEvent); std::array<uint8_t, 32> hmac2 = mHmacKeyManager.sign(verifiedEvent); ASSERT_EQ(hmac1, hmac2); } /** * Ensure that changes in VerifiedKeyEvent produce a different hmac. */ TEST_F(HmacKeyManagerTest, GeneratedHmac_ChangesWhenFieldsChange) { KeyEvent event = getTestKeyEvent(); VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event); std::array<uint8_t, 32> initialHmac = mHmacKeyManager.sign(verifiedEvent); verifiedEvent.deviceId += 1; ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent)); verifiedEvent.source += 1; ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent)); verifiedEvent.eventTimeNanos += 1; ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent)); verifiedEvent.displayId += 1; ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent)); verifiedEvent.action += 1; ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent)); verifiedEvent.downTimeNanos += 1; ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent)); verifiedEvent.flags += 1; ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent)); verifiedEvent.keyCode += 1; ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent)); verifiedEvent.scanCode += 1; ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent)); verifiedEvent.metaState += 1; ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent)); verifiedEvent.repeatCount += 1; ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent)); } // --- InputDispatcherTest --- Loading Loading
services/inputflinger/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ cc_library_shared { "libinputreporter", "libinputreader", "libbinder", "libcrypto", "libcutils", "libhidlbase", "libinput", Loading
services/inputflinger/dispatcher/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ cc_library_static { ], shared_libs: [ "libbase", "libcrypto", "libcutils", "libinput", "libinputreporter", Loading
services/inputflinger/dispatcher/InputDispatcher.cpp +51 −0 Original line number Diff line number Diff line Loading @@ -61,6 +61,8 @@ static constexpr bool DEBUG_FOCUS = false; #include <android-base/stringprintf.h> #include <binder/Binder.h> #include <log/log.h> #include <openssl/hmac.h> #include <openssl/rand.h> #include <powermanager/PowerManager.h> #include <utils/Trace.h> Loading Loading @@ -325,6 +327,55 @@ static std::unique_ptr<DispatchEntry> createDispatchEntry(const InputTarget& inp return dispatchEntry; } static std::array<uint8_t, 128> getRandomKey() { std::array<uint8_t, 128> key; if (RAND_bytes(key.data(), key.size()) != 1) { LOG_ALWAYS_FATAL("Can't generate HMAC key"); } return key; } // --- HmacKeyManager --- HmacKeyManager::HmacKeyManager() : mHmacKey(getRandomKey()) {} std::array<uint8_t, 32> HmacKeyManager::sign(const VerifiedInputEvent& event) const { size_t size; switch (event.type) { case VerifiedInputEvent::Type::KEY: { size = sizeof(VerifiedKeyEvent); break; } case VerifiedInputEvent::Type::MOTION: { size = sizeof(VerifiedMotionEvent); break; } } std::vector<uint8_t> data; const uint8_t* start = reinterpret_cast<const uint8_t*>(&event); data.assign(start, start + size); return sign(data); } std::array<uint8_t, 32> HmacKeyManager::sign(const std::vector<uint8_t>& data) const { // SHA256 always generates 32-bytes result std::array<uint8_t, 32> hash; unsigned int hashLen = 0; uint8_t* result = HMAC(EVP_sha256(), mHmacKey.data(), mHmacKey.size(), data.data(), data.size(), hash.data(), &hashLen); if (result == nullptr) { ALOGE("Could not sign the data using HMAC"); return INVALID_HMAC; } if (hashLen != hash.size()) { ALOGE("HMAC-SHA256 has unexpected length"); return INVALID_HMAC; } return hash; } // --- InputDispatcher --- InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) Loading
services/inputflinger/dispatcher/InputDispatcher.h +10 −0 Original line number Diff line number Diff line Loading @@ -56,6 +56,16 @@ namespace android::inputdispatcher { class Connection; class HmacKeyManager { public: HmacKeyManager(); std::array<uint8_t, 32> sign(const VerifiedInputEvent& event) const; private: std::array<uint8_t, 32> sign(const std::vector<uint8_t>& data) const; const std::array<uint8_t, 128> mHmacKey; }; /* Dispatches events to input targets. Some functions of the input dispatcher, such as * identifying input targets, are controlled by a separate policy object. * Loading
services/inputflinger/tests/InputDispatcher_test.cpp +75 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,18 @@ struct PointF { float y; }; /** * Return a DOWN key event with KEYCODE_A. */ static KeyEvent getTestKeyEvent() { KeyEvent event; event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME); return event; } // --- FakeInputDispatcherPolicy --- class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface { Loading Loading @@ -197,6 +209,69 @@ private: } }; // --- HmacKeyManagerTest --- class HmacKeyManagerTest : public testing::Test { protected: HmacKeyManager mHmacKeyManager; }; /** * Ensure that separate calls to sign the same data are generating the same key. * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky * tests. */ TEST_F(HmacKeyManagerTest, GeneratedHmac_IsConsistent) { KeyEvent event = getTestKeyEvent(); VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event); std::array<uint8_t, 32> hmac1 = mHmacKeyManager.sign(verifiedEvent); std::array<uint8_t, 32> hmac2 = mHmacKeyManager.sign(verifiedEvent); ASSERT_EQ(hmac1, hmac2); } /** * Ensure that changes in VerifiedKeyEvent produce a different hmac. */ TEST_F(HmacKeyManagerTest, GeneratedHmac_ChangesWhenFieldsChange) { KeyEvent event = getTestKeyEvent(); VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event); std::array<uint8_t, 32> initialHmac = mHmacKeyManager.sign(verifiedEvent); verifiedEvent.deviceId += 1; ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent)); verifiedEvent.source += 1; ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent)); verifiedEvent.eventTimeNanos += 1; ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent)); verifiedEvent.displayId += 1; ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent)); verifiedEvent.action += 1; ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent)); verifiedEvent.downTimeNanos += 1; ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent)); verifiedEvent.flags += 1; ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent)); verifiedEvent.keyCode += 1; ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent)); verifiedEvent.scanCode += 1; ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent)); verifiedEvent.metaState += 1; ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent)); verifiedEvent.repeatCount += 1; ASSERT_NE(initialHmac, mHmacKeyManager.sign(verifiedEvent)); } // --- InputDispatcherTest --- Loading