/* * Copyright 2021, 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 #include #include #include #include #define countof(arr) (sizeof(arr) / sizeof(arr[0])) namespace android { namespace trusty { namespace confirmationui { using ::android::base::unique_fd; static inline uintptr_t RoundPageUp(uintptr_t val) { return (val + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); } ssize_t TrustyApp::TrustyRpc(const uint8_t* obegin, const uint8_t* oend, uint8_t* ibegin, uint8_t* iend) { uint32_t olen = oend - obegin; if (olen > shm_len_) { LOG(ERROR) << AT << "request message too long to fit in shared memory"; return -1; } memcpy(shm_base_, obegin, olen); confirmationui_hdr hdr = { .cmd = CONFIRMATIONUI_CMD_MSG, }; confirmationui_msg_args args = { .msg_len = olen, }; iovec iov[] = { { .iov_base = &hdr, .iov_len = sizeof(hdr), }, { .iov_base = &args, .iov_len = sizeof(args), }, }; int rc = tipc_send(handle_, iov, countof(iov), NULL, 0); if (rc != static_cast(sizeof(hdr) + sizeof(args))) { LOG(ERROR) << AT << "failed to send MSG request"; return -1; } rc = readv(handle_, iov, countof(iov)); if (rc != static_cast(sizeof(hdr) + sizeof(args))) { LOG(ERROR) << AT << "failed to receive MSG response"; return -1; } if (hdr.cmd != (CONFIRMATIONUI_CMD_MSG | CONFIRMATIONUI_RESP_BIT)) { LOG(ERROR) << AT << "unknown response command: " << hdr.cmd; return -1; } uint32_t ilen = iend - ibegin; if (args.msg_len > ilen) { LOG(ERROR) << AT << "response message too long to fit in return buffer"; return -1; } memcpy(ibegin, shm_base_, args.msg_len); return args.msg_len; } TrustyApp::TrustyApp(const std::string& path, const std::string& appname) : handle_(kInvalidHandle) { unique_fd tipc_handle(tipc_connect(path.c_str(), appname.c_str())); if (tipc_handle < 0) { LOG(ERROR) << AT << "failed to connect to Trusty TA \"" << appname << "\" using dev:" << "\"" << path << "\""; return; } uint32_t shm_len = RoundPageUp(CONFIRMATIONUI_MAX_MSG_SIZE); BufferAllocator allocator; unique_fd dma_buf(allocator.Alloc("system", shm_len)); if (dma_buf < 0) { LOG(ERROR) << AT << "failed to allocate shared memory buffer"; return; } confirmationui_hdr hdr = { .cmd = CONFIRMATIONUI_CMD_INIT, }; confirmationui_init_req args = { .shm_len = shm_len, }; iovec iov[] = { { .iov_base = &hdr, .iov_len = sizeof(hdr), }, { .iov_base = &args, .iov_len = sizeof(args), }, }; trusty_shm shm = { .fd = dma_buf, .transfer = TRUSTY_SHARE, }; int rc = tipc_send(tipc_handle, iov, 2, &shm, 1); if (rc != static_cast(sizeof(hdr) + sizeof(args))) { LOG(ERROR) << AT << "failed to send INIT request"; return; } rc = read(tipc_handle, &hdr, sizeof(hdr)); if (rc != static_cast(sizeof(hdr))) { LOG(ERROR) << AT << "failed to receive INIT response"; return; } if (hdr.cmd != (CONFIRMATIONUI_CMD_INIT | CONFIRMATIONUI_RESP_BIT)) { LOG(ERROR) << AT << "unknown response command: " << hdr.cmd; return; } void* shm_base = mmap(0, shm_len, PROT_READ | PROT_WRITE, MAP_SHARED, dma_buf, 0); if (shm_base == MAP_FAILED) { LOG(ERROR) << AT << "failed to mmap() shared memory buffer"; return; } handle_ = std::move(tipc_handle); shm_base_ = shm_base; shm_len_ = shm_len; LOG(INFO) << AT << "succeeded to connect to Trusty TA \"" << appname << "\""; } TrustyApp::~TrustyApp() { LOG(INFO) << "Done shutting down TrustyApp"; } } // namespace confirmationui } // namespace trusty } // namespace android