/* * Copyright 2020, 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. */ #include "TrustyApp.h" #include <android-base/logging.h> #include <sys/uio.h> #include <trusty/tipc.h> namespace android { namespace trusty { // 0x1000 is the message buffer size but we need to leave some space for a protocol header. // This assures that packets can always be read/written in one read/write operation. static constexpr const uint32_t kPacketSize = 0x1000 - 32; enum class PacketType : uint32_t { SND, RCV, ACK, }; struct PacketHeader { PacketType type; uint32_t remaining; }; const char* toString(PacketType t) { switch (t) { case PacketType::SND: return "SND"; case PacketType::RCV: return "RCV"; case PacketType::ACK: return "ACK"; default: return "UNKNOWN"; } } static constexpr const uint32_t kHeaderSize = sizeof(PacketHeader); static constexpr const uint32_t kPayloadSize = kPacketSize - kHeaderSize; ssize_t TrustyRpc(int handle, const uint8_t* obegin, const uint8_t* oend, uint8_t* ibegin, uint8_t* iend) { while (obegin != oend) { PacketHeader header = { .type = PacketType::SND, .remaining = uint32_t(oend - obegin), }; uint32_t body_size = std::min(kPayloadSize, header.remaining); iovec iov[] = { { .iov_base = &header, .iov_len = kHeaderSize, }, { .iov_base = const_cast<uint8_t*>(obegin), .iov_len = body_size, }, }; int rc = writev(handle, iov, 2); if (!rc) { PLOG(ERROR) << "Error sending SND message. " << rc; return rc; } obegin += body_size; rc = read(handle, &header, kHeaderSize); if (!rc) { PLOG(ERROR) << "Error reading ACK. " << rc; return rc; } if (header.type != PacketType::ACK || header.remaining != oend - obegin) { LOG(ERROR) << "malformed ACK"; return -1; } } ssize_t remaining = 0; auto begin = ibegin; do { PacketHeader header = { .type = PacketType::RCV, .remaining = 0, }; iovec iov[] = { { .iov_base = &header, .iov_len = kHeaderSize, }, { .iov_base = begin, .iov_len = uint32_t(iend - begin), }, }; ssize_t rc = writev(handle, iov, 1); if (!rc) { PLOG(ERROR) << "Error sending RCV message. " << rc; return rc; } rc = readv(handle, iov, 2); if (rc < 0) { PLOG(ERROR) << "Error reading response. " << rc; return rc; } uint32_t body_size = std::min(kPayloadSize, header.remaining); if (body_size != rc - kHeaderSize) { LOG(ERROR) << "Unexpected amount of data: " << rc; return -1; } remaining = header.remaining - body_size; begin += body_size; } while (remaining); return begin - ibegin; } TrustyApp::TrustyApp(const std::string& path, const std::string& appname) : handle_(kInvalidHandle) { handle_ = tipc_connect(path.c_str(), appname.c_str()); if (handle_ == kInvalidHandle) { LOG(ERROR) << AT << "failed to connect to Trusty TA \"" << appname << "\" using dev:" << "\"" << path << "\""; } LOG(INFO) << AT << "succeeded to connect to Trusty TA \"" << appname << "\""; } TrustyApp::~TrustyApp() { if (handle_ != kInvalidHandle) { tipc_close(handle_); } LOG(INFO) << "Done shutting down TrustyApp"; } } // namespace trusty } // namespace android