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

Commit 26ce3040 authored by Santosh Dronamraju's avatar Santosh Dronamraju Committed by Gerrit - the friendly Code Review server
Browse files

soc: qcom: Added support for virtualized FBE



Added crypto-qti-virt.c which sends crypto requests to backend(HOST)
via hab channel from frontend(GUEST) while performing hardware based
file encryption. This Makes the driver to use the hypervisor backend
for ICE virtualization instead of calling directly to TZ.

Added virtio_blk_qti_crypto.c which creates a keyslot manager device
for virtual disk to manage keyslots, which will forward the request
to crypto virtual library and eventually will program the ICE slot
in the backend(HOST).

Test:
1.Basic_SimpleEncryption
2.ModifyEnforcedFiles_FileCreationWithinEnforcedFolder
3.PIN, pattern, password
4.verified filename encryption.

Change-Id: Idc57d9958e1cecba68eecd556d18ec54fa1c02b0
Signed-off-by: default avatarSantosh Dronamraju <sdronamr@codeaurora.org>
parent daf5b313
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -432,6 +432,15 @@ config VIRTIO_BLK
	  This is the virtual block driver for virtio.  It can be used with
          QEMU based VMMs (like KVM or Xen).  Say Y or M.

config VIRTIO_BLK_QTI_CRYPTO
	tristate "Vendor specific VIRTIO Crypto Engine Support"
	depends on VIRTIO_BLK
	help
	 Enable storage inline crypto engine support for guest virtual machine.
	 Enabling this allows kernel to use crypto operations defined
	 and implemented by QTI.
	 Say Y or M.

config VIRTIO_BLK_SCSI
	bool "SCSI passthrough request for the Virtio block driver"
	depends on VIRTIO_BLK
+1 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ obj-$(CONFIG_BLK_DEV_SKD) += skd.o
obj-$(CONFIG_BLK_DEV_UMEM)	+= umem.o
obj-$(CONFIG_BLK_DEV_NBD)	+= nbd.o
obj-$(CONFIG_BLK_DEV_CRYPTOLOOP) += cryptoloop.o
obj-$(CONFIG_VIRTIO_BLK_QTI_CRYPTO) += virtio_blk_qti_crypto.o
obj-$(CONFIG_VIRTIO_BLK)	+= virtio_blk.o

obj-$(CONFIG_BLK_DEV_SX8)	+= sx8.o
+70 −4
Original line number Diff line number Diff line
@@ -16,11 +16,22 @@
#include <linux/blk-mq.h>
#include <linux/blk-mq-virtio.h>
#include <linux/numa.h>
#ifdef CONFIG_QTI_CRYPTO_VIRTUALIZATION
#include <linux/bio-crypt-ctx.h>
#include "virtio_blk_qti_crypto.h"
#endif

#define PART_BITS 4
#define VQ_NAME_LEN 16
#define MAX_DISCARD_SEGMENTS 256u

#ifdef CONFIG_QTI_CRYPTO_VIRTUALIZATION
/* Temporaryly declaring ice supported feature bit.
 * Will discard this macro once uapi chages are mainlined
 */
#define VIRTIO_BLK_F_ICE	23	/* support ice virtualization */
#endif

static int major;
static DEFINE_IDA(vd_index_ida);

@@ -71,6 +82,15 @@ struct virtio_blk {
	struct virtio_blk_vq *vqs;
};

#ifdef CONFIG_QTI_CRYPTO_VIRTUALIZATION
struct virtio_blk_ice_info {
	/*the key slot to use for inline crypto*/
	u8  ice_slot;
	u8  activate;
	u16 reserved;
} __packed;
#endif

