Merge "Add support for RPMB over VirtIO Serial"

This commit is contained in:
Matthew Maurer 2019-03-07 21:30:56 +00:00 committed by Gerrit Code Review
commit 2ba61b775a
3 changed files with 117 additions and 40 deletions

View file

@ -39,15 +39,29 @@ static const char* trusty_devname;
static const char* rpmb_devname;
static const char* ss_srv_name = STORAGE_DISK_PROXY_PORT;
static const char* _sopts = "hp:d:r:";
static enum dev_type dev_type = MMC_RPMB;
static enum dev_type parse_dev_type(const char* dev_type_name) {
if (!strcmp(dev_type_name, "mmc")) {
return MMC_RPMB;
} else if (!strcmp(dev_type_name, "virt")) {
return VIRT_RPMB;
} else {
return UNKNOWN_RPMB;
}
}
static const char* _sopts = "hp:d:r:t:";
static const struct option _lopts[] = {{"help", no_argument, NULL, 'h'},
{"trusty_dev", required_argument, NULL, 'd'},
{"data_path", required_argument, NULL, 'p'},
{"rpmb_dev", required_argument, NULL, 'r'},
{"dev_type", required_argument, NULL, 't'},
{0, 0, 0, 0}};
static void show_usage_and_exit(int code) {
ALOGE("usage: storageproxyd -d <trusty_dev> -p <data_path> -r <rpmb_dev>\n");
ALOGE("usage: storageproxyd -d <trusty_dev> -p <data_path> -r <rpmb_dev> -t <dev_type>\n");
ALOGE("Available dev types: mmc, virt\n");
exit(code);
}
@ -195,6 +209,14 @@ static void parse_args(int argc, char* argv[]) {
rpmb_devname = strdup(optarg);
break;
case 't':
dev_type = parse_dev_type(optarg);
if (dev_type == UNKNOWN_RPMB) {
ALOGE("Unrecognized dev type: %s\n", optarg);
show_usage_and_exit(EXIT_FAILURE);
}
break;
default:
ALOGE("unrecognized option (%c):\n", opt);
show_usage_and_exit(EXIT_FAILURE);
@ -226,7 +248,7 @@ int main(int argc, char* argv[]) {
if (rc < 0) return EXIT_FAILURE;
/* open rpmb device */
rc = rpmb_open(rpmb_devname);
rc = rpmb_open(rpmb_devname, dev_type);
if (rc < 0) return EXIT_FAILURE;
/* connect to Trusty secure storage server */

View file

@ -51,6 +51,7 @@
static int rpmb_fd = -1;
static uint8_t read_buf[4096];
static enum dev_type dev_type = UNKNOWN_RPMB;
#ifdef RPMB_DEBUG
@ -68,36 +69,16 @@ static void print_buf(const char* prefix, const uint8_t* buf, size_t size) {
#endif
int rpmb_send(struct storage_msg* msg, const void* r, size_t req_len) {
int rc;
static int send_mmc_rpmb_req(int mmc_fd, const struct storage_rpmb_send_req* req) {
struct {
struct mmc_ioc_multi_cmd multi;
struct mmc_ioc_cmd cmd_buf[3];
} mmc = {};
struct mmc_ioc_cmd* cmd = mmc.multi.cmds;
const struct storage_rpmb_send_req* req = r;
if (req_len < sizeof(*req)) {
ALOGW("malformed rpmb request: invalid length (%zu < %zu)\n", req_len, sizeof(*req));
msg->result = STORAGE_ERR_NOT_VALID;
goto err_response;
}
size_t expected_len = sizeof(*req) + req->reliable_write_size + req->write_size;
if (req_len != expected_len) {
ALOGW("malformed rpmb request: invalid length (%zu != %zu)\n", req_len, expected_len);
msg->result = STORAGE_ERR_NOT_VALID;
goto err_response;
}
int rc;
const uint8_t* write_buf = req->payload;
if (req->reliable_write_size) {
if ((req->reliable_write_size % MMC_BLOCK_SIZE) != 0) {
ALOGW("invalid reliable write size %u\n", req->reliable_write_size);
msg->result = STORAGE_ERR_NOT_VALID;
goto err_response;
}
cmd->write_flag = MMC_WRITE_FLAG_RELW;
cmd->opcode = MMC_WRITE_MULTIPLE_BLOCK;
cmd->flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
@ -114,12 +95,6 @@ int rpmb_send(struct storage_msg* msg, const void* r, size_t req_len) {
}
if (req->write_size) {
if ((req->write_size % MMC_BLOCK_SIZE) != 0) {
ALOGW("invalid write size %u\n", req->write_size);
msg->result = STORAGE_ERR_NOT_VALID;
goto err_response;
}
cmd->write_flag = MMC_WRITE_FLAG_W;
cmd->opcode = MMC_WRITE_MULTIPLE_BLOCK;
cmd->flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
@ -136,12 +111,6 @@ int rpmb_send(struct storage_msg* msg, const void* r, size_t req_len) {
}
if (req->read_size) {
if (req->read_size % MMC_BLOCK_SIZE != 0 || req->read_size > sizeof(read_buf)) {
ALOGE("%s: invalid read size %u\n", __func__, req->read_size);
msg->result = STORAGE_ERR_NOT_VALID;
goto err_response;
}
cmd->write_flag = MMC_WRITE_FLAG_R;
cmd->opcode = MMC_READ_MULTIPLE_BLOCK;
cmd->flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC, cmd->blksz = MMC_BLOCK_SIZE;
@ -154,9 +123,92 @@ int rpmb_send(struct storage_msg* msg, const void* r, size_t req_len) {
cmd++;
}
rc = ioctl(rpmb_fd, MMC_IOC_MULTI_CMD, &mmc.multi);
rc = ioctl(mmc_fd, MMC_IOC_MULTI_CMD, &mmc.multi);
if (rc < 0) {
ALOGE("%s: mmc ioctl failed: %d, %s\n", __func__, rc, strerror(errno));
}
return rc;
}
static int send_virt_rpmb_req(int rpmb_fd, void* read_buf, size_t read_size, const void* payload,
size_t payload_size) {
int rc;
uint16_t res_count = read_size / MMC_BLOCK_SIZE;
uint16_t cmd_count = payload_size / MMC_BLOCK_SIZE;
rc = write(rpmb_fd, &res_count, sizeof(res_count));
if (rc < 0) {
return rc;
}
rc = write(rpmb_fd, &cmd_count, sizeof(cmd_count));
if (rc < 0) {
return rc;
}
rc = write(rpmb_fd, payload, payload_size);
if (rc < 0) {
return rc;
}
rc = read(rpmb_fd, read_buf, read_size);
return rc;
}
int rpmb_send(struct storage_msg* msg, const void* r, size_t req_len) {
int rc;
const struct storage_rpmb_send_req* req = r;
if (req_len < sizeof(*req)) {
ALOGW("malformed rpmb request: invalid length (%zu < %zu)\n", req_len, sizeof(*req));
msg->result = STORAGE_ERR_NOT_VALID;
goto err_response;
}
size_t expected_len = sizeof(*req) + req->reliable_write_size + req->write_size;
if (req_len != expected_len) {
ALOGW("malformed rpmb request: invalid length (%zu != %zu)\n", req_len, expected_len);
msg->result = STORAGE_ERR_NOT_VALID;
goto err_response;
}
if ((req->reliable_write_size % MMC_BLOCK_SIZE) != 0) {
ALOGW("invalid reliable write size %u\n", req->reliable_write_size);
msg->result = STORAGE_ERR_NOT_VALID;
goto err_response;
}
if ((req->write_size % MMC_BLOCK_SIZE) != 0) {
ALOGW("invalid write size %u\n", req->write_size);
msg->result = STORAGE_ERR_NOT_VALID;
goto err_response;
}
if (req->read_size % MMC_BLOCK_SIZE != 0 || req->read_size > sizeof(read_buf)) {
ALOGE("%s: invalid read size %u\n", __func__, req->read_size);
msg->result = STORAGE_ERR_NOT_VALID;
goto err_response;
}
if (dev_type == MMC_RPMB) {
rc = send_mmc_rpmb_req(rpmb_fd, req);
if (rc < 0) {
msg->result = STORAGE_ERR_GENERIC;
goto err_response;
}
} else if (dev_type == VIRT_RPMB) {
size_t payload_size = req->reliable_write_size + req->write_size;
rc = send_virt_rpmb_req(rpmb_fd, read_buf, req->read_size, req->payload, payload_size);
if (rc < 0) {
ALOGE("send_virt_rpmb_req failed: %d, %s\n", rc, strerror(errno));
msg->result = STORAGE_ERR_GENERIC;
goto err_response;
}
if (rc != req->read_size) {
ALOGE("send_virt_rpmb_req got incomplete response: "
"(size %d, expected %d)\n",
rc, req->read_size);
msg->result = STORAGE_ERR_GENERIC;
goto err_response;
}
} else {
ALOGE("Unsupported dev_type\n");
msg->result = STORAGE_ERR_GENERIC;
goto err_response;
}
@ -178,8 +230,9 @@ err_response:
return ipc_respond(msg, NULL, 0);
}
int rpmb_open(const char* rpmb_devname) {
int rpmb_open(const char* rpmb_devname, enum dev_type open_dev_type) {
int rc;
dev_type = open_dev_type;
rc = open(rpmb_devname, O_RDWR, 0);
if (rc < 0) {

View file

@ -18,6 +18,8 @@
#include <stdint.h>
#include <trusty/interface/storage.h>
int rpmb_open(const char* rpmb_devname);
enum dev_type { UNKNOWN_RPMB, MMC_RPMB, VIRT_RPMB };
int rpmb_open(const char* rpmb_devname, enum dev_type dev_type);
int rpmb_send(struct storage_msg* msg, const void* r, size_t req_len);
void rpmb_close(void);