| /* |
| * Copyright (C) 2016 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| |
| #include <assert.h> |
| #include <err.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| |
| #include <trusty_std.h> |
| |
| |
| #define LOCAL_TRACE 1 |
| #define LOG_TAG "hwcrypto_srv" |
| |
| #include "common.h" |
| #include "hwrng_srv_priv.h" |
| #include "hwkey_srv_priv.h" |
| |
| |
| /* |
| * Hexdump content of memory region |
| */ |
| void _hexdump8(const void *ptr, size_t len) |
| { |
| addr_t address = (addr_t)ptr; |
| size_t count; |
| size_t i; |
| |
| for (count = 0 ; count < len; count += 16) { |
| fprintf(stderr, "0x%08lx: ", address); |
| for (i=0; i < MIN(len - count, 16); i++) { |
| fprintf(stderr, "0x%02hhx ", *(const uint8_t *)(address + i)); |
| } |
| fprintf(stderr, "\n"); |
| address += 16; |
| } |
| } |
| |
| |
| /* |
| * Handle common unexpected port events |
| */ |
| void tipc_handle_port_errors(const uevent_t *ev) |
| { |
| if ((ev->event & IPC_HANDLE_POLL_ERROR) || |
| (ev->event & IPC_HANDLE_POLL_HUP) || |
| (ev->event & IPC_HANDLE_POLL_MSG) || |
| (ev->event & IPC_HANDLE_POLL_SEND_UNBLOCKED)) { |
| /* should never happen with port handles */ |
| TLOGE("error event (0x%x) for port (%d)\n", |
| ev->event, ev->handle); |
| abort(); |
| } |
| } |
| |
| /* |
| * Handle common unexpected channel events |
| */ |
| void tipc_handle_chan_errors(const uevent_t *ev) |
| { |
| if ((ev->event & IPC_HANDLE_POLL_ERROR) || |
| (ev->event & IPC_HANDLE_POLL_READY)) { |
| /* close it as it is in an error state */ |
| TLOGE("error event (0x%x) for chan (%d)\n", |
| ev->event, ev->handle); |
| abort(); |
| } |
| } |
| |
| /* |
| * Send single buf message |
| */ |
| int tipc_send_single_buf(handle_t chan, const void *buf, size_t len) |
| { |
| iovec_t iov = { |
| .base = (void *)buf, |
| .len = len, |
| }; |
| ipc_msg_t msg = { |
| .iov = &iov, |
| .num_iov = 1, |
| |
| }; |
| return send_msg(chan, &msg); |
| } |
| |
| /* |
| * Receive single buf message |
| */ |
| int tipc_recv_single_buf(handle_t chan, void *buf, size_t len) |
| { |
| int rc; |
| ipc_msg_info_t msg_inf; |
| |
| rc = get_msg(chan, &msg_inf); |
| if (rc) |
| return rc; |
| |
| if (msg_inf.len != len) { |
| /* unexpected msg size */ |
| rc = ERR_BAD_LEN; |
| } else { |
| iovec_t iov = { |
| .base = buf, |
| .len = len, |
| }; |
| ipc_msg_t msg = { |
| .iov = &iov, |
| .num_iov = 1, |
| }; |
| rc = read_msg(chan, msg_inf.id, 0, &msg); |
| } |
| |
| put_msg(chan, msg_inf.id); |
| return rc; |
| } |
| |
| /* |
| * Send message consisting of two segments (header and payload) |
| */ |
| int tipc_send_two_segments(handle_t chan, const void *hdr, size_t hdr_len, |
| const void *payload, size_t payload_len) |
| { |
| iovec_t iovs[2] = { |
| { |
| .base = (void *)hdr, |
| .len = hdr_len, |
| }, |
| { |
| .base = (void *)payload, |
| .len = payload_len, |
| }, |
| }; |
| ipc_msg_t msg = { |
| .iov = iovs, |
| .num_iov = countof(iovs), |
| }; |
| return send_msg(chan, &msg); |
| } |
| |
| /* |
| * Receive message consisting of two segments (header and payload). |
| */ |
| int tipc_recv_two_segments(handle_t chan, void *hdr, size_t hdr_len, |
| void *payload, size_t payload_len) |
| { |
| int rc; |
| ipc_msg_info_t msg_inf; |
| |
| rc = get_msg(chan, &msg_inf); |
| if (rc) |
| return rc; |
| |
| if (msg_inf.len < hdr_len) { |
| /* unexpected msg size */ |
| rc = ERR_BAD_LEN; |
| } else { |
| iovec_t iovs[2] = { |
| { |
| .base = hdr, |
| .len = hdr_len, |
| }, |
| { |
| .base = payload, |
| .len = payload_len, |
| } |
| }; |
| ipc_msg_t msg = { |
| .iov = iovs, |
| .num_iov = countof(iovs), |
| }; |
| rc = read_msg(chan, msg_inf.id, 0, &msg); |
| } |
| |
| put_msg(chan, msg_inf.id); |
| return rc; |
| } |
| |
| /* |
| * Dispatch event |
| */ |
| static void dispatch_event(const uevent_t *ev) |
| { |
| assert(ev); |
| |
| if (ev->event == IPC_HANDLE_POLL_NONE) { |
| /* not really an event, do nothing */ |
| TLOGI("got an empty event\n"); |
| return; |
| } |
| |
| /* check if we have handler */ |
| struct tipc_event_handler *handler = ev->cookie; |
| if (handler && handler->proc) { |
| /* invoke it */ |
| handler->proc(ev, handler->priv); |
| return; |
| } |
| |
| /* no handler? close it */ |
| TLOGE("no handler for event (0x%x) with handle %d\n", |
| ev->event, ev->handle); |
| |
| close(ev->handle); |
| |
| return; |
| } |
| |
| /* |
| * Main application event loop |
| */ |
| int main(void) |
| { |
| int rc; |
| uevent_t event; |
| |
| TLOGI("Initializing\n"); |
| |
| /* initialize service providers */ |
| hwrng_init_srv_provider(); |
| hwkey_init_srv_provider(); |
| |
| TLOGI("enter main event loop\n"); |
| |
| /* enter main event loop */ |
| while (true) { |
| event.handle = INVALID_IPC_HANDLE; |
| event.event = 0; |
| event.cookie = NULL; |
| |
| rc = wait_any(&event, -1); |
| if (rc < 0) { |
| TLOGE("wait_any failed (%d)\n", rc); |
| break; |
| } |
| |
| if (rc == NO_ERROR) { /* got an event */ |
| dispatch_event(&event); |
| } |
| } |
| |
| return rc; |
| } |