mirror of
https://github.com/torvalds/linux.git
synced 2026-04-18 14:53:58 -04:00
crypto: virtio - Register an algo only if it's supported
Register a crypto algo with the Linux crypto layer only if the algorithm is supported by the backend virtio-crypto device. Also route crypto requests to a virtio-crypto device, only if it can support the requested service and algorithm. Signed-off-by: Farhan Ali <alifm@linux.ibm.com> Acked-by: Gonglei <arei.gonglei@huawei.com> Acked-by: Christian Borntraeger <borntraeger@de.ibm.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
@@ -181,14 +181,20 @@ int virtcrypto_dev_started(struct virtio_crypto *vcrypto_dev)
|
||||
/*
|
||||
* virtcrypto_get_dev_node() - Get vcrypto_dev on the node.
|
||||
* @node: Node id the driver works.
|
||||
* @service: Crypto service that needs to be supported by the
|
||||
* dev
|
||||
* @algo: The algorithm number that needs to be supported by the
|
||||
* dev
|
||||
*
|
||||
* Function returns the virtio crypto device used fewest on the node.
|
||||
* Function returns the virtio crypto device used fewest on the node,
|
||||
* and supports the given crypto service and algorithm.
|
||||
*
|
||||
* To be used by virtio crypto device specific drivers.
|
||||
*
|
||||
* Return: pointer to vcrypto_dev or NULL if not found.
|
||||
*/
|
||||
struct virtio_crypto *virtcrypto_get_dev_node(int node)
|
||||
struct virtio_crypto *virtcrypto_get_dev_node(int node, uint32_t service,
|
||||
uint32_t algo)
|
||||
{
|
||||
struct virtio_crypto *vcrypto_dev = NULL, *tmp_dev;
|
||||
unsigned long best = ~0;
|
||||
@@ -199,7 +205,8 @@ struct virtio_crypto *virtcrypto_get_dev_node(int node)
|
||||
|
||||
if ((node == dev_to_node(&tmp_dev->vdev->dev) ||
|
||||
dev_to_node(&tmp_dev->vdev->dev) < 0) &&
|
||||
virtcrypto_dev_started(tmp_dev)) {
|
||||
virtcrypto_dev_started(tmp_dev) &&
|
||||
virtcrypto_algo_is_supported(tmp_dev, service, algo)) {
|
||||
ctr = atomic_read(&tmp_dev->ref_count);
|
||||
if (best > ctr) {
|
||||
vcrypto_dev = tmp_dev;
|
||||
@@ -214,7 +221,9 @@ struct virtio_crypto *virtcrypto_get_dev_node(int node)
|
||||
/* Get any started device */
|
||||
list_for_each_entry(tmp_dev,
|
||||
virtcrypto_devmgr_get_head(), list) {
|
||||
if (virtcrypto_dev_started(tmp_dev)) {
|
||||
if (virtcrypto_dev_started(tmp_dev) &&
|
||||
virtcrypto_algo_is_supported(tmp_dev,
|
||||
service, algo)) {
|
||||
vcrypto_dev = tmp_dev;
|
||||
break;
|
||||
}
|
||||
@@ -240,7 +249,7 @@ struct virtio_crypto *virtcrypto_get_dev_node(int node)
|
||||
*/
|
||||
int virtcrypto_dev_start(struct virtio_crypto *vcrypto)
|
||||
{
|
||||
if (virtio_crypto_algs_register()) {
|
||||
if (virtio_crypto_algs_register(vcrypto)) {
|
||||
pr_err("virtio_crypto: Failed to register crypto algs\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
@@ -260,5 +269,65 @@ int virtcrypto_dev_start(struct virtio_crypto *vcrypto)
|
||||
*/
|
||||
void virtcrypto_dev_stop(struct virtio_crypto *vcrypto)
|
||||
{
|
||||
virtio_crypto_algs_unregister();
|
||||
virtio_crypto_algs_unregister(vcrypto);
|
||||
}
|
||||
|
||||
/*
|
||||
* vcrypto_algo_is_supported()
|
||||
* @vcrypto: Pointer to virtio crypto device.
|
||||
* @service: The bit number for service validate.
|
||||
* See VIRTIO_CRYPTO_SERVICE_*
|
||||
* @algo : The bit number for the algorithm to validate.
|
||||
*
|
||||
*
|
||||
* Validate if the virtio crypto device supports a service and
|
||||
* algo.
|
||||
*
|
||||
* Return true if device supports a service and algo.
|
||||
*/
|
||||
|
||||
bool virtcrypto_algo_is_supported(struct virtio_crypto *vcrypto,
|
||||
uint32_t service,
|
||||
uint32_t algo)
|
||||
{
|
||||
uint32_t service_mask = 1u << service;
|
||||
uint32_t algo_mask = 0;
|
||||
bool low = true;
|
||||
|
||||
if (algo > 31) {
|
||||
algo -= 32;
|
||||
low = false;
|
||||
}
|
||||
|
||||
if (!(vcrypto->crypto_services & service_mask))
|
||||
return false;
|
||||
|
||||
switch (service) {
|
||||
case VIRTIO_CRYPTO_SERVICE_CIPHER:
|
||||
if (low)
|
||||
algo_mask = vcrypto->cipher_algo_l;
|
||||
else
|
||||
algo_mask = vcrypto->cipher_algo_h;
|
||||
break;
|
||||
|
||||
case VIRTIO_CRYPTO_SERVICE_HASH:
|
||||
algo_mask = vcrypto->hash_algo;
|
||||
break;
|
||||
|
||||
case VIRTIO_CRYPTO_SERVICE_MAC:
|
||||
if (low)
|
||||
algo_mask = vcrypto->mac_algo_l;
|
||||
else
|
||||
algo_mask = vcrypto->mac_algo_h;
|
||||
break;
|
||||
|
||||
case VIRTIO_CRYPTO_SERVICE_AEAD:
|
||||
algo_mask = vcrypto->aead_algo;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(algo_mask & (1u << algo)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user