1 /*
2  * Copyright 2016 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 #include <UniquePtr.h>
18 #include <trusty_ipc.h>
19 #include <uapi/err.h>
20 
21 #include "avb_ipc.h"
22 #include "avb_manager.h"
23 #include "secure_storage.h"
24 
25 const char kAvbServiceName[] = "com.android.trusty.avb";
26 const int kAvbServiceNumBufs = 1;
27 const int kAvbServiceBufSize = 2048;
28 const uint32_t kAvbServiceFlags = IPC_PORT_ALLOW_NS_CONNECT;
29 static bool boot_state_locked = false;
30 
31 avb::AvbManager* g_avb_manager;
32 
33 namespace avb {
34 
35 // Deserializes request in |in_buf|, calls |operation| to execute request,
36 // and serializes response to |out_buf|. Returns a Trusty error code if there
37 // is a problem during serializing the response or deserializing the request.
38 template <typename Request, typename Response>
ExecuteCommand(void (AvbManager::* operation)(const Request &,Response *),const uint8_t * in_buf,uint32_t in_size,UniquePtr<uint8_t[]> * out_buf,uint32_t * out_size,AvbError * error)39 static int ExecuteCommand(void (AvbManager::*operation)(const Request&,
40                                                         Response*),
41                           const uint8_t* in_buf,
42                           uint32_t in_size,
43                           UniquePtr<uint8_t[]>* out_buf,
44                           uint32_t* out_size,
45                           AvbError* error) {
46     Request req;
47     int rc = req.Deserialize(in_buf, in_buf + in_size);
48     if (rc < 0) {
49         TLOGE("Error deserializing request: %d\n", rc);
50         return rc;
51     }
52     Response rsp;
53     (g_avb_manager->*operation)(req, &rsp);
54 
55     *error = rsp.get_error();
56     *out_size = rsp.GetSerializedSize();
57     if (*out_size > kAvbServiceBufSize) {
58         TLOGE("Response size too large: %d\n", *out_size);
59         *out_size = 0;
60         return ERR_TOO_BIG;
61     }
62 
63     if (*out_size == 0) {
64         return NO_ERROR;
65     }
66 
67     out_buf->reset(new uint8_t[*out_size]);
68     if (out_buf->get() == nullptr) {
69         *out_size = 0;
70         return ERR_NO_MEMORY;
71     }
72 
73     if (rsp.Serialize(out_buf->get(), out_buf->get() + *out_size) !=
74         *out_size) {
75         TLOGE("Error serializing response message\n");
76         return ERR_NOT_VALID;
77     }
78 
79     return NO_ERROR;
80 }
81 
82 // Dispatches command |cmd|. Fulfills request in |in_buf|, and writes response
83 // to |out_buf|. Returns a Trusty error code if there is a problem serializing
84 // the response or deserializing the request. Avb specific errors are put in
85 // |error|.
ProcessRequest(uint32_t cmd,const uint8_t * in_buf,uint32_t in_size,UniquePtr<uint8_t[]> * out_buf,uint32_t * out_size,AvbError * error)86 static int ProcessRequest(uint32_t cmd,
87                           const uint8_t* in_buf,
88                           uint32_t in_size,
89                           UniquePtr<uint8_t[]>* out_buf,
90                           uint32_t* out_size,
91                           AvbError* error) {
92     if (boot_state_locked) {
93         switch (cmd) {
94         case WRITE_ROLLBACK_INDEX:
95         case WRITE_PERMANENT_ATTRIBUTES:
96         case WRITE_LOCK_STATE:
97             *out_size = 0;
98             *error = AvbError::kInvalid;
99             return NO_ERROR;
100         }
101     }
102     switch (cmd) {
103     case READ_ROLLBACK_INDEX:
104         return ExecuteCommand(&AvbManager::ReadRollbackIndex, in_buf, in_size,
105                               out_buf, out_size, error);
106     case WRITE_ROLLBACK_INDEX:
107         return ExecuteCommand(&AvbManager::WriteRollbackIndex, in_buf, in_size,
108                               out_buf, out_size, error);
109     case AVB_GET_VERSION:
110         return ExecuteCommand(&AvbManager::GetVersion, in_buf, in_size, out_buf,
111                               out_size, error);
112     case READ_PERMANENT_ATTRIBUTES:
113         return ExecuteCommand(&AvbManager::ReadPermanentAttributes, in_buf,
114                               in_size, out_buf, out_size, error);
115     case WRITE_PERMANENT_ATTRIBUTES:
116         return ExecuteCommand(&AvbManager::WritePermanentAttributes, in_buf,
117                               in_size, out_buf, out_size, error);
118     case READ_LOCK_STATE:
119         return ExecuteCommand(&AvbManager::ReadLockState, in_buf, in_size,
120                               out_buf, out_size, error);
121     case WRITE_LOCK_STATE:
122         return ExecuteCommand(&AvbManager::WriteLockState, in_buf, in_size,
123                               out_buf, out_size, error);
124     case LOCK_BOOT_STATE:
125         *out_size = 0;
126         *error = AvbError::kNone;
127         boot_state_locked = true;
128         return NO_ERROR;
129 
130     default:
131         return ERR_NOT_VALID;
132     }
133 }
134 
135 // Reads the message described by |msg_info| from channel and processes it.
136 // Writes the response message back to |channel|. Returns a Trusty error code if
137 // there is any I/O problem.
ProcessOneMessage(handle_t channel,const ipc_msg_info_t & msg_info)138 static int ProcessOneMessage(handle_t channel, const ipc_msg_info_t& msg_info) {
139     if (msg_info.len > kAvbServiceBufSize) {
140         TLOGE("Message too large on channel %x: %zu", channel, msg_info.len);
141         return ERR_TOO_BIG;
142     }
143     UniquePtr<uint8_t[]> msg_buf(new uint8_t[msg_info.len]);
144 
145     struct iovec request_iov = {msg_buf.get(), msg_info.len};
146     ipc_msg_t request_msg = {
147             1,             // number of iovecs
148             &request_iov,  // iovecs pointer
149             0,             // number of handles
150             nullptr        // handles pointer
151     };
152 
153     int rc = read_msg(channel, msg_info.id, 0, &request_msg);
154 
155     if (rc < 0) {
156         TLOGE("Failed to read msg for channel %x: %d\n", channel, rc);
157         return rc;
158     }
159 
160     if (((size_t)rc) < sizeof(avb_message)) {
161         TLOGE("Invalid message of size %zu for channel %x\n", (size_t)rc,
162               channel);
163         return ERR_NOT_VALID;
164     }
165 
166     // Parse and handle request
167     avb_message* avb_request_header =
168             reinterpret_cast<struct avb_message*>(msg_buf.get());
169     UniquePtr<uint8_t[]> out_buf;
170     uint32_t out_size = 0;
171     AvbError error;
172     rc = ProcessRequest(avb_request_header->cmd, avb_request_header->payload,
173                         msg_info.len - sizeof(avb_message), &out_buf, &out_size,
174                         &error);
175     if (rc < 0) {
176         TLOGE("Unable to handle request: %d", rc);
177         return rc;
178     }
179 
180     // Send response message back to caller
181     avb_message avb_response_header = {
182             .cmd = avb_request_header->cmd | AVB_RESP_BIT,
183             .result = error,
184             .payload = {},
185     };
186     struct iovec response_iov[2] = {
187             {&avb_response_header, sizeof(avb_response_header)},
188             {out_buf.get(), out_size},
189     };
190     ipc_msg_t response_msg = {
191             2,             // number of iovecs
192             response_iov,  // iovecs pointer
193             0,             // number of handles
194             nullptr        // handles pointer
195     };
196     rc = send_msg(channel, &response_msg);
197     if (rc < 0) {
198         TLOGE("Failed to send_msg on channel %x: %d\n", channel, rc);
199         return rc;
200     }
201     return NO_ERROR;
202 }
203 
204 // Receives all pending messages from |channel| and processes them, sending
205 // responses as appropriate. Returns a Trusty error code if there is a
206 // problem with message processing or I/O.
ProcessMessages(handle_t channel)207 static int ProcessMessages(handle_t channel) {
208     while (true) {
209         ipc_msg_info_t msg_info;
210         int rc = get_msg(channel, &msg_info);
211         if (rc == ERR_NO_MSG) {
212             break;
213         }
214 
215         if (rc != NO_ERROR) {
216             TLOGE("Failed to get_msg on channel %x: %d\n", channel, rc);
217             return rc;
218         }
219 
220         rc = ProcessOneMessage(channel, msg_info);
221         if (rc != NO_ERROR) {
222             put_msg(channel, msg_info.id);
223             return rc;
224         }
225 
226         rc = put_msg(channel, msg_info.id);
227         if (rc != NO_ERROR) {
228             TLOGE("Failed to put_msg on channel %x: %d\n", rc, channel);
229             return rc;
230         }
231     }
232 
233     return NO_ERROR;
234 }
235 
236 // Handles an |event| on a channel. If it is an incoming message, it is
237 // processed. Otherwise, the event indicates a channel hangup or error, so
238 // the channel is closed.
HandleChannelEvent(const uevent_t & event)239 static void HandleChannelEvent(const uevent_t& event) {
240     if ((event.event & IPC_HANDLE_POLL_ERROR) ||
241         (event.event & IPC_HANDLE_POLL_READY)) {
242         // close it as it is in an error state
243         TLOGE("Error event on channel %x: 0x%x\n", event.event, event.handle);
244         close(event.handle);
245     }
246 
247     if (event.event & IPC_HANDLE_POLL_HUP) {
248         // closed by peer
249         close(event.handle);
250         return;
251     }
252 
253     if (event.event & IPC_HANDLE_POLL_MSG) {
254         if (ProcessMessages(event.handle) != NO_ERROR) {
255             close(event.handle);
256         }
257     }
258 }
259 
260 // Handles an |event| on a port. If it is an incoming connection event,
261 // the connection is accepted. Any other event is unexpected.
HandlePortEvent(const uevent_t & event)262 static void HandlePortEvent(const uevent_t& event) {
263     if (event.event & IPC_HANDLE_POLL_READY) {
264         // incoming connection: accept it
265         uuid_t peer_uuid;
266         int rc = accept(event.handle, &peer_uuid);
267         if (rc < 0) {
268             TLOGE("Failed to accept on port %d: %d\n", event.handle, rc);
269         }
270     } else {
271         TLOGE("Unexpected event on port %d: 0x%x\n", event.handle, event.event);
272     }
273 }
274 
275 }  // namespace avb
276 
main(void)277 int main(void) {
278     avb::AvbManager avb_manager(new avb::SecureStorage);
279     g_avb_manager = &avb_manager;
280 
281     TLOGD("Initializing AVB App\n");
282 
283     int rc = port_create(kAvbServiceName, kAvbServiceNumBufs,
284                          kAvbServiceBufSize, kAvbServiceFlags);
285     if (rc < 0) {
286         TLOGE("Failed to initialize AVB app: %d", rc);
287         return rc;
288     }
289 
290     handle_t port = static_cast<handle_t>(rc);
291 
292     // enter main event loop
293     while (true) {
294         uevent_t event;
295         event.handle = INVALID_IPC_HANDLE;
296         event.event = 0;
297         event.cookie = nullptr;
298         rc = wait_any(&event, INFINITE_TIME);
299 
300         if (rc == NO_ERROR) {  // got an event
301             if (event.handle == port) {
302                 avb::HandlePortEvent(event);
303             } else {
304                 avb::HandleChannelEvent(event);
305             }
306         } else {
307             TLOGE("wait_any failed: %d\n", rc);
308         }
309     }
310 
311     g_avb_manager = nullptr;
312     return 0;
313 }
314