• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/list.h>
20 #include <stdint.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <trusty_ipc.h>
25 #include <uapi/err.h>
26 
27 #include <interface/hwrng/hwrng.h>
28 
29 #include "common.h"
30 #include "hwrng_srv_priv.h"
31 
32 #define TLOG_TAG "hwrng_srv"
33 #include <trusty_log.h>
34 
35 #define HWRNG_SRV_NAME HWRNG_PORT
36 #define MAX_HWRNG_MSG_SIZE 4096
37 
38 struct hwrng_chan_ctx {
39     tipc_event_handler_t evt_handler;
40     struct list_node node;
41     handle_t chan;
42     size_t req_size;
43     bool send_blocked;
44 };
45 
46 static void hwrng_port_handler(const uevent_t* ev, void* priv);
47 static void hwrng_chan_handler(const uevent_t* ev, void* priv);
48 
49 static handle_t hwrng_port = INVALID_IPC_HANDLE;
50 
51 static tipc_event_handler_t hwrng_port_evt_handler = {
52         .proc = hwrng_port_handler,
53 };
54 
55 static uint8_t rng_data[MAX_HWRNG_MSG_SIZE];
56 
57 static struct list_node hwrng_req_list = LIST_INITIAL_VALUE(hwrng_req_list);
58 
59 /****************************************************************************/
60 
61 /*
62  *  Hexdump content of memory region
63  */
_hexdump8(const void * ptr,size_t len)64 static void _hexdump8(const void* ptr, size_t len) {
65     uintptr_t address = (uintptr_t)ptr;
66     size_t count;
67     size_t i;
68 
69     for (count = 0; count < len; count += 16) {
70         fprintf(stderr, "0x%08" PRIxPTR ": ", address);
71         for (i = 0; i < MIN(len - count, 16); i++) {
72             fprintf(stderr, "0x%02hhx ", *(const uint8_t*)(address + i));
73         }
74         fprintf(stderr, "\n");
75         address += 16;
76     }
77 }
78 
79 /*
80  * Close specified HWRNG service channel
81  */
hwrng_close_chan(struct hwrng_chan_ctx * ctx)82 static void hwrng_close_chan(struct hwrng_chan_ctx* ctx) {
83     close(ctx->chan);
84 
85     if (list_in_list(&ctx->node))
86         list_delete(&ctx->node);
87 
88     free(ctx);
89 }
90 
91 /*
92  * Handle HWRNG request queue
93  */
hwrng_handle_req_queue(void)94 static bool hwrng_handle_req_queue(void) {
95     struct hwrng_chan_ctx* ctx;
96     struct hwrng_chan_ctx* temp;
97 
98     /* service channels */
99     bool need_more = false;
100 
101     /* for all pending requests */
102     list_for_every_entry_safe(&hwrng_req_list, ctx, temp, struct hwrng_chan_ctx,
103                               node) {
104         if (ctx->send_blocked)
105             continue; /* cant service it rignt now */
106 
107         size_t len = ctx->req_size;
108 
109         if (len > MAX_HWRNG_MSG_SIZE)
110             len = MAX_HWRNG_MSG_SIZE;
111 
112         /* get rng data */
113         hwrng_dev_get_rng_data(rng_data, len);
114 
115         /* send reply */
116         int rc = tipc_send_single_buf(ctx->chan, rng_data, len);
117         if (rc < 0) {
118             if (rc == ERR_NOT_ENOUGH_BUFFER) {
119                 /* mark it as send_blocked */
120                 ctx->send_blocked = true;
121             } else {
122                 /* just close HWRNG request channel */
123                 TLOGE("failed (%d) to send_reply\n", rc);
124                 hwrng_close_chan(ctx);
125             }
126             continue;
127         }
128 
129         ctx->req_size -= len;
130 
131         if (ctx->req_size == 0) {
132             /* remove it from pending list */
133             list_delete(&ctx->node);
134         } else {
135             need_more = true;
136         }
137     }
138 
139     return need_more;
140 }
141 
142 /*
143  * Check if we can handle request queue
144  */
hwrng_kick_req_queue(void)145 static void hwrng_kick_req_queue(void) {
146     hwrng_handle_req_queue();
147 }
148 
149 /*
150  *  Read and queue HWRNG request message
151  */
hwrng_chan_handle_msg(struct hwrng_chan_ctx * ctx)152 static int hwrng_chan_handle_msg(struct hwrng_chan_ctx* ctx) {
153     int rc;
154     struct hwrng_req req;
155 
156     assert(ctx);
157 
158     /* read request */
159     rc = tipc_recv_single_buf(ctx->chan, &req, sizeof(req));
160     if (rc != sizeof(req)) {
161         TLOGE("failed (%d) to receive msg for chan %d\n", rc, ctx->chan);
162         return rc;
163     }
164 
165     /* check if we already have request in progress */
166     if (list_in_list(&ctx->node)) {
167         /* extend it */
168         ctx->req_size += req.len;
169     } else {
170         /* queue it */
171         ctx->req_size = req.len;
172         list_add_tail(&hwrng_req_list, &ctx->node);
173     }
174 
175     return 0;
176 }
177 
178 /*
179  *  Channel handler where HWRNG requests are coming from
180  */
hwrng_chan_handler(const uevent_t * ev,void * priv)181 static void hwrng_chan_handler(const uevent_t* ev, void* priv) {
182     struct hwrng_chan_ctx* ctx = priv;
183 
184     assert(ctx);
185     assert(ev->handle == ctx->chan);
186 
187     tipc_handle_chan_errors(ev);
188 
189     if (ev->event & IPC_HANDLE_POLL_HUP) {
190         hwrng_close_chan(ctx);
191     } else {
192         if (ev->event & IPC_HANDLE_POLL_SEND_UNBLOCKED) {
193             ctx->send_blocked = false;
194         }
195 
196         if (ev->event & IPC_HANDLE_POLL_MSG) {
197             int rc = hwrng_chan_handle_msg(ctx);
198             if (rc) {
199                 hwrng_close_chan(ctx);
200             }
201         }
202     }
203 
204     /* kick state machine */
205     hwrng_kick_req_queue();
206 }
207 
208 /*
209  * Port were HWRNG requests are coming from
210  */
hwrng_port_handler(const uevent_t * ev,void * priv)211 static void hwrng_port_handler(const uevent_t* ev, void* priv) {
212     uuid_t peer_uuid;
213 
214     tipc_handle_port_errors(ev);
215 
216     if (ev->event & IPC_HANDLE_POLL_READY) {
217         handle_t chan;
218 
219         /* incoming connection: accept it */
220         int rc = accept(ev->handle, &peer_uuid);
221         if (rc < 0) {
222             TLOGE("failed (%d) to accept on port %d\n", rc, ev->handle);
223             return;
224         }
225         chan = (handle_t)rc;
226 
227         /* allocate state */
228         struct hwrng_chan_ctx* ctx = calloc(1, sizeof(*ctx));
229         if (!ctx) {
230             TLOGE("failed to alloc state for chan %d\n", chan);
231             close(chan);
232             return;
233         }
234 
235         /* init channel state */
236         ctx->evt_handler.priv = ctx;
237         ctx->evt_handler.proc = hwrng_chan_handler;
238         ctx->chan = chan;
239 
240         /* attach channel handler */
241         rc = set_cookie(chan, &ctx->evt_handler);
242         if (rc) {
243             TLOGE("failed (%d) to set_cookie on chan %d\n", rc, chan);
244             free(ctx);
245             close(chan);
246             return;
247         }
248     }
249 }
250 
251 /*
252  *  Initialize HWRNG services
253  */
hwrng_start_service(void)254 int hwrng_start_service(void) {
255     int rc;
256 
257     TLOGD("Start HWRNG service\n");
258 
259     /* create HWRNG port */
260     rc = port_create(HWRNG_SRV_NAME, 1, MAX_HWRNG_MSG_SIZE,
261                      IPC_PORT_ALLOW_TA_CONNECT);
262     if (rc < 0) {
263         TLOGE("Failed (%d) to create port '%s'\n", rc, HWRNG_SRV_NAME);
264         return rc;
265     } else {
266         hwrng_port = (handle_t)rc;
267         set_cookie(hwrng_port, &hwrng_port_evt_handler);
268     }
269 
270     return NO_ERROR;
271 }
272