1 /* 2 * Copyright 2020, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include <TrustyIpc.h> 20 21 #include <android-base/logging.h> 22 #include <android-base/unique_fd.h> 23 #include <errno.h> 24 #include <poll.h> 25 #include <stdio.h> 26 #include <sys/eventfd.h> 27 #include <sys/stat.h> 28 #include <teeui/msg_formatting.h> 29 #include <trusty/tipc.h> 30 #include <unistd.h> 31 32 #include <fstream> 33 #include <functional> 34 #include <future> 35 #include <iostream> 36 #include <sstream> 37 #include <thread> 38 #include <vector> 39 40 #define AT __FILE__ ":" << __LINE__ << ": " 41 42 namespace android { 43 namespace trusty { 44 namespace confirmationui { 45 46 using ::teeui::Message; 47 using ::teeui::msg2tuple_t; 48 using ::teeui::ReadStream; 49 using ::teeui::WriteStream; 50 51 #ifndef TEEUI_USE_STD_VECTOR 52 /* 53 * TEEUI_USE_STD_VECTOR makes certain wire types like teeui::MsgString and 54 * teeui::MsgVector be aliases for std::vector. This is required for thread safe 55 * message serialization. Always compile this with -DTEEUI_USE_STD_VECTOR set in 56 * CFLAGS of the HAL service. 57 */ 58 #error "Must be compiled with -DTEEUI_USE_STD_VECTOR." 59 #endif 60 61 enum class TrustyAppError : int32_t { 62 OK, 63 ERROR = -1, 64 MSG_TOO_LONG = -2, 65 }; 66 67 class TrustyApp { 68 private: 69 android::base::unique_fd handle_; 70 void* shm_base_; 71 size_t shm_len_; 72 static constexpr const int kInvalidHandle = -1; 73 /* 74 * This mutex serializes communication with the trusted app, not handle_. 75 * Calling issueCmd during construction or deletion is undefined behavior. 76 */ 77 std::mutex mutex_; 78 79 public: 80 TrustyApp(const std::string& path, const std::string& appname); 81 ~TrustyApp(); 82 83 ssize_t TrustyRpc(const uint8_t* obegin, const uint8_t* oend, uint8_t* ibegin, uint8_t* iend); 84 85 template <typename Request, typename Response, typename... T> issueCmd(const T &...args)86 std::tuple<TrustyAppError, msg2tuple_t<Response>> issueCmd(const T&... args) { 87 std::lock_guard<std::mutex> lock(mutex_); 88 89 if (handle_ == kInvalidHandle) { 90 LOG(ERROR) << "TrustyApp not connected"; 91 return {TrustyAppError::ERROR, {}}; 92 } 93 94 uint8_t buffer[CONFIRMATIONUI_MAX_MSG_SIZE]; 95 WriteStream out(buffer); 96 97 out = write(Request(), out, args...); 98 if (!out) { 99 LOG(ERROR) << AT << "send command failed: message formatting"; 100 return {TrustyAppError::MSG_TOO_LONG, {}}; 101 } 102 103 auto rc = TrustyRpc(&buffer[0], const_cast<const uint8_t*>(out.pos()), &buffer[0], 104 &buffer[CONFIRMATIONUI_MAX_MSG_SIZE]); 105 if (rc < 0) return {TrustyAppError::ERROR, {}}; 106 107 ReadStream in(&buffer[0], rc); 108 auto result = read(Response(), in); 109 if (!std::get<0>(result)) { 110 LOG(ERROR) << "send command failed: message parsing"; 111 return {TrustyAppError::ERROR, {}}; 112 } 113 114 return {std::get<0>(result) ? TrustyAppError::OK : TrustyAppError::ERROR, 115 tuple_tail(std::move(result))}; 116 } 117 issueCmd(const T &...args)118 template <typename Request, typename... T> TrustyAppError issueCmd(const T&... args) { 119 std::lock_guard<std::mutex> lock(mutex_); 120 121 if (handle_ == kInvalidHandle) { 122 LOG(ERROR) << "TrustyApp not connected"; 123 return TrustyAppError::ERROR; 124 } 125 126 uint8_t buffer[CONFIRMATIONUI_MAX_MSG_SIZE]; 127 WriteStream out(buffer); 128 129 out = write(Request(), out, args...); 130 if (!out) { 131 LOG(ERROR) << AT << "send command failed: message formatting"; 132 return TrustyAppError::MSG_TOO_LONG; 133 } 134 135 auto rc = TrustyRpc(&buffer[0], const_cast<const uint8_t*>(out.pos()), &buffer[0], 136 &buffer[CONFIRMATIONUI_MAX_MSG_SIZE]); 137 if (rc < 0) { 138 LOG(ERROR) << "send command failed: " << strerror(errno) << " (" << errno << ")"; 139 return TrustyAppError::ERROR; 140 } 141 142 if (rc > 0) { 143 LOG(ERROR) << "Unexpected non zero length response"; 144 return TrustyAppError::ERROR; 145 } 146 return TrustyAppError::OK; 147 } 148 149 operator bool() const { return handle_ != kInvalidHandle; } 150 }; 151 152 } // namespace confirmationui 153 } // namespace trusty 154 } // namespace android 155