blob: 134800278ea8b210bb4adefbce67fe2016cdb293 [file] [log] [blame]
/*
* Copyright (C) 2016-2017 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 <stdio.h>
#include <stdlib.h>
#include <trusty_ipc.h>
#include <uapi/err.h>
#include "caam.h"
#include "common.h"
#include "hwkey_srv_priv.h"
#include "hwrng_srv_priv.h"
#define TLOG_LVL TLOG_LVL_DEFAULT
#define TLOG_TAG "hwcrypto"
#include "tlog.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");
rc = init_caam_env();
if (rc != 0) {
TLOGE("CAAM init env failed (%d)!\n", rc);
return rc;
}
/* 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;
}