blob: 05a25f61deed548d83a1c6f8f8f6098a693fe596 [file] [log] [blame]
Janis Danisevskis8fe0cfb2020-01-13 14:24:32 -08001/*
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
39namespace android {
40namespace trusty {
41
42using ::teeui::Message;
43using ::teeui::msg2tuple_t;
44using ::teeui::ReadStream;
45using ::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
57enum 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 */
68static constexpr const size_t kSendBufferSize = 0x2000;
69
70ssize_t TrustyRpc(int handle, const uint8_t* obegin, const uint8_t* oend, uint8_t* ibegin,
71 uint8_t* iend);
72
73class 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>
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
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