• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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