C++程序  |  135行  |  4.76 KB

/*
 **
 ** 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_