1 /*
2 * Copyright (C) 2016-2017 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 <assert.h>
18 #include <inttypes.h>
19 #include <lk/macros.h>
20 #include <stdint.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <trusty_ipc.h>
24 #include <uapi/err.h>
25
26 #include "caam.h"
27 #include "common.h"
28 #include "hwkey_srv_priv.h"
29 #include "hwrng_srv_priv.h"
30
31 #define TLOG_TAG "hwcrypto"
32 #include <trusty_log.h>
33
34 /*
35 * Hexdump content of memory region
36 */
_hexdump8(const void * ptr,size_t len)37 void _hexdump8(const void* ptr, size_t len) {
38 uintptr_t address = (uintptr_t)ptr;
39 size_t count;
40 size_t i;
41
42 for (count = 0; count < len; count += 16) {
43 fprintf(stderr, "0x%08" PRIxPTR ": ", address);
44 for (i = 0; i < MIN(len - count, 16); i++) {
45 fprintf(stderr, "0x%02hhx ", *(const uint8_t*)(address + i));
46 }
47 fprintf(stderr, "\n");
48 address += 16;
49 }
50 }
51
52 /*
53 * Handle common unexpected port events
54 */
tipc_handle_port_errors(const uevent_t * ev)55 void tipc_handle_port_errors(const uevent_t* ev) {
56 if ((ev->event & IPC_HANDLE_POLL_ERROR) ||
57 (ev->event & IPC_HANDLE_POLL_HUP) ||
58 (ev->event & IPC_HANDLE_POLL_MSG) ||
59 (ev->event & IPC_HANDLE_POLL_SEND_UNBLOCKED)) {
60 /* should never happen with port handles */
61 TLOGE("error event (0x%x) for port (%d)\n", ev->event, ev->handle);
62 abort();
63 }
64 }
65
66 /*
67 * Handle common unexpected channel events
68 */
tipc_handle_chan_errors(const uevent_t * ev)69 void tipc_handle_chan_errors(const uevent_t* ev) {
70 if ((ev->event & IPC_HANDLE_POLL_ERROR) ||
71 (ev->event & IPC_HANDLE_POLL_READY)) {
72 /* close it as it is in an error state */
73 TLOGE("error event (0x%x) for chan (%d)\n", ev->event, ev->handle);
74 abort();
75 }
76 }
77
78 /*
79 * Send single buf message
80 */
tipc_send_single_buf(handle_t chan,const void * buf,size_t len)81 int tipc_send_single_buf(handle_t chan, const void* buf, size_t len) {
82 struct iovec iov = {
83 .iov_base = (void*)buf,
84 .iov_len = len,
85 };
86 ipc_msg_t msg = {
87 .iov = &iov,
88 .num_iov = 1,
89
90 };
91 return send_msg(chan, &msg);
92 }
93
94 /*
95 * Receive single buf message
96 */
tipc_recv_single_buf(handle_t chan,void * buf,size_t len)97 int tipc_recv_single_buf(handle_t chan, void* buf, size_t len) {
98 int rc;
99 ipc_msg_info_t msg_inf;
100
101 rc = get_msg(chan, &msg_inf);
102 if (rc)
103 return rc;
104
105 if (msg_inf.len != len) {
106 /* unexpected msg size */
107 rc = ERR_BAD_LEN;
108 } else {
109 struct iovec iov = {
110 .iov_base = buf,
111 .iov_len = len,
112 };
113 ipc_msg_t msg = {
114 .iov = &iov,
115 .num_iov = 1,
116 };
117 rc = read_msg(chan, msg_inf.id, 0, &msg);
118 }
119
120 put_msg(chan, msg_inf.id);
121 return rc;
122 }
123
124 /*
125 * Send message consisting of two segments (header and payload)
126 */
tipc_send_two_segments(handle_t chan,const void * hdr,size_t hdr_len,const void * payload,size_t payload_len)127 int tipc_send_two_segments(handle_t chan,
128 const void* hdr,
129 size_t hdr_len,
130 const void* payload,
131 size_t payload_len) {
132 struct iovec iovs[2] = {
133 {
134 .iov_base = (void*)hdr,
135 .iov_len = hdr_len,
136 },
137 {
138 .iov_base = (void*)payload,
139 .iov_len = payload_len,
140 },
141 };
142 ipc_msg_t msg = {
143 .iov = iovs,
144 .num_iov = countof(iovs),
145 };
146 return send_msg(chan, &msg);
147 }
148
149 /*
150 * Receive message consisting of two segments (header and payload).
151 */
tipc_recv_two_segments(handle_t chan,void * hdr,size_t hdr_len,void * payload,size_t payload_len)152 int tipc_recv_two_segments(handle_t chan,
153 void* hdr,
154 size_t hdr_len,
155 void* payload,
156 size_t payload_len) {
157 int rc;
158 ipc_msg_info_t msg_inf;
159
160 rc = get_msg(chan, &msg_inf);
161 if (rc)
162 return rc;
163
164 if (msg_inf.len < hdr_len) {
165 /* unexpected msg size */
166 rc = ERR_BAD_LEN;
167 } else {
168 struct iovec iovs[2] = {{
169 .iov_base = hdr,
170 .iov_len = hdr_len,
171 },
172 {
173 .iov_base = payload,
174 .iov_len = payload_len,
175 }};
176 ipc_msg_t msg = {
177 .iov = iovs,
178 .num_iov = countof(iovs),
179 };
180 rc = read_msg(chan, msg_inf.id, 0, &msg);
181 }
182
183 put_msg(chan, msg_inf.id);
184 return rc;
185 }
186
187 /*
188 * Dispatch event
189 */
dispatch_event(const uevent_t * ev)190 static void dispatch_event(const uevent_t* ev) {
191 assert(ev);
192
193 if (ev->event == IPC_HANDLE_POLL_NONE) {
194 /* not really an event, do nothing */
195 TLOGI("got an empty event\n");
196 return;
197 }
198
199 /* check if we have handler */
200 struct tipc_event_handler* handler = ev->cookie;
201 if (handler && handler->proc) {
202 /* invoke it */
203 handler->proc(ev, handler->priv);
204 return;
205 }
206
207 /* no handler? close it */
208 TLOGE("no handler for event (0x%x) with handle %d\n", ev->event,
209 ev->handle);
210
211 close(ev->handle);
212
213 return;
214 }
215
216 /*
217 * Main application event loop
218 */
main(void)219 int main(void) {
220 int rc;
221 uevent_t event;
222
223 TLOGD("Initializing\n");
224
225 rc = init_caam_env();
226 if (rc != 0) {
227 TLOGE("CAAM init env failed (%d)!\n", rc);
228 return rc;
229 }
230
231 /* initialize service providers */
232 hwrng_init_srv_provider();
233 hwkey_init_srv_provider();
234
235 TLOGD("enter main event loop\n");
236
237 /* enter main event loop */
238 while (true) {
239 event.handle = INVALID_IPC_HANDLE;
240 event.event = 0;
241 event.cookie = NULL;
242
243 rc = wait_any(&event, -1);
244 if (rc < 0) {
245 TLOGE("wait_any failed (%d)\n", rc);
246 break;
247 }
248
249 if (rc == NO_ERROR) { /* got an event */
250 dispatch_event(&event);
251 }
252 }
253
254 return rc;
255 }
256