Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2ba61b77 authored by Matthew Maurer's avatar Matthew Maurer Committed by Gerrit Code Review
Browse files

Merge "Add support for RPMB over VirtIO Serial"

parents e9223204 57ba8c58
Loading
Loading
Loading
Loading
+25 −3
Original line number Diff line number Diff line
@@ -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 */
+89 −36
Original line number Diff line number Diff line
@@ -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) {
+3 −1
Original line number Diff line number Diff line
@@ -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);