1 /* 2 ** 3 ** Copyright 2016, The Android Open Source Project 4 ** 5 ** Licensed under the Apache License, Version 2.0 (the "License"); 6 ** you may not use this file except in compliance with the License. 7 ** You may obtain a copy of the License at 8 ** 9 ** http://www.apache.org/licenses/LICENSE-2.0 10 ** 11 ** Unless required by applicable law or agreed to in writing, software 12 ** distributed under the License is distributed on an "AS IS" BASIS, 13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 ** See the License for the specific language governing permissions and 15 ** limitations under the License. 16 */ 17 18 #ifndef KEYSTORE_KEYSTORE_HIDL_SUPPORT_H_ 19 #define KEYSTORE_KEYSTORE_HIDL_SUPPORT_H_ 20 21 #include <ostream> 22 #include <sstream> 23 #include <string> 24 25 #include <android-base/logging.h> 26 #include <android/hardware/keymaster/3.0/IKeymasterDevice.h> 27 #include <hardware/hw_auth_token.h> 28 #include <hidl/Status.h> 29 #include <keymasterV4_0/keymaster_utils.h> 30 31 #include <keystore/keymaster_types.h> 32 33 namespace keystore { 34 35 using android::hardware::keymaster::V4_0::support::blob2hidlVec; 36 using android::hardware::keymaster::V4_0::support::hidlVec2AuthToken; 37 using android::hardware::keymaster::V4_0::support::authToken2HidlVec; 38 39 inline static std::ostream& formatArgs(std::ostream& out) { 40 return out; 41 } 42 43 template <typename First, typename... Args> 44 inline static std::ostream& formatArgs(std::ostream& out, First&& first, Args&&... args) { 45 out << first; 46 return formatArgs(out, args...); 47 } 48 49 template <typename... Args> inline static std::string argsToString(Args&&... args) { 50 std::stringstream s; 51 formatArgs(s, args...); 52 return s.str(); 53 } 54 55 template <typename... Msgs> 56 inline static ErrorCode ksHandleHidlError(const Return<ErrorCode>& error, Msgs&&... msgs) { 57 if (!error.isOk()) { 58 ALOGE("HIDL call failed with %s @ %s", error.description().c_str(), 59 argsToString(msgs...).c_str()); 60 return ErrorCode::UNKNOWN_ERROR; 61 } 62 return ErrorCode(error); 63 } 64 template <typename... Msgs> 65 inline static ErrorCode ksHandleHidlError(const Return<void>& error, Msgs&&... msgs) { 66 if (!error.isOk()) { 67 ALOGE("HIDL call failed with %s @ %s", error.description().c_str(), 68 argsToString(msgs...).c_str()); 69 return ErrorCode::UNKNOWN_ERROR; 70 } 71 return ErrorCode::OK; 72 } 73 74 #define KS_HANDLE_HIDL_ERROR(rc) \ 75 ::keystore::ksHandleHidlError(rc, __FILE__, ":", __LINE__, ":", __PRETTY_FUNCTION__) 76 77 template <typename T, typename OutIter> 78 inline static OutIter copy_bytes_to_iterator(const T& value, OutIter dest) { 79 const uint8_t* value_ptr = reinterpret_cast<const uint8_t*>(&value); 80 return std::copy(value_ptr, value_ptr + sizeof(value), dest); 81 } 82 83 constexpr size_t kHmacSize = 32; 84 85 inline static hidl_vec<uint8_t> authToken2HidlVec(const Km3HardwareAuthToken& token) { 86 static_assert(std::is_same<decltype(token.hmac), 87 ::android::hardware::hidl_array<uint8_t, kHmacSize>>::value, 88 "This function assumes token HMAC is 32 bytes, but it might not be."); 89 static_assert(1 /* version size */ + sizeof(token.challenge) + sizeof(token.userId) + 90 sizeof(token.authenticatorId) + sizeof(token.authenticatorType) + 91 sizeof(token.timestamp) + kHmacSize == 92 sizeof(hw_auth_token_t), 93 "HardwareAuthToken content size does not match hw_auth_token_t size"); 94 95 hidl_vec<uint8_t> result; 96 result.resize(sizeof(hw_auth_token_t)); 97 auto pos = result.begin(); 98 *pos++ = 0; // Version byte 99 pos = copy_bytes_to_iterator(token.challenge, pos); 100 pos = copy_bytes_to_iterator(token.userId, pos); 101 pos = copy_bytes_to_iterator(token.authenticatorId, pos); 102 pos = copy_bytes_to_iterator(token.authenticatorType, pos); 103 pos = copy_bytes_to_iterator(token.timestamp, pos); 104 pos = std::copy(token.hmac.data(), token.hmac.data() + token.hmac.size(), pos); 105 106 return result; 107 } 108 109 template <typename T, typename InIter> 110 inline static InIter copy_bytes_from_iterator(T* value, InIter src) { 111 uint8_t* value_ptr = reinterpret_cast<uint8_t*>(value); 112 std::copy(src, src + sizeof(T), value_ptr); 113 return src + sizeof(T); 114 } 115 116 inline static Km3HardwareAuthToken hidlVec2Km3AuthToken(const hidl_vec<uint8_t>& buffer) { 117 Km3HardwareAuthToken token; 118 static_assert(std::is_same<decltype(token.hmac), 119 ::android::hardware::hidl_array<uint8_t, kHmacSize>>::value, 120 "This function assumes token HMAC is 32 bytes, but it might not be."); 121 static_assert(1 /* version size */ + sizeof(token.challenge) + sizeof(token.userId) + 122 sizeof(token.authenticatorId) + sizeof(token.authenticatorType) + 123 sizeof(token.timestamp) + kHmacSize == 124 sizeof(hw_auth_token_t), 125 "HardwareAuthToken content size does not match hw_auth_token_t size"); 126 127 if (buffer.size() != sizeof(hw_auth_token_t)) return {}; 128 129 auto pos = buffer.begin(); 130 ++pos; // skip first byte 131 pos = copy_bytes_from_iterator(&token.challenge, pos); 132 pos = copy_bytes_from_iterator(&token.userId, pos); 133 pos = copy_bytes_from_iterator(&token.authenticatorId, pos); 134 pos = copy_bytes_from_iterator(&token.authenticatorType, pos); 135 pos = copy_bytes_from_iterator(&token.timestamp, pos); 136 pos = std::copy(pos, pos + token.hmac.size(), &token.hmac[0]); 137 138 return token; 139 } 140 141 inline std::string hidlVec2String(const hidl_vec<uint8_t>& value) { 142 return std::string(reinterpret_cast<const std::string::value_type*>(&value[0]), value.size()); 143 } 144 145 } // namespace keystore 146 147 #endif // KEYSTORE_KEYSTORE_HIDL_SUPPORT_H_ 148