Home Home > GIT Browse > SLE12-SP5-AZURE
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetr Tesarik <ptesarik@suse.cz>2019-09-05 18:05:50 +0200
committerPetr Tesarik <ptesarik@suse.cz>2019-09-05 18:06:09 +0200
commit45a2564cc128365c4174766549d396fd84e18ce4 (patch)
tree1847df012c8bdc162ec643c39ade483d3baec9fe
parent8ebbf67d580a1c9527d8c2ebfe1e53ebbccf2055 (diff)
crypto: virtio - Register an algo only if it's supported
(jsc#SLE-5844 jsc#SLE-6331 FATE#327377 bsc#1145446 LTC#175307).
-rw-r--r--patches.suse/crypto-virtio-register-an-algo-only-if-it-s-supported339
-rw-r--r--series.conf1
2 files changed, 340 insertions, 0 deletions
diff --git a/patches.suse/crypto-virtio-register-an-algo-only-if-it-s-supported b/patches.suse/crypto-virtio-register-an-algo-only-if-it-s-supported
new file mode 100644
index 0000000000..4879510a28
--- /dev/null
+++ b/patches.suse/crypto-virtio-register-an-algo-only-if-it-s-supported
@@ -0,0 +1,339 @@
+From: Farhan Ali <alifm@linux.vnet.ibm.com>
+Date: Tue, 19 Jun 2018 11:41:34 -0400
+Subject: crypto: virtio - Register an algo only if it's supported
+Git-commit: d0d859bb87ac3b4df1cb6692531fc95d093357c5
+Patch-mainline: v4.19-rc1
+References: jsc#SLE-5844 jsc#SLE-6331 FATE#327377 bsc#1145446 LTC#175307
+
+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>
+Acked-by: Petr Tesarik <ptesarik@suse.com>
+---
+ drivers/crypto/virtio/virtio_crypto_algs.c | 112 ++++++++++++++++++---------
+ drivers/crypto/virtio/virtio_crypto_common.h | 11 +-
+ drivers/crypto/virtio/virtio_crypto_mgr.c | 81 ++++++++++++++++++-
+ 3 files changed, 159 insertions(+), 45 deletions(-)
+
+--- a/drivers/crypto/virtio/virtio_crypto_algs.c
++++ b/drivers/crypto/virtio/virtio_crypto_algs.c
+@@ -27,12 +27,18 @@
+ #include <uapi/linux/virtio_crypto.h>
+ #include "virtio_crypto_common.h"
+
++struct virtio_crypto_algo {
++ uint32_t algonum;
++ uint32_t service;
++ unsigned int active_devs;
++ struct crypto_alg algo;
++};
++
+ /*
+ * The algs_lock protects the below global virtio_crypto_active_devs
+ * and crypto algorithms registion.
+ */
+ static DEFINE_MUTEX(algs_lock);
+-static unsigned int virtio_crypto_active_devs;
+
+ static u64 virtio_crypto_alg_sg_nents_length(struct scatterlist *sg)
+ {
+@@ -255,15 +261,21 @@ static int virtio_crypto_ablkcipher_setk
+ unsigned int keylen)
+ {
+ struct virtio_crypto_ablkcipher_ctx *ctx = crypto_ablkcipher_ctx(tfm);
++ uint32_t alg;
+ int ret;
+
++ ret = virtio_crypto_alg_validate_key(keylen, &alg);
++ if (ret)
++ return ret;
++
+ if (!ctx->vcrypto) {
+ /* New key */
+ int node = virtio_crypto_get_current_node();
+ struct virtio_crypto *vcrypto =
+- virtcrypto_get_dev_node(node);
++ virtcrypto_get_dev_node(node,
++ VIRTIO_CRYPTO_SERVICE_CIPHER, alg);
+ if (!vcrypto) {
+- pr_err("virtio_crypto: Could not find a virtio device in the system");
++ pr_err("virtio_crypto: Could not find a virtio device in the system or unsupported algo\n");
+ return -ENODEV;
+ }
+
+@@ -502,57 +514,85 @@ void virtio_crypto_ablkcipher_finalize_r
+ virtcrypto_clear_request(vc_req);
+ }
+
+-static struct crypto_alg virtio_crypto_algs[] = { {
+- .cra_name = "cbc(aes)",
+- .cra_driver_name = "virtio_crypto_aes_cbc",
+- .cra_priority = 150,
+- .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+- .cra_blocksize = AES_BLOCK_SIZE,
+- .cra_ctxsize = sizeof(struct virtio_crypto_ablkcipher_ctx),
+- .cra_alignmask = 0,
+- .cra_module = THIS_MODULE,
+- .cra_type = &crypto_ablkcipher_type,
+- .cra_init = virtio_crypto_ablkcipher_init,
+- .cra_exit = virtio_crypto_ablkcipher_exit,
+- .cra_u = {
+- .ablkcipher = {
+- .setkey = virtio_crypto_ablkcipher_setkey,
+- .decrypt = virtio_crypto_ablkcipher_decrypt,
+- .encrypt = virtio_crypto_ablkcipher_encrypt,
+- .min_keysize = AES_MIN_KEY_SIZE,
+- .max_keysize = AES_MAX_KEY_SIZE,
+- .ivsize = AES_BLOCK_SIZE,
++static struct virtio_crypto_algo virtio_crypto_algs[] = { {
++ .algonum = VIRTIO_CRYPTO_CIPHER_AES_CBC,
++ .service = VIRTIO_CRYPTO_SERVICE_CIPHER,
++ .algo = {
++ .cra_name = "cbc(aes)",
++ .cra_driver_name = "virtio_crypto_aes_cbc",
++ .cra_priority = 150,
++ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
++ .cra_blocksize = AES_BLOCK_SIZE,
++ .cra_ctxsize = sizeof(struct virtio_crypto_ablkcipher_ctx),
++ .cra_alignmask = 0,
++ .cra_module = THIS_MODULE,
++ .cra_type = &crypto_ablkcipher_type,
++ .cra_init = virtio_crypto_ablkcipher_init,
++ .cra_exit = virtio_crypto_ablkcipher_exit,
++ .cra_u = {
++ .ablkcipher = {
++ .setkey = virtio_crypto_ablkcipher_setkey,
++ .decrypt = virtio_crypto_ablkcipher_decrypt,
++ .encrypt = virtio_crypto_ablkcipher_encrypt,
++ .min_keysize = AES_MIN_KEY_SIZE,
++ .max_keysize = AES_MAX_KEY_SIZE,
++ .ivsize = AES_BLOCK_SIZE,
++ },
+ },
+ },
+ } };
+
+-int virtio_crypto_algs_register(void)
++int virtio_crypto_algs_register(struct virtio_crypto *vcrypto)
+ {
+ int ret = 0;
++ int i = 0;
+
+ mutex_lock(&algs_lock);
+- if (++virtio_crypto_active_devs != 1)
+- goto unlock;
+
+- ret = crypto_register_algs(virtio_crypto_algs,
+- ARRAY_SIZE(virtio_crypto_algs));
+- if (ret)
+- virtio_crypto_active_devs--;
++ for (i = 0; i < ARRAY_SIZE(virtio_crypto_algs); i++) {
++
++ uint32_t service = virtio_crypto_algs[i].service;
++ uint32_t algonum = virtio_crypto_algs[i].algonum;
++
++ if (!virtcrypto_algo_is_supported(vcrypto, service, algonum))
++ continue;
++
++ if (virtio_crypto_algs[i].active_devs == 0) {
++ ret = crypto_register_alg(&virtio_crypto_algs[i].algo);
++ if (ret)
++ goto unlock;
++ }
++
++ virtio_crypto_algs[i].active_devs++;
++ dev_info(&vcrypto->vdev->dev, "Registered algo %s\n",
++ virtio_crypto_algs[i].algo.cra_name);
++ }
+
+ unlock:
+ mutex_unlock(&algs_lock);
+ return ret;
+ }
+
+-void virtio_crypto_algs_unregister(void)
++void virtio_crypto_algs_unregister(struct virtio_crypto *vcrypto)
+ {
++ int i = 0;
++
+ mutex_lock(&algs_lock);
+- if (--virtio_crypto_active_devs != 0)
+- goto unlock;
+
+- crypto_unregister_algs(virtio_crypto_algs,
+- ARRAY_SIZE(virtio_crypto_algs));
++ for (i = 0; i < ARRAY_SIZE(virtio_crypto_algs); i++) {
++
++ uint32_t service = virtio_crypto_algs[i].service;
++ uint32_t algonum = virtio_crypto_algs[i].algonum;
++
++ if (virtio_crypto_algs[i].active_devs == 0 ||
++ !virtcrypto_algo_is_supported(vcrypto, service, algonum))
++ continue;
++
++ if (virtio_crypto_algs[i].active_devs == 1)
++ crypto_unregister_alg(&virtio_crypto_algs[i].algo);
++
++ virtio_crypto_algs[i].active_devs--;
++ }
+
+-unlock:
+ mutex_unlock(&algs_lock);
+ }
+--- a/drivers/crypto/virtio/virtio_crypto_common.h
++++ b/drivers/crypto/virtio/virtio_crypto_common.h
+@@ -126,7 +126,12 @@ int virtcrypto_dev_in_use(struct virtio_
+ int virtcrypto_dev_get(struct virtio_crypto *vcrypto_dev);
+ void virtcrypto_dev_put(struct virtio_crypto *vcrypto_dev);
+ int virtcrypto_dev_started(struct virtio_crypto *vcrypto_dev);
+-struct virtio_crypto *virtcrypto_get_dev_node(int node);
++bool virtcrypto_algo_is_supported(struct virtio_crypto *vcrypto_dev,
++ uint32_t service,
++ uint32_t algo);
++struct virtio_crypto *virtcrypto_get_dev_node(int node,
++ uint32_t service,
++ uint32_t algo);
+ int virtcrypto_dev_start(struct virtio_crypto *vcrypto);
+ void virtcrypto_dev_stop(struct virtio_crypto *vcrypto);
+ int virtio_crypto_ablkcipher_crypt_req(
+@@ -151,7 +156,7 @@ static inline int virtio_crypto_get_curr
+ return node;
+ }
+
+-int virtio_crypto_algs_register(void);
+-void virtio_crypto_algs_unregister(void);
++int virtio_crypto_algs_register(struct virtio_crypto *vcrypto);
++void virtio_crypto_algs_unregister(struct virtio_crypto *vcrypto);
+
+ #endif /* _VIRTIO_CRYPTO_COMMON_H */
+--- a/drivers/crypto/virtio/virtio_crypto_mgr.c
++++ b/drivers/crypto/virtio/virtio_crypto_mgr.c
+@@ -181,14 +181,20 @@ int virtcrypto_dev_started(struct virtio
+ /*
+ * 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
+
+ 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
+ /* 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
+ */
+ 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_c
+ */
+ 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;
+ }
diff --git a/series.conf b/series.conf
index 03d59d3ec6..2efd29769c 100644
--- a/series.conf
+++ b/series.conf
@@ -37091,6 +37091,7 @@
patches.suse/crypto-vmac-require-a-block-cipher-with-128-bit-bloc
patches.suse/crypto-vmac-separate-tfm-and-request-context
patches.suse/crypto-virtio-read-crypto-services-and-algorithm-masks
+ patches.suse/crypto-virtio-register-an-algo-only-if-it-s-supported
patches.suse/crypto-skcipher-Fix-Wstringop-truncation-warnings.patch
patches.suse/crypto-x86-sha256-mb-fix-digest-copy-in-sha256_mb_mg
patches.suse/crypto-ccp-Fix-command-completion-detection-race