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