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 <android-base/logging.h> 20 #include <errno.h> 21 #include <poll.h> 22 #include <stdio.h> 23 #include <sys/eventfd.h> 24 #include <sys/stat.h> 25 #include <teeui/msg_formatting.h> 26 #include <trusty/tipc.h> 27 #include <unistd.h> 28 29 #include <fstream> 30 #include <functional> 31 #include <future> 32 #include <iostream> 33 #include <sstream> 34 #include <thread> 35 #include <vector> 36 37 #define AT __FILE__ ":" << __LINE__ << ": " 38 39 namespace android { 40 namespace trusty { 41 42 using ::teeui::Message; 43 using ::teeui::msg2tuple_t; 44 using ::teeui::ReadStream; 45 using ::teeui::WriteStream; 46 47 #ifndef TEEUI_USE_STD_VECTOR 48 /* 49 * TEEUI_USE_STD_VECTOR makes certain wire types like teeui::MsgString and 50 * teeui::MsgVector be aliases for std::vector. This is required for thread safe 51 * message serialization. Always compile this with -DTEEUI_USE_STD_VECTOR set in 52 * CFLAGS of the HAL service. 53 */ 54 #error "Must be compiled with -DTEEUI_USE_STD_VECTOR." 55 #endif 56 57 enum class TrustyAppError : int32_t { 58 OK, 59 ERROR = -1, 60 MSG_TOO_LONG = -2, 61 }; 62 63 /* 64 * There is a hard limitation of 0x1800 bytes for the to-be-signed message size. The protocol 65 * overhead is limited, so that 0x2000 is a buffer size that will be sufficient in any benign 66 * mode of operation. 67 */ 68 static constexpr const size_t kSendBufferSize = 0x2000; 69 70 ssize_t TrustyRpc(int handle, const uint8_t* obegin, const uint8_t* oend, uint8_t* ibegin, 71 uint8_t* iend); 72 73 class TrustyApp { 74 private: 75 int handle_; 76 static constexpr const int kInvalidHandle = -1; 77 /* 78 * This mutex serializes communication with the trusted app, not handle_. 79 * Calling issueCmd during construction or deletion is undefined behavior. 80 */ 81 std::mutex mutex_; 82 83 public: 84 TrustyApp(const std::string& path, const std::string& appname); 85 ~TrustyApp(); 86 87 template <typename Request, typename Response, typename... T> issueCmd(const T &...args)88 std::tuple<TrustyAppError, msg2tuple_t<Response>> issueCmd(const T&... args) { 89 std::lock_guard<std::mutex> lock(mutex_); 90 91 if (handle_ == kInvalidHandle) { 92 LOG(ERROR) << "TrustyApp not connected"; 93 return {TrustyAppError::ERROR, {}}; 94 } 95 96 uint8_t buffer[kSendBufferSize]; 97 WriteStream out(buffer); 98 99 out = write(Request(), out, args...); 100 if (!out) { 101 LOG(ERROR) << AT << "send command failed: message formatting"; 102 return {TrustyAppError::MSG_TOO_LONG, {}}; 103 } 104 105 auto rc = TrustyRpc(handle_, &buffer[0], const_cast<const uint8_t*>(out.pos()), &buffer[0], 106 &buffer[kSendBufferSize]); 107 if (rc < 0) return {TrustyAppError::ERROR, {}}; 108 109 ReadStream in(&buffer[0], rc); 110 auto result = read(Response(), in); 111 if (!std::get<0>(result)) { 112 LOG(ERROR) << "send command failed: message parsing"; 113 return {TrustyAppError::ERROR, {}}; 114 } 115 116 return {std::get<0>(result) ? TrustyAppError::OK : TrustyAppError::ERROR, 117 tuple_tail(std::move(result))}; 118 } 119 issueCmd(const T &...args)120 template <typename Request, typename... T> TrustyAppError issueCmd(const T&... args) { 121 std::lock_guard<std::mutex> lock(mutex_); 122 123 if (handle_ == kInvalidHandle) { 124 LOG(ERROR) << "TrustyApp not connected"; 125 return TrustyAppError::ERROR; 126 } 127 128 uint8_t buffer[kSendBufferSize]; 129 WriteStream out(buffer); 130 131 out = write(Request(), out, args...); 132 if (!out) { 133 LOG(ERROR) << AT << "send command failed: message formatting"; 134 return TrustyAppError::MSG_TOO_LONG; 135 } 136 137 auto rc = TrustyRpc(handle_, &buffer[0], const_cast<const uint8_t*>(out.pos()), &buffer[0], 138 &buffer[kSendBufferSize]); 139 if (rc < 0) { 140 LOG(ERROR) << "send command failed: " << strerror(errno) << " (" << errno << ")"; 141 return TrustyAppError::ERROR; 142 } 143 144 if (rc > 0) { 145 LOG(ERROR) << "Unexpected non zero length response"; 146 return TrustyAppError::ERROR; 147 } 148 return TrustyAppError::OK; 149 } 150 151 operator bool() const { return handle_ != kInvalidHandle; } 152 }; 153 154 } // namespace trusty 155 } // namespace android 156