Home | History | Annotate | Download | only in keystore
      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