struct virtblk_req {
#ifdef CONFIG_VIRTIO_BLK_SCSI
	struct scsi_request sreq;	/* for SCSI passthrough, must be first */
@@ -78,6 +98,9 @@ struct virtblk_req {
	struct virtio_scsi_inhdr in_hdr;
#endif
	struct virtio_blk_outhdr out_hdr;
#ifdef CONFIG_QTI_CRYPTO_VIRTUALIZATION
	struct virtio_blk_ice_info ice_info;
#endif
	u8 status;
	struct scatterlist sg[];
};
@@ -173,8 +196,14 @@ static int virtblk_add_req(struct virtqueue *vq, struct virtblk_req *vbr,
{
	struct scatterlist hdr, status, *sgs[3];
	unsigned int num_out = 0, num_in = 0;

#ifdef CONFIG_QTI_CRYPTO_VIRTUALIZATION
	size_t const hdr_size = virtio_has_feature(vq->vdev, VIRTIO_BLK_F_ICE) ?
				sizeof(vbr->out_hdr) + sizeof(vbr->ice_info) :
				sizeof(vbr->out_hdr);
	sg_init_one(&hdr, &vbr->out_hdr, hdr_size);
#else
	sg_init_one(&hdr, &vbr->out_hdr, sizeof(vbr->out_hdr));
#endif
	sgs[num_out++] = &hdr;

	if (have_data) {
@@ -284,6 +313,25 @@ static void virtio_commit_rqs(struct blk_mq_hw_ctx *hctx)
		virtqueue_notify(vq->vq);
}

#ifdef CONFIG_QTI_CRYPTO_VIRTUALIZATION
static void virtblk_get_ice_info(struct virtio_blk *vblk, struct request *req)
{
	/* whether or not the request needs inline crypto operations*/
	struct bio_crypt_ctx *bc;
	struct virtblk_req *vbr = blk_mq_rq_to_pdu(req);

	if (!bio_crypt_should_process(req)) {
		/* ice is not activated */
		vbr->ice_info.activate = false;
	} else {
		bc = req->bio->bi_crypt_context;
		/* ice is activated - successful flow */
		vbr->ice_info.ice_slot = bc->bc_keyslot;
		vbr->ice_info.activate = true;
	}
}
#endif

static blk_status_t virtio_queue_rq(struct blk_mq_hw_ctx *hctx,
			   const struct blk_mq_queue_data *bd)
{
@@ -333,7 +381,10 @@ static blk_status_t virtio_queue_rq(struct blk_mq_hw_ctx *hctx,
	vbr->out_hdr.sector = type ?
		0 : cpu_to_virtio64(vblk->vdev, blk_rq_pos(req));
	vbr->out_hdr.ioprio = cpu_to_virtio32(vblk->vdev, req_get_ioprio(req));

#ifdef CONFIG_QTI_CRYPTO_VIRTUALIZATION
	if (virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_ICE))
		virtblk_get_ice_info(vblk, req);
#endif
	blk_mq_start_request(req);

	if (type == VIRTIO_BLK_T_DISCARD || type == VIRTIO_BLK_T_WRITE_ZEROES) {
@@ -981,8 +1032,17 @@ static int virtblk_probe(struct virtio_device *vdev)
	}

	virtblk_update_capacity(vblk, false);
	virtio_device_ready(vdev);

#ifdef CONFIG_QTI_CRYPTO_VIRTUALIZATION
	if (virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_ICE)) {
		dev_notice(&vdev->dev, "%s\n", vblk->disk->disk_name);
		/* Initilaize supported crypto capabilities*/
		err = virtblk_init_crypto_qti_spec();
		if (!err)
			virtblk_crypto_qti_setup_rq_keyslot_manager(vblk->disk->queue);
	}
#endif
	virtio_device_ready(vdev);
	device_add_disk(&vdev->dev, vblk->disk, virtblk_attr_groups);
	return 0;

@@ -1007,7 +1067,10 @@ static void virtblk_remove(struct virtio_device *vdev)

	/* Make sure no work handler is accessing the device. */
	flush_work(&vblk->config_work);

#ifdef CONFIG_QTI_CRYPTO_VIRTUALIZATION
	if (virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_ICE))
		virtblk_crypto_qti_destroy_rq_keyslot_manager(vblk->disk->queue);
#endif
	del_gendisk(vblk->disk);
	blk_cleanup_queue(vblk->disk->queue);

@@ -1083,6 +1146,9 @@ static unsigned int features[] = {
	VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE,
	VIRTIO_BLK_F_FLUSH, VIRTIO_BLK_F_TOPOLOGY, VIRTIO_BLK_F_CONFIG_WCE,
	VIRTIO_BLK_F_MQ, VIRTIO_BLK_F_DISCARD, VIRTIO_BLK_F_WRITE_ZEROES,
#ifdef CONFIG_QTI_CRYPTO_VIRTUALIZATION
	VIRTIO_BLK_F_ICE,
#endif
};

static struct virtio_driver virtio_blk = {
+162 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * virtio block crypto ops QTI implementation.
 *
 * Copyright (c) 2021, Linux Foundation. All rights reserved.
 */

#include <linux/device.h>
#include <linux/module.h>
#include <linux/blkdev.h>
#include <linux/crypto_qti_virt.h>
#include <linux/keyslot-manager.h>

/*keyslot manager for vrtual IO*/
static struct keyslot_manager *virtio_ksm;
/*To get max ice slots for guest vm */
static uint32_t num_ice_slots;

void virtblk_crypto_qti_setup_rq_keyslot_manager(struct request_queue *q)
{
		q->ksm = virtio_ksm;
}
EXPORT_SYMBOL(virtblk_crypto_qti_setup_rq_keyslot_manager);

void virtblk_crypto_qti_destroy_rq_keyslot_manager(struct request_queue *q)
{
		keyslot_manager_destroy(virtio_ksm);
}
EXPORT_SYMBOL(virtblk_crypto_qti_destroy_rq_keyslot_manager);

static inline bool virtblk_keyslot_valid(unsigned int slot)
{
	/*
	 * slot numbers range from 0 to max available
	 * slots for vm.
	 */
	return slot < num_ice_slots;
}

static int virtblk_crypto_qti_keyslot_program(struct keyslot_manager *ksm,
						const struct blk_crypto_key *key,
						unsigned int slot)
{
	int err = 0;

	if (!virtblk_keyslot_valid(slot)) {
		pr_err("%s: key slot is not valid\n",
			__func__);
		return -EINVAL;
	}
	err = crypto_qti_virt_program_key(key, slot);
	if (err) {
		pr_err("%s: program key failed with error %d\n",
			__func__, err);
		err = crypto_qti_virt_invalidate_key(slot);
		if (err) {
			pr_err("%s: invalidate key failed with error %d\n",
				__func__, err);
			return err;
		}
	}
	return err;
}

static int virtblk_crypto_qti_keyslot_evict(struct keyslot_manager *ksm,
					const struct blk_crypto_key *key,
					unsigned int slot)
{
	int err = 0;

	if (!virtblk_keyslot_valid(slot)) {
		pr_err("%s: key slot is not valid\n",
			__func__);
		return -EINVAL;
	}
	err = crypto_qti_virt_invalidate_key(slot);
	if (err) {
		pr_err("%s: evict key failed with error %d\n",
			__func__, err);
		return err;
	}
	return err;
}

static int virtblk_crypto_qti_derive_raw_secret(struct keyslot_manager *ksm,
						const u8 *wrapped_key,
						unsigned int wrapped_key_size,
						u8 *secret,
						unsigned int secret_size)
{
	int err = 0;

	if (wrapped_key_size <= RAW_SECRET_SIZE) {
		pr_err("%s: Invalid wrapped_key_size: %u\n",
			__func__, wrapped_key_size);
		err = -EINVAL;
		return err;
	}
	if (secret_size != RAW_SECRET_SIZE) {
		pr_err("%s: Invalid secret size: %u\n",
			__func__, secret_size);
		err = -EINVAL;
		return err;
	}
	err = crypto_qti_virt_derive_raw_secret_platform(wrapped_key,
							 wrapped_key_size,
							 secret,
							 secret_size);
	return err;
}

static const struct keyslot_mgmt_ll_ops virtio_blk_crypto_qti_ksm_ops = {
	.keyslot_program        = virtblk_crypto_qti_keyslot_program,
	.keyslot_evict          = virtblk_crypto_qti_keyslot_evict,
	.derive_raw_secret      = virtblk_crypto_qti_derive_raw_secret,
};

int virtblk_init_crypto_qti_spec(void)
{
	int err = 0;
	int cap_idx = 0;
	unsigned int crypto_modes_supported[BLK_ENCRYPTION_MODE_MAX];

	/* Actual determination of capabilities for UFS/EMMC for different
	 * encryption modes are done in the back end in case of virtualization
	 * driver, so initializing this to 0xFFFFFFFF meaning it supports
	 * all crypto capabilities to please the keyslot manager. feeding
	 * as input parameter to the keyslot manager
	 */
	for (cap_idx = 0; cap_idx < BLK_ENCRYPTION_MODE_MAX; cap_idx++)
		crypto_modes_supported[cap_idx] = 0xFFFFFFFF;
	crypto_modes_supported[BLK_ENCRYPTION_MODE_INVALID] = 0;

	/* Get max number of ice  slots for guest vm */
	err = crypto_qti_virt_ice_get_info(&num_ice_slots);
	if (err) {
		pr_err("crypto_qti_virt_ice_get_info failed error = %d\n", err);
		return err;
	}
	/* Return from here inacse keyslot manger is already created */
	if (virtio_ksm)
		return 0;

	/* create keyslot manager and which will manage the keyslots for all
	 * virtual disks
	 */
	virtio_ksm = keyslot_manager_create(NULL,
					num_ice_slots,
					&virtio_blk_crypto_qti_ksm_ops,
					BLK_CRYPTO_FEATURE_STANDARD_KEYS |
					BLK_CRYPTO_FEATURE_WRAPPED_KEYS,
					crypto_modes_supported,
					NULL);

	if (!virtio_ksm)
		return  -ENOMEM;

	pr_info("%s: keyslot manager created\n", __func__);

	return err;
}
EXPORT_SYMBOL(virtblk_init_crypto_qti_spec);
+35 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2021, The Linux Foundation. All rights reserved.
 */

#ifndef _VIRTIO_BLK_QTI_CRYPTO_H
#define _VIRTIO_BLK_QTI_CRYPTO_H

#include <linux/device.h>
#include <linux/blkdev.h>

/**
 * This function intializes the supported crypto capabilities
 * and create keyslot manager to manage keyslots for virtual
 * disks.
 *
 * Return: zero on success, else a -errno value
 */
int virtblk_init_crypto_qti_spec(void);

/**
 * set up a keyslot manager in the virtual disks request_queue
 *
 * @request_queue: virtual disk request queue
 */
void virtblk_crypto_qti_setup_rq_keyslot_manager(struct request_queue *q);
/**
 * destroy keyslot manager
 *
 * @request_queue: virtual disk request queue
 */
void virtblk_crypto_qti_destroy_rq_keyslot_manager(struct request_queue *q);

#endif /* _VIRTIO_BLK_QTI_CRYPTO_H */
Loading