130 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			130 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			C++
		
	
	
	
| /*
 | |
|  **
 | |
|  ** 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.
 | |
|  */
 | |
| 
 | |
| #pragma once
 | |
| 
 | |
| #include "keymaster_tags.h"
 | |
| #include <android/hardware/keymaster/3.0/IKeymasterDevice.h>
 | |
| #include <hidl/Status.h>
 | |
| #include <ostream>
 | |
| #include <sstream>
 | |
| #include <string>
 | |
| 
 | |
| #include <android-base/logging.h>
 | |
| 
 | |
| namespace keymaster::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 keymaster::ng
 |