android_kernel_samsung_sm8650/drivers/block/virtio_blk_qti_crypto.c
Santosh Dronamraju b39e3411a2 soc: qcom: Added support for virtualized FBE
Virtualized FBE is snapshot from msm-5.15 branch with commit id

commit 4d0e75a8e326 ("soc: qcom: Added support for virtualized FBE")

Modified virt block crypto supported APIS according to latest
implementation.

Change-Id: Ifee4bbd481b5a034cba5312216a6a05272895191
Signed-off-by: Santosh Dronamraju <quic_sdronamr@quicinc.com>
2023-11-02 11:06:19 +05:30

169 lines
4.8 KiB
C

// SPDX-License-Identifier: GPL-2.0-only
/*
* virtio block crypto ops QTI implementation.
*
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/device.h>
#include <linux/module.h>
#include <linux/blkdev.h>
#include <linux/crypto_qti_virt.h>
#include <linux/blk-crypto-profile.h>
/*keyslot manager for vrtual IO*/
static struct blk_crypto_profile virtio_crypto_profile;
/* initialize crypto profile only once */
static bool is_crypto_profile_initalized;
/*To get max ice slots for guest vm */
static uint32_t num_ice_slots;
void virtblk_crypto_qti_crypto_register(struct request_queue *q)
{
blk_crypto_register(&virtio_crypto_profile, q);
}
EXPORT_SYMBOL_GPL(virtblk_crypto_qti_crypto_register);
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 blk_crypto_profile *profile,
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 blk_crypto_profile *profile,
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 blk_crypto_profile *profile,
const u8 *eph_key,
size_t eph_key_size,
u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE])
{
int err = 0;
if (eph_key_size <= BLK_CRYPTO_SW_SECRET_SIZE) {
pr_err("%s: Invalid wrapped_key_size: %u\n",
__func__, eph_key_size);
err = -EINVAL;
return err;
}
if (eph_key_size > 64) {
err = crypto_qti_virt_derive_raw_secret_platform(eph_key,
eph_key_size,
sw_secret,
BLK_CRYPTO_SW_SECRET_SIZE);
} else {
memcpy(sw_secret, eph_key, BLK_CRYPTO_SW_SECRET_SIZE);
}
return err;
}
static const struct blk_crypto_ll_ops virtio_blk_qti_crypto_ops = {
.keyslot_program = virtblk_crypto_qti_keyslot_program,
.keyslot_evict = virtblk_crypto_qti_keyslot_evict,
.derive_sw_secret = virtblk_crypto_qti_derive_raw_secret,
};
int virtblk_init_crypto_qti_spec(struct device *dev)
{
int err = 0;
unsigned int crypto_modes_supported[BLK_ENCRYPTION_MODE_MAX];
memset(crypto_modes_supported, 0, sizeof(crypto_modes_supported));
/* Actual determination of capabilities for UFS/EMMC for different
* encryption modes are done in the back end (host operating system)
* in case of virtualization driver, so will get crypto capabilities
* from the back end. The received capabilities is feeded as input
* parameter to keyslot manager
*/
err = crypto_qti_virt_get_crypto_capabilities(crypto_modes_supported,
sizeof(crypto_modes_supported));
if (err) {
pr_err("crypto_qti_virt_get_crypto_capabilities failed error = %d\n", err);
return err;
}
/* 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 incase keyslot manager is already initialized */
if (is_crypto_profile_initalized)
return 0;
/* create keyslot manager and which will manage the keyslots for all
* virtual disks
*/
err = devm_blk_crypto_profile_init(dev, &virtio_crypto_profile, num_ice_slots);
if (err) {
pr_err("%s: crypto profile initialization failed\n", __func__);
return err;
}
is_crypto_profile_initalized = true;
virtio_crypto_profile.ll_ops = virtio_blk_qti_crypto_ops;
/* This value suppose to get from host based on storage type
* will remove hard code value later
*/
virtio_crypto_profile.max_dun_bytes_supported = 8;
virtio_crypto_profile.key_types_supported = BLK_CRYPTO_KEY_TYPE_HW_WRAPPED;
virtio_crypto_profile.dev = dev;
memcpy(virtio_crypto_profile.modes_supported, crypto_modes_supported,
sizeof(crypto_modes_supported));
pr_info("%s: crypto profile initialized.\n", __func__);
return err;
}
EXPORT_SYMBOL_GPL(virtblk_init_crypto_qti_spec);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Crypto Virtual library for storage encryption");