/* ** ** Copyright 2016, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** ** http://www.apache.org/licenses/LICENSE-2.0 ** ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. */ #ifndef KEYSTORE_KEYSTORE_HIDL_SUPPORT_H_ #define KEYSTORE_KEYSTORE_HIDL_SUPPORT_H_ #include <android/hardware/keymaster/3.0/IKeymasterDevice.h> #include <hidl/Status.h> #include "keymaster_tags.h" #include <ostream> #include <sstream> #include <string> #include <android-base/logging.h> namespace keymaster { namespace ng { inline static std::ostream& formatArgs(std::ostream& out) { return out; } template <typename First, typename... Args> inline static std::ostream& formatArgs(std::ostream& out, First&& first, Args&&... args) { out << first; return formatArgs(out, args...); } template <typename... Args> inline static std::string argsToString(Args&&... args) { std::stringstream s; formatArgs(s, args...); return s.str(); } template <typename... Msgs> inline static ErrorCode ksHandleHidlError(const Return<ErrorCode>& error, Msgs&&... msgs) { if (!error.isOk()) { LOG(ERROR) << "HIDL call failed with " << error.description() << " @ " << argsToString(msgs...); return ErrorCode::UNKNOWN_ERROR; } return ErrorCode(error); } template <typename... Msgs> inline static ErrorCode ksHandleHidlError(const Return<void>& error, Msgs&&... msgs) { if (!error.isOk()) { LOG(ERROR) << "HIDL call failed with " << error.description() << " @ " << argsToString(msgs...); return ErrorCode::UNKNOWN_ERROR; } return ErrorCode::OK; } #define KS_HANDLE_HIDL_ERROR(rc) \ ::keystore::ksHandleHidlError(rc, __FILE__, ":", __LINE__, ":", __PRETTY_FUNCTION__) inline static hidl_vec<uint8_t> blob2hidlVec(const uint8_t* data, const size_t length, bool inPlace = true) { hidl_vec<uint8_t> result; if (inPlace) result.setToExternal(const_cast<unsigned char*>(data), length); else { result.resize(length); memcpy(&result[0], data, length); } return result; } inline static hidl_vec<uint8_t> blob2hidlVec(const std::string& value) { hidl_vec<uint8_t> result; result.setToExternal( reinterpret_cast<uint8_t*>(const_cast<std::string::value_type*>(value.data())), static_cast<size_t>(value.size())); return result; } inline static hidl_vec<uint8_t> blob2hidlVec(const std::vector<uint8_t>& blob) { hidl_vec<uint8_t> result; result.setToExternal(const_cast<uint8_t*>(blob.data()), static_cast<size_t>(blob.size())); return result; } template <typename T, typename OutIter> inline static OutIter copy_bytes_to_iterator(const T& value, OutIter dest) { const uint8_t* value_ptr = reinterpret_cast<const uint8_t*>(&value); return std::copy(value_ptr, value_ptr + sizeof(value), dest); } inline static hidl_vec<uint8_t> authToken2HidlVec(const HardwareAuthToken& token) { static_assert( std::is_same<decltype(token.hmac), ::android::hardware::hidl_array<uint8_t, 32>>::value, "This function assumes token HMAC is 32 bytes, but it might not be."); static_assert(1 /* version size */ + sizeof(token.challenge) + sizeof(token.userId) + sizeof(token.authenticatorId) + sizeof(token.authenticatorType) + sizeof(token.timestamp) + 32 /* HMAC size */ == sizeof(hw_auth_token_t), "HardwareAuthToken content size does not match hw_auth_token_t size"); hidl_vec<uint8_t> result; result.resize(sizeof(hw_auth_token_t)); auto pos = result.begin(); *pos++ = 0; // Version byte pos = copy_bytes_to_iterator(token.challenge, pos); pos = copy_bytes_to_iterator(token.userId, pos); pos = copy_bytes_to_iterator(token.authenticatorId, pos); pos = copy_bytes_to_iterator(token.authenticatorType, pos); pos = copy_bytes_to_iterator(token.timestamp, pos); pos = std::copy(token.hmac.data(), token.hmac.data() + token.hmac.size(), pos); return result; } inline std::string hidlVec2String(const hidl_vec<uint8_t>& value) { return std::string(reinterpret_cast<const std::string::value_type*>(&value[0]), value.size()); } } } // namespace keystore #endif // KEYSTORE_KEYSTORE_HIDL_SUPPORT_H_