Esempio n. 1
0
static int64_t block_crypto_getlength(BlockDriverState *bs)
{
    BlockCrypto *crypto = bs->opaque;
    int64_t len = bdrv_getlength(bs->file->bs);

    ssize_t offset = qcrypto_block_get_payload_offset(crypto->block);

    len -= offset;

    return len;
}
Esempio n. 2
0
static int block_crypto_create_generic(QCryptoBlockFormat format,
                                       const char *filename,
                                       QemuOpts *opts,
                                       Error **errp)
{
    int ret = -EINVAL;
    QCryptoBlockCreateOptions *create_opts = NULL;
    QCryptoBlock *crypto = NULL;
    struct BlockCryptoCreateData data = {
        .size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
                         BDRV_SECTOR_SIZE),
        .opts = opts,
        .filename = filename,
    };

    create_opts = block_crypto_create_opts_init(format, opts, errp);
    if (!create_opts) {
        return -1;
    }

    crypto = qcrypto_block_create(create_opts,
                                  block_crypto_init_func,
                                  block_crypto_write_func,
                                  &data,
                                  errp);

    if (!crypto) {
        ret = -EIO;
        goto cleanup;
    }

    ret = 0;
 cleanup:
    qcrypto_block_free(crypto);
    blk_unref(data.blk);
    qapi_free_QCryptoBlockCreateOptions(create_opts);
    return ret;
}

static int block_crypto_truncate(BlockDriverState *bs, int64_t offset,
                                 Error **errp)
{
    BlockCrypto *crypto = bs->opaque;
    size_t payload_offset =
        qcrypto_block_get_payload_offset(crypto->block);

    offset += payload_offset;

    return bdrv_truncate(bs->file, offset, errp);
}
Esempio n. 3
0
static coroutine_fn int
block_crypto_co_writev(BlockDriverState *bs, int64_t sector_num,
                       int remaining_sectors, QEMUIOVector *qiov)
{
    BlockCrypto *crypto = bs->opaque;
    int cur_nr_sectors; /* number of sectors in current iteration */
    uint64_t bytes_done = 0;
    uint8_t *cipher_data = NULL;
    QEMUIOVector hd_qiov;
    int ret = 0;
    size_t payload_offset =
        qcrypto_block_get_payload_offset(crypto->block) / 512;

    qemu_iovec_init(&hd_qiov, qiov->niov);

    /* Bounce buffer so we have a linear mem region for
     * entire sector. XXX optimize so we avoid bounce
     * buffer in case that qiov->niov == 1
     */
    cipher_data =
        qemu_try_blockalign(bs->file->bs, MIN(BLOCK_CRYPTO_MAX_SECTORS * 512,
                                              qiov->size));
    if (cipher_data == NULL) {
        ret = -ENOMEM;
        goto cleanup;
    }

    while (remaining_sectors) {
        cur_nr_sectors = remaining_sectors;

        if (cur_nr_sectors > BLOCK_CRYPTO_MAX_SECTORS) {
            cur_nr_sectors = BLOCK_CRYPTO_MAX_SECTORS;
        }

        qemu_iovec_to_buf(qiov, bytes_done,
                          cipher_data, cur_nr_sectors * 512);

        if (qcrypto_block_encrypt(crypto->block,
                                  sector_num,
                                  cipher_data, cur_nr_sectors * 512,
                                  NULL) < 0) {
            ret = -EIO;
            goto cleanup;
        }

        qemu_iovec_reset(&hd_qiov);
        qemu_iovec_add(&hd_qiov, cipher_data, cur_nr_sectors * 512);

        ret = bdrv_co_writev(bs->file,
                             payload_offset + sector_num,
                             cur_nr_sectors, &hd_qiov);
        if (ret < 0) {
            goto cleanup;
        }

        remaining_sectors -= cur_nr_sectors;
        sector_num += cur_nr_sectors;
        bytes_done += cur_nr_sectors * 512;
    }

 cleanup:
    qemu_iovec_destroy(&hd_qiov);
    qemu_vfree(cipher_data);

    return ret;
}