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:
@@ -49,12 +49,18 @@ struct virtio_crypto_sym_request {
|
||||
bool encrypt;
|
||||
};
|
||||
|
||||
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 void virtio_crypto_ablkcipher_finalize_req(
|
||||
struct virtio_crypto_sym_request *vc_sym_req,
|
||||
struct ablkcipher_request *req,
|
||||
@@ -312,15 +318,21 @@ static int virtio_crypto_ablkcipher_setkey(struct crypto_ablkcipher *tfm,
|
||||
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\n");
|
||||
pr_err("virtio_crypto: Could not find a virtio device in the system or unsupported algo\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
@@ -571,57 +583,85 @@ static void virtio_crypto_ablkcipher_finalize_req(
|
||||
virtcrypto_clear_request(&vc_sym_req->base);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user