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 
formatArgs(std::ostream & out)39 inline static std::ostream& formatArgs(std::ostream& out) {
40     return out;
41 }
42 
43 template <typename First, typename... Args>
formatArgs(std::ostream & out,First && first,Args &&...args)44 inline static std::ostream& formatArgs(std::ostream& out, First&& first, Args&&... args) {
45     out << first;
46     return formatArgs(out, args...);
47 }
48 
argsToString(Args &&...args)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 KMDevice, typename... Msgs>
ksHandleHidlError(KMDevice dev,const Return<ErrorCode> & error,Msgs &&...msgs)56 inline static ErrorCode ksHandleHidlError(KMDevice dev, const Return<ErrorCode>& error,
57                                           Msgs&&... msgs) {
58     if (!error.isOk()) {
59         LOG(ERROR) << "HIDL call failed with " << error.description().c_str() << " @ "
60                    << argsToString(msgs...);
61         return ErrorCode::UNKNOWN_ERROR;
62     }
63     auto ec = ErrorCode(error);
64     dev->logIfKeymasterVendorError(ec);
65     return ec;
66 }
67 template <typename KMDevice, typename... Msgs>
ksHandleHidlError(KMDevice,const Return<void> & error,Msgs &&...msgs)68 inline static ErrorCode ksHandleHidlError(KMDevice, const Return<void>& error, Msgs&&... msgs) {
69     if (!error.isOk()) {
70         ALOGE("HIDL call failed with %s @ %s", error.description().c_str(),
71               argsToString(msgs...).c_str());
72         return ErrorCode::UNKNOWN_ERROR;
73     }
74     return ErrorCode::OK;
75 }
76 
77 #define KS_HANDLE_HIDL_ERROR(dev, rc)                                                              \
78     ::keystore::ksHandleHidlError(dev, rc, __FILE__, ":", __LINE__, ":", __PRETTY_FUNCTION__)
79 
80 template <typename T, typename OutIter>
copy_bytes_to_iterator(const T & value,OutIter dest)81 inline static OutIter copy_bytes_to_iterator(const T& value, OutIter dest) {
82     const uint8_t* value_ptr = reinterpret_cast<const uint8_t*>(&value);
83     return std::copy(value_ptr, value_ptr + sizeof(value), dest);
84 }
85 
86 constexpr size_t kHmacSize = 32;
87 
authToken2HidlVec(const Km3HardwareAuthToken & token)88 inline static hidl_vec<uint8_t> authToken2HidlVec(const Km3HardwareAuthToken& token) {
89     static_assert(std::is_same<decltype(token.hmac),
90                                ::android::hardware::hidl_array<uint8_t, kHmacSize>>::value,
91                   "This function assumes token HMAC is 32 bytes, but it might not be.");
92     static_assert(1 /* version size */ + sizeof(token.challenge) + sizeof(token.userId) +
93                           sizeof(token.authenticatorId) + sizeof(token.authenticatorType) +
94                           sizeof(token.timestamp) + kHmacSize ==
95                       sizeof(hw_auth_token_t),
96                   "HardwareAuthToken content size does not match hw_auth_token_t size");
97 
98     hidl_vec<uint8_t> result;
99     result.resize(sizeof(hw_auth_token_t));
100     auto pos = result.begin();
101     *pos++ = 0;  // Version byte
102     pos = copy_bytes_to_iterator(token.challenge, pos);
103     pos = copy_bytes_to_iterator(token.userId, pos);
104     pos = copy_bytes_to_iterator(token.authenticatorId, pos);
105     pos = copy_bytes_to_iterator(token.authenticatorType, pos);
106     pos = copy_bytes_to_iterator(token.timestamp, pos);
107     pos = std::copy(token.hmac.data(), token.hmac.data() + token.hmac.size(), pos);
108 
109     return result;
110 }
111 
112 template <typename T, typename InIter>
copy_bytes_from_iterator(T * value,InIter src)113 inline static InIter copy_bytes_from_iterator(T* value, InIter src) {
114     uint8_t* value_ptr = reinterpret_cast<uint8_t*>(value);
115     std::copy(src, src + sizeof(T), value_ptr);
116     return src + sizeof(T);
117 }
118 
hidlVec2Km3AuthToken(const hidl_vec<uint8_t> & buffer)119 inline static Km3HardwareAuthToken hidlVec2Km3AuthToken(const hidl_vec<uint8_t>& buffer) {
120     Km3HardwareAuthToken token;
121     static_assert(std::is_same<decltype(token.hmac),
122                                ::android::hardware::hidl_array<uint8_t, kHmacSize>>::value,
123                   "This function assumes token HMAC is 32 bytes, but it might not be.");
124     static_assert(1 /* version size */ + sizeof(token.challenge) + sizeof(token.userId) +
125                           sizeof(token.authenticatorId) + sizeof(token.authenticatorType) +
126                           sizeof(token.timestamp) + kHmacSize ==
127                       sizeof(hw_auth_token_t),
128                   "HardwareAuthToken content size does not match hw_auth_token_t size");
129 
130     if (buffer.size() != sizeof(hw_auth_token_t)) return {};
131 
132     auto pos = buffer.begin();
133     ++pos;  // skip first byte
134     pos = copy_bytes_from_iterator(&token.challenge, pos);
135     pos = copy_bytes_from_iterator(&token.userId, pos);
136     pos = copy_bytes_from_iterator(&token.authenticatorId, pos);
137     pos = copy_bytes_from_iterator(&token.authenticatorType, pos);
138     pos = copy_bytes_from_iterator(&token.timestamp, pos);
139     pos = std::copy(pos, pos + token.hmac.size(), &token.hmac[0]);
140 
141     return token;
142 }
143 
hidlVec2String(const hidl_vec<uint8_t> & value)144 inline std::string hidlVec2String(const hidl_vec<uint8_t>& value) {
145     return std::string(reinterpret_cast<const std::string::value_type*>(&value[0]), value.size());
146 }
147 
148 }  // namespace keystore
149 
150 #endif  // KEYSTORE_KEYSTORE_HIDL_SUPPORT_H_
151