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