1 #define LOG_TAG "hwservicemanager" 2 3 #include "TokenManager.h" 4 5 #include <android-base/logging.h> 6 #include <functional> 7 #include <log/log.h> 8 #include <openssl/hmac.h> 9 #include <openssl/rand.h> 10 11 namespace android { 12 namespace hidl { 13 namespace token { 14 namespace V1_0 { 15 namespace implementation { 16 17 static void ReadRandomBytes(uint8_t *buf, size_t len) { 18 int fd = TEMP_FAILURE_RETRY(open("/dev/urandom", O_RDONLY | O_CLOEXEC | O_NOFOLLOW)); 19 if (fd == -1) { 20 ALOGE("%s: cannot read /dev/urandom", __func__); 21 return; 22 } 23 24 size_t n; 25 while ((n = TEMP_FAILURE_RETRY(read(fd, buf, len))) > 0) { 26 len -= n; 27 buf += n; 28 } 29 if (len > 0) { 30 ALOGW("%s: there are %d bytes skipped", __func__, (int)len); 31 } 32 close(fd); 33 } 34 35 TokenManager::TokenManager() { 36 ReadRandomBytes(mKey.data(), mKey.size()); 37 } 38 39 // Methods from ::android::hidl::token::V1_0::ITokenManager follow. 40 Return<void> TokenManager::createToken(const sp<IBase>& store, createToken_cb hidl_cb) { 41 TokenInterface interface = generateToken(store); 42 43 if (interface.interface == nullptr) { 44 hidl_cb({}); 45 return Void(); 46 } 47 48 uint64_t id = getTokenId(interface.token); 49 50 if (id == TOKEN_ID_NONE) { 51 hidl_cb({}); 52 return Void(); 53 } 54 55 mMap[id] = interface; 56 57 hidl_cb(interface.token); 58 return Void(); 59 } 60 61 std::unordered_map<uint64_t, TokenManager::TokenInterface>::const_iterator 62 TokenManager::lookupToken(const hidl_vec<uint8_t> &token) { 63 uint64_t tokenId = getTokenId(token); 64 65 if (tokenId == TOKEN_ID_NONE) { 66 return mMap.end(); 67 } 68 69 auto it = mMap.find(tokenId); 70 71 if (it == mMap.end()) { 72 return mMap.end(); 73 } 74 75 const TokenInterface &interface = it->second; 76 77 if (!constantTimeCompare(token, interface.token)) { 78 ALOGE("Fetch of token with invalid hash."); 79 return mMap.end(); 80 } 81 82 return it; 83 } 84 85 Return<bool> TokenManager::unregister(const hidl_vec<uint8_t> &token) { 86 auto it = lookupToken(token); 87 88 if (it == mMap.end()) { 89 return false; 90 } 91 92 mMap.erase(it); 93 return true; 94 } 95 96 Return<sp<IBase>> TokenManager::get(const hidl_vec<uint8_t> &token) { 97 auto it = lookupToken(token); 98 99 if (it == mMap.end()) { 100 return nullptr; 101 } 102 103 return it->second.interface; 104 } 105 106 107 TokenManager::TokenInterface TokenManager::generateToken(const sp<IBase> &interface) { 108 uint64_t id = ++mTokenIndex; 109 110 std::array<uint8_t, EVP_MAX_MD_SIZE> hmac; 111 uint32_t hmacSize; 112 113 uint8_t *hmacOut = HMAC(EVP_sha256(), 114 mKey.data(), mKey.size(), 115 (uint8_t*) &id, ID_SIZE, 116 hmac.data(), &hmacSize); 117 118 if (hmacOut == nullptr || 119 hmacOut != hmac.data()) { 120 ALOGE("Generating token failed, got %p.", hmacOut); 121 return { nullptr, {} }; 122 } 123 124 // only care about the first HMAC_SIZE bytes of the HMAC 125 const hidl_vec<uint8_t> &token = TokenManager::getToken(id, hmac.data(), hmacSize); 126 127 return { interface, token }; 128 } 129 130 __attribute__((optnone)) 131 bool TokenManager::constantTimeCompare(const hidl_vec<uint8_t> &t1, const hidl_vec<uint8_t> &t2) { 132 if (t1.size() != t2.size()) { 133 return false; 134 } 135 136 uint8_t x = 0; 137 for (size_t i = 0; i < t1.size(); i++) { 138 x |= t1[i] ^ t2[i]; 139 } 140 141 return x == 0; 142 } 143 144 uint64_t TokenManager::getTokenId(const hidl_vec<uint8_t> &token) { 145 if (token.size() < ID_SIZE) { 146 return TOKEN_ID_NONE; 147 } 148 149 uint64_t id = 0; 150 for (size_t i = 0; i < ID_SIZE; i++) { 151 id |= token[i] << i; 152 } 153 154 return id; 155 } 156 157 hidl_vec<uint8_t> TokenManager::getToken(const uint64_t id, const uint8_t *hmac, uint64_t hmacSize) { 158 hidl_vec<uint8_t> token; 159 token.resize(ID_SIZE + hmacSize); 160 161 for (size_t i = 0; i < ID_SIZE; i++) { 162 token[i] = (id >> i) & 0xFF; 163 } 164 165 for (size_t i = 0; i < hmacSize; i++) { 166 token[i + ID_SIZE] = hmac[i]; 167 } 168 169 return token; 170 } 171 172 173 } // namespace implementation 174 } // namespace V1_0 175 } // namespace token 176 } // namespace hidl 177 } // namespace android 178