blob: 86100d07d9732b1d53f7b398d935f96232c8c2c4 [file] [log] [blame]
#include <BpCastAuth.h>
int BpCastAuth::ProvisionKey(const ::tidl::Payload& req_payload) {
if (!mChan.ok()) {
return ERR_INVALID_ARGS;
}
::tidl::RequestHeader req_hdr = {
.cmd = CMD_ProvisionKey,
};
Request_ProvisionKey req = {};
constexpr uint32_t req_num_handles =
::tidl::HandleOps<Request_ProvisionKey>::num_handles;
::tidl::Handle req_handles[req_num_handles];
::tidl::Handle* hptr = req_handles;
req.send_handles(hptr);
assert(hptr == &req_handles[req_num_handles]);
int rc =
::tidl::ipc::send(mChan.get(), &req_hdr, sizeof(req_hdr), &req,
sizeof(req), req_payload.data(),
req_payload.size(), req_handles, req_num_handles);
if (rc < 0) {
return rc;
}
if (static_cast<size_t>(rc) !=
sizeof(req_hdr) + sizeof(req) +
static_cast<size_t>(req_payload.size())) {
return ERR_BAD_LEN;
}
rc = ::tidl::ipc::wait_for_msg(mChan.get());
if (rc != NO_ERROR) {
return rc;
}
::tidl::ResponseHeader resp_hdr;
rc = ::tidl::ipc::recv(mChan.get(), sizeof(resp_hdr), &resp_hdr,
sizeof(resp_hdr), nullptr, 0);
if (rc < 0) {
return rc;
}
if (static_cast<size_t>(rc) < sizeof(resp_hdr)) {
return ERR_BAD_LEN;
}
if (resp_hdr.cmd != (CMD_ProvisionKey | RESP_BIT)) {
return ERR_CMD_UNKNOWN;
}
if (resp_hdr.rc != NO_ERROR) {
if (static_cast<size_t>(rc) != sizeof(resp_hdr)) {
return ERR_BAD_LEN;
}
return resp_hdr.rc;
}
if (static_cast<size_t>(rc) != sizeof(resp_hdr)) {
return ERR_BAD_LEN;
}
return NO_ERROR;
}
int BpCastAuth::SignHash(const ::tidl::Payload& req_payload,
::tidl::Payload* resp_payload) {
if (!mChan.ok()) {
return ERR_INVALID_ARGS;
}
::tidl::RequestHeader req_hdr = {
.cmd = CMD_SignHash,
.resp_payload_size = resp_payload->size(),
};
Request_SignHash req = {};
constexpr uint32_t req_num_handles =
::tidl::HandleOps<Request_SignHash>::num_handles;
::tidl::Handle req_handles[req_num_handles];
::tidl::Handle* hptr = req_handles;
req.send_handles(hptr);
assert(hptr == &req_handles[req_num_handles]);
int rc =
::tidl::ipc::send(mChan.get(), &req_hdr, sizeof(req_hdr), &req,
sizeof(req), req_payload.data(),
req_payload.size(), req_handles, req_num_handles);
if (rc < 0) {
return rc;
}
if (static_cast<size_t>(rc) !=
sizeof(req_hdr) + sizeof(req) +
static_cast<size_t>(req_payload.size())) {
return ERR_BAD_LEN;
}
rc = ::tidl::ipc::wait_for_msg(mChan.get());
if (rc != NO_ERROR) {
return rc;
}
::tidl::ResponseHeader resp_hdr;
rc = ::tidl::ipc::recv(mChan.get(), sizeof(resp_hdr), &resp_hdr,
sizeof(resp_hdr), resp_payload->data(),
resp_payload->size(), nullptr, 0);
if (rc < 0) {
return rc;
}
if (static_cast<size_t>(rc) < sizeof(resp_hdr)) {
return ERR_BAD_LEN;
}
if (resp_hdr.cmd != (CMD_SignHash | RESP_BIT)) {
return ERR_CMD_UNKNOWN;
}
if (resp_hdr.rc != NO_ERROR) {
if (static_cast<size_t>(rc) != sizeof(resp_hdr)) {
return ERR_BAD_LEN;
}
return resp_hdr.rc;
}
if (static_cast<size_t>(rc) !=
sizeof(resp_hdr) + static_cast<size_t>(resp_hdr.resp_payload_size)) {
return ERR_BAD_LEN;
}
resp_payload->resize(resp_hdr.resp_payload_size);
return NO_ERROR;
}
int BpCastAuth::connect(const char* port, uint32_t flags) {
if (mChan.ok()) {
return ERR_INVALID_ARGS;
}
return ::tidl::ipc::connect(port, flags, mChan);
}
bool BpCastAuth::is_connected() {
return (mChan.ok());
}
void BpCastAuth::reset() {
mChan.reset();
}
#if !defined(__QL_TIPC__)
#include <BnCastAuth.h>
struct TIDL_PACKED_ATTR Request {
::tidl::RequestHeader hdr;
union TIDL_PACKED_ATTR {
BnCastAuth::Request_ProvisionKey ProvisionKey;
BnCastAuth::Request_SignHash SignHash;
} req;
};
struct TIDL_PACKED_ATTR Response {
::tidl::ResponseHeader hdr;
union TIDL_PACKED_ATTR {
} resp;
};
union TIDL_PACKED_ATTR LongestMessage {
Request req;
Response resp;
};
BnCastAuth::BnCastAuth(const char* port,
const ::tidl::Service::PortAcl* acl,
uint32_t maximum_payload_size)
: Service("BnCastAuth",
port,
sizeof(LongestMessage) + maximum_payload_size,
acl,
&kOps) {}
int BnCastAuth::get_instance(ICastAuth*& instance, const struct uuid*) {
instance = this;
return NO_ERROR;
}
::tidl::Service::Ops BnCastAuth::kOps = {
.on_connect = BnCastAuth::on_connect,
.on_message = BnCastAuth::on_message,
.on_channel_cleanup = BnCastAuth::on_channel_cleanup,
};
int BnCastAuth::on_connect(const ::tidl::Service::Port* port,
::tidl::Handle chan,
const struct uuid* peer,
void** ctx_p) {
auto* bn_impl = static_cast<BnCastAuth*>(
reinterpret_cast<Service*>(const_cast<void*>(port->priv)));
assert(bn_impl);
ICastAuth* instance;
int rc = bn_impl->get_instance(instance, peer);
if (rc != NO_ERROR) {
return rc;
}
*ctx_p = instance;
return NO_ERROR;
}
void BnCastAuth::on_channel_cleanup(void* ctx) {
auto* impl = reinterpret_cast<ICastAuth*>(ctx);
assert(impl);
impl->destroy();
}
int BnCastAuth::on_message(const ::tidl::Service::Port* port,
::tidl::Handle chan,
void* ctx) {
auto* impl = reinterpret_cast<ICastAuth*>(ctx);
auto* bn_impl = static_cast<BnCastAuth*>(
reinterpret_cast<Service*>(const_cast<void*>(port->priv)));
assert(impl);
assert(bn_impl);
::tidl::Payload req_payload;
::tidl::Payload resp_payload;
ipc_msg_info_t mi;
int rc = get_msg(chan, &mi);
if (rc != NO_ERROR) {
return rc;
}
bool call_put_msg = true;
::tidl::RequestHeader req_hdr;
struct iovec req_hdr_iov = {.iov_base = &req_hdr,
.iov_len = sizeof(req_hdr)};
ipc_msg_t req_hdr_msg = {.num_iov = 1,
.iov = &req_hdr_iov,
.num_handles = 0,
.handles = nullptr};
rc = read_msg(chan, mi.id, 0, &req_hdr_msg);
if (rc < 0) {
goto done;
}
if (static_cast<size_t>(rc) < sizeof(req_hdr)) {
rc = ERR_BAD_LEN;
goto done;
}
switch (req_hdr.cmd) {
case CMD_ProvisionKey: {
Request_ProvisionKey req;
constexpr uint32_t min_msg_len = sizeof(req_hdr) + sizeof(req);
if (mi.len < min_msg_len) {
rc = ERR_BAD_LEN;
goto send_rc;
}
rc = bn_impl->get_payload_buffer(req_payload, mi.len - min_msg_len,
false);
if (rc != NO_ERROR) {
goto send_rc;
}
constexpr uint32_t req_num_handles = Request_ProvisionKey::num_handles;
::tidl::Handle req_handles[req_num_handles];
struct iovec req_iov[] = {
{.iov_base = &req, .iov_len = sizeof(req)},
{.iov_base = req_payload.data(), .iov_len = req_payload.size()},
};
ipc_msg_t req_msg = {.num_iov = countof(req_iov),
.iov = req_iov,
.num_handles = req_num_handles,
.handles = req_handles};
rc = read_msg(chan, mi.id, sizeof(req_hdr), &req_msg);
if (rc < 0) {
goto done;
}
if (static_cast<size_t>(rc) <
sizeof(req) + static_cast<size_t>(req_payload.size())) {
rc = ERR_BAD_LEN;
goto send_rc;
}
put_msg(chan, mi.id);
call_put_msg = false;
::tidl::Handle* hptr = req_handles;
req.recv_handles(hptr);
assert(hptr == &req_handles[req_num_handles]);
rc = impl->ProvisionKey(req_payload);
if (rc != NO_ERROR) {
goto send_rc;
}
::tidl::ResponseHeader resp_hdr = {
.cmd = req_hdr.cmd | RESP_BIT,
.rc = rc,
};
rc = ::tidl::ipc::send(chan, &resp_hdr, sizeof(resp_hdr), nullptr, 0);
if (rc < 0) {
goto done;
}
if (static_cast<size_t>(rc) != sizeof(resp_hdr)) {
rc = ERR_BAD_LEN;
goto done;
}
break;
}
case CMD_SignHash: {
Request_SignHash req;
constexpr uint32_t min_msg_len = sizeof(req_hdr) + sizeof(req);
if (mi.len < min_msg_len) {
rc = ERR_BAD_LEN;
goto send_rc;
}
rc = bn_impl->get_payload_buffer(req_payload, mi.len - min_msg_len,
false);
if (rc != NO_ERROR) {
goto send_rc;
}
rc = bn_impl->get_payload_buffer(resp_payload,
req_hdr.resp_payload_size, true);
if (rc != NO_ERROR) {
goto send_rc;
}
constexpr uint32_t req_num_handles = Request_SignHash::num_handles;
::tidl::Handle req_handles[req_num_handles];
struct iovec req_iov[] = {
{.iov_base = &req, .iov_len = sizeof(req)},
{.iov_base = req_payload.data(), .iov_len = req_payload.size()},
};
ipc_msg_t req_msg = {.num_iov = countof(req_iov),
.iov = req_iov,
.num_handles = req_num_handles,
.handles = req_handles};
rc = read_msg(chan, mi.id, sizeof(req_hdr), &req_msg);
if (rc < 0) {
goto done;
}
if (static_cast<size_t>(rc) <
sizeof(req) + static_cast<size_t>(req_payload.size())) {
rc = ERR_BAD_LEN;
goto send_rc;
}
put_msg(chan, mi.id);
call_put_msg = false;
::tidl::Handle* hptr = req_handles;
req.recv_handles(hptr);
assert(hptr == &req_handles[req_num_handles]);
rc = impl->SignHash(req_payload, &resp_payload);
if (rc != NO_ERROR) {
goto send_rc;
}
::tidl::ResponseHeader resp_hdr = {
.cmd = req_hdr.cmd | RESP_BIT,
.resp_payload_size = resp_payload.size(),
.rc = rc,
};
rc = ::tidl::ipc::send(chan, &resp_hdr, sizeof(resp_hdr),
resp_payload.data(), resp_payload.size(),
nullptr, 0);
if (rc < 0) {
goto done;
}
if (static_cast<size_t>(rc) != sizeof(resp_hdr) + resp_payload.size()) {
rc = ERR_BAD_LEN;
goto done;
}
break;
}
default:
put_msg(chan, mi.id);
call_put_msg = false;
rc = ERR_CMD_UNKNOWN;
goto send_rc;
break;
}
rc = NO_ERROR;
done:
if (call_put_msg) {
put_msg(chan, mi.id);
}
bn_impl->free_payload_buffer(tidl::move(req_payload));
bn_impl->free_payload_buffer(tidl::move(resp_payload));
return rc;
send_rc:
::tidl::ResponseHeader resp_hdr = {.cmd = req_hdr.cmd | RESP_BIT, .rc = rc};
rc = ::tidl::ipc::send(chan, &resp_hdr, sizeof(resp_hdr), nullptr, 0);
if (rc < 0) {
goto done;
}
if (static_cast<size_t>(rc) != sizeof(resp_hdr)) {
rc = ERR_BAD_LEN;
goto done;
}
goto done;
}
#endif // #if !defined(__QL_TIPC__)