166ac401fabe4106f53e3352f0559cad082246d7bSteven Moreland#define LOG_TAG "hwservicemanager" 266ac401fabe4106f53e3352f0559cad082246d7bSteven Moreland 366ac401fabe4106f53e3352f0559cad082246d7bSteven Moreland#include "TokenManager.h" 466ac401fabe4106f53e3352f0559cad082246d7bSteven Moreland 566ac401fabe4106f53e3352f0559cad082246d7bSteven Moreland#include <android-base/logging.h> 666ac401fabe4106f53e3352f0559cad082246d7bSteven Moreland#include <functional> 779a9e3263f171a220ce4e32d89e5df10b1ab6499Steven Moreland#include <log/log.h> 8d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland#include <openssl/hmac.h> 9d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland#include <openssl/rand.h> 1066ac401fabe4106f53e3352f0559cad082246d7bSteven Moreland 1166ac401fabe4106f53e3352f0559cad082246d7bSteven Morelandnamespace android { 1266ac401fabe4106f53e3352f0559cad082246d7bSteven Morelandnamespace hidl { 1366ac401fabe4106f53e3352f0559cad082246d7bSteven Morelandnamespace token { 1466ac401fabe4106f53e3352f0559cad082246d7bSteven Morelandnamespace V1_0 { 1566ac401fabe4106f53e3352f0559cad082246d7bSteven Morelandnamespace implementation { 1666ac401fabe4106f53e3352f0559cad082246d7bSteven Moreland 1769673825e0f3d99673892d2adf4ed003c6019238bohustatic void ReadRandomBytes(uint8_t *buf, size_t len) { 1869673825e0f3d99673892d2adf4ed003c6019238bohu int fd = TEMP_FAILURE_RETRY(open("/dev/urandom", O_RDONLY | O_CLOEXEC | O_NOFOLLOW)); 1969673825e0f3d99673892d2adf4ed003c6019238bohu if (fd == -1) { 2069673825e0f3d99673892d2adf4ed003c6019238bohu ALOGE("%s: cannot read /dev/urandom", __func__); 2169673825e0f3d99673892d2adf4ed003c6019238bohu return; 2269673825e0f3d99673892d2adf4ed003c6019238bohu } 2369673825e0f3d99673892d2adf4ed003c6019238bohu 2469673825e0f3d99673892d2adf4ed003c6019238bohu size_t n; 2569673825e0f3d99673892d2adf4ed003c6019238bohu while ((n = TEMP_FAILURE_RETRY(read(fd, buf, len))) > 0) { 2669673825e0f3d99673892d2adf4ed003c6019238bohu len -= n; 2769673825e0f3d99673892d2adf4ed003c6019238bohu buf += n; 2869673825e0f3d99673892d2adf4ed003c6019238bohu } 2969673825e0f3d99673892d2adf4ed003c6019238bohu if (len > 0) { 3069673825e0f3d99673892d2adf4ed003c6019238bohu ALOGW("%s: there are %d bytes skipped", __func__, (int)len); 3169673825e0f3d99673892d2adf4ed003c6019238bohu } 3269673825e0f3d99673892d2adf4ed003c6019238bohu close(fd); 3369673825e0f3d99673892d2adf4ed003c6019238bohu} 3469673825e0f3d99673892d2adf4ed003c6019238bohu 35d4530e491c82df0ef296af69ded1c10490fbc4e9Steven MorelandTokenManager::TokenManager() { 3669673825e0f3d99673892d2adf4ed003c6019238bohu ReadRandomBytes(mKey.data(), mKey.size()); 37d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland} 38d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland 3966ac401fabe4106f53e3352f0559cad082246d7bSteven Moreland// Methods from ::android::hidl::token::V1_0::ITokenManager follow. 40d4530e491c82df0ef296af69ded1c10490fbc4e9Steven MorelandReturn<void> TokenManager::createToken(const sp<IBase>& store, createToken_cb hidl_cb) { 41d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland TokenInterface interface = generateToken(store); 4266ac401fabe4106f53e3352f0559cad082246d7bSteven Moreland 43d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland if (interface.interface == nullptr) { 44d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland hidl_cb({}); 45d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland return Void(); 46d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland } 4766ac401fabe4106f53e3352f0559cad082246d7bSteven Moreland 48d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland uint64_t id = getTokenId(interface.token); 49d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland 50d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland if (id == TOKEN_ID_NONE) { 51d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland hidl_cb({}); 52d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland return Void(); 53d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland } 54d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland 55d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland mMap[id] = interface; 56d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland 57d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland hidl_cb(interface.token); 58d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland return Void(); 5966ac401fabe4106f53e3352f0559cad082246d7bSteven Moreland} 6066ac401fabe4106f53e3352f0559cad082246d7bSteven Moreland 61d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Morelandstd::unordered_map<uint64_t, TokenManager::TokenInterface>::const_iterator 62d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland TokenManager::lookupToken(const hidl_vec<uint8_t> &token) { 63d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland uint64_t tokenId = getTokenId(token); 64d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland 65d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland if (tokenId == TOKEN_ID_NONE) { 66d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland return mMap.end(); 67d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland } 68d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland 69d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland auto it = mMap.find(tokenId); 70d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland 71d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland if (it == mMap.end()) { 72d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland return mMap.end(); 73d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland } 74d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland 75d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland const TokenInterface &interface = it->second; 76d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland 77d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland if (!constantTimeCompare(token, interface.token)) { 78d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland ALOGE("Fetch of token with invalid hash."); 79d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland return mMap.end(); 80d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland } 81d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland 82d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland return it; 83d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland} 84d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland 85d4530e491c82df0ef296af69ded1c10490fbc4e9Steven MorelandReturn<bool> TokenManager::unregister(const hidl_vec<uint8_t> &token) { 86d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland auto it = lookupToken(token); 8766ac401fabe4106f53e3352f0559cad082246d7bSteven Moreland 8866ac401fabe4106f53e3352f0559cad082246d7bSteven Moreland if (it == mMap.end()) { 8966ac401fabe4106f53e3352f0559cad082246d7bSteven Moreland return false; 9066ac401fabe4106f53e3352f0559cad082246d7bSteven Moreland } 9166ac401fabe4106f53e3352f0559cad082246d7bSteven Moreland 9266ac401fabe4106f53e3352f0559cad082246d7bSteven Moreland mMap.erase(it); 9366ac401fabe4106f53e3352f0559cad082246d7bSteven Moreland return true; 9466ac401fabe4106f53e3352f0559cad082246d7bSteven Moreland} 9566ac401fabe4106f53e3352f0559cad082246d7bSteven Moreland 96d4530e491c82df0ef296af69ded1c10490fbc4e9Steven MorelandReturn<sp<IBase>> TokenManager::get(const hidl_vec<uint8_t> &token) { 97d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland auto it = lookupToken(token); 9866ac401fabe4106f53e3352f0559cad082246d7bSteven Moreland 9966ac401fabe4106f53e3352f0559cad082246d7bSteven Moreland if (it == mMap.end()) { 1007b02bf9599142a2fc04102537f60c28dd8483e8bMartijn Coenen return nullptr; 10166ac401fabe4106f53e3352f0559cad082246d7bSteven Moreland } 10266ac401fabe4106f53e3352f0559cad082246d7bSteven Moreland 103d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland return it->second.interface; 10466ac401fabe4106f53e3352f0559cad082246d7bSteven Moreland} 10566ac401fabe4106f53e3352f0559cad082246d7bSteven Moreland 106d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland 107d4530e491c82df0ef296af69ded1c10490fbc4e9Steven MorelandTokenManager::TokenInterface TokenManager::generateToken(const sp<IBase> &interface) { 108d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland uint64_t id = ++mTokenIndex; 109d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland 110d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland std::array<uint8_t, EVP_MAX_MD_SIZE> hmac; 111d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland uint32_t hmacSize; 112d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland 113d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland uint8_t *hmacOut = HMAC(EVP_sha256(), 114d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland mKey.data(), mKey.size(), 115d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland (uint8_t*) &id, ID_SIZE, 116d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland hmac.data(), &hmacSize); 117d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland 118d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland if (hmacOut == nullptr || 119d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland hmacOut != hmac.data()) { 120d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland ALOGE("Generating token failed, got %p.", hmacOut); 121d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland return { nullptr, {} }; 122d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland } 123d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland 124d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland // only care about the first HMAC_SIZE bytes of the HMAC 125d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland const hidl_vec<uint8_t> &token = TokenManager::getToken(id, hmac.data(), hmacSize); 126d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland 127d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland return { interface, token }; 128d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland} 129d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland 130d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland__attribute__((optnone)) 131d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Morelandbool TokenManager::constantTimeCompare(const hidl_vec<uint8_t> &t1, const hidl_vec<uint8_t> &t2) { 132d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland if (t1.size() != t2.size()) { 133d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland return false; 134d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland } 135d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland 136d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland uint8_t x = 0; 137d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland for (size_t i = 0; i < t1.size(); i++) { 138d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland x |= t1[i] ^ t2[i]; 139d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland } 140d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland 141d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland return x == 0; 142d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland} 143d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland 144d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Morelanduint64_t TokenManager::getTokenId(const hidl_vec<uint8_t> &token) { 145d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland if (token.size() < ID_SIZE) { 146d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland return TOKEN_ID_NONE; 147d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland } 148d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland 149d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland uint64_t id = 0; 150d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland for (size_t i = 0; i < ID_SIZE; i++) { 151d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland id |= token[i] << i; 152d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland } 153d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland 154d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland return id; 155d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland} 156d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland 157d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Morelandhidl_vec<uint8_t> TokenManager::getToken(const uint64_t id, const uint8_t *hmac, uint64_t hmacSize) { 158d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland hidl_vec<uint8_t> token; 159d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland token.resize(ID_SIZE + hmacSize); 160d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland 161d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland for (size_t i = 0; i < ID_SIZE; i++) { 162d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland token[i] = (id >> i) & 0xFF; 163d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland } 164d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland 165d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland for (size_t i = 0; i < hmacSize; i++) { 166d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland token[i + ID_SIZE] = hmac[i]; 167d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland } 168d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland 169d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland return token; 17066ac401fabe4106f53e3352f0559cad082246d7bSteven Moreland} 17166ac401fabe4106f53e3352f0559cad082246d7bSteven Moreland 172d4530e491c82df0ef296af69ded1c10490fbc4e9Steven Moreland 17366ac401fabe4106f53e3352f0559cad082246d7bSteven Moreland} // namespace implementation 17466ac401fabe4106f53e3352f0559cad082246d7bSteven Moreland} // namespace V1_0 17566ac401fabe4106f53e3352f0559cad082246d7bSteven Moreland} // namespace token 17666ac401fabe4106f53e3352f0559cad082246d7bSteven Moreland} // namespace hidl 17766ac401fabe4106f53e3352f0559cad082246d7bSteven Moreland} // namespace android 178