Skip to content

Commit d0d859b

Browse files
Farhan Aliherbertx
authored andcommitted
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>
1 parent b551bac commit d0d859b

File tree

3 files changed

+159
-45
lines changed

3 files changed

+159
-45
lines changed

drivers/crypto/virtio/virtio_crypto_algs.c

Lines changed: 76 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,18 @@ struct virtio_crypto_sym_request {
4949
bool encrypt;
5050
};
5151

52+
struct virtio_crypto_algo {
53+
uint32_t algonum;
54+
uint32_t service;
55+
unsigned int active_devs;
56+
struct crypto_alg algo;
57+
};
58+
5259
/*
5360
* The algs_lock protects the below global virtio_crypto_active_devs
5461
* and crypto algorithms registion.
5562
*/
5663
static DEFINE_MUTEX(algs_lock);
57-
static unsigned int virtio_crypto_active_devs;
5864
static void virtio_crypto_ablkcipher_finalize_req(
5965
struct virtio_crypto_sym_request *vc_sym_req,
6066
struct ablkcipher_request *req,
@@ -312,15 +318,21 @@ static int virtio_crypto_ablkcipher_setkey(struct crypto_ablkcipher *tfm,
312318
unsigned int keylen)
313319
{
314320
struct virtio_crypto_ablkcipher_ctx *ctx = crypto_ablkcipher_ctx(tfm);
321+
uint32_t alg;
315322
int ret;
316323

324+
ret = virtio_crypto_alg_validate_key(keylen, &alg);
325+
if (ret)
326+
return ret;
327+
317328
if (!ctx->vcrypto) {
318329
/* New key */
319330
int node = virtio_crypto_get_current_node();
320331
struct virtio_crypto *vcrypto =
321-
virtcrypto_get_dev_node(node);
332+
virtcrypto_get_dev_node(node,
333+
VIRTIO_CRYPTO_SERVICE_CIPHER, alg);
322334
if (!vcrypto) {
323-
pr_err("virtio_crypto: Could not find a virtio device in the system\n");
335+
pr_err("virtio_crypto: Could not find a virtio device in the system or unsupported algo\n");
324336
return -ENODEV;
325337
}
326338

@@ -571,57 +583,85 @@ static void virtio_crypto_ablkcipher_finalize_req(
571583
virtcrypto_clear_request(&vc_sym_req->base);
572584
}
573585

574-
static struct crypto_alg virtio_crypto_algs[] = { {
575-
.cra_name = "cbc(aes)",
576-
.cra_driver_name = "virtio_crypto_aes_cbc",
577-
.cra_priority = 150,
578-
.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
579-
.cra_blocksize = AES_BLOCK_SIZE,
580-
.cra_ctxsize = sizeof(struct virtio_crypto_ablkcipher_ctx),
581-
.cra_alignmask = 0,
582-
.cra_module = THIS_MODULE,
583-
.cra_type = &crypto_ablkcipher_type,
584-
.cra_init = virtio_crypto_ablkcipher_init,
585-
.cra_exit = virtio_crypto_ablkcipher_exit,
586-
.cra_u = {
587-
.ablkcipher = {
588-
.setkey = virtio_crypto_ablkcipher_setkey,
589-
.decrypt = virtio_crypto_ablkcipher_decrypt,
590-
.encrypt = virtio_crypto_ablkcipher_encrypt,
591-
.min_keysize = AES_MIN_KEY_SIZE,
592-
.max_keysize = AES_MAX_KEY_SIZE,
593-
.ivsize = AES_BLOCK_SIZE,
586+
static struct virtio_crypto_algo virtio_crypto_algs[] = { {
587+
.algonum = VIRTIO_CRYPTO_CIPHER_AES_CBC,
588+
.service = VIRTIO_CRYPTO_SERVICE_CIPHER,
589+
.algo = {
590+
.cra_name = "cbc(aes)",
591+
.cra_driver_name = "virtio_crypto_aes_cbc",
592+
.cra_priority = 150,
593+
.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
594+
.cra_blocksize = AES_BLOCK_SIZE,
595+
.cra_ctxsize = sizeof(struct virtio_crypto_ablkcipher_ctx),
596+
.cra_alignmask = 0,
597+
.cra_module = THIS_MODULE,
598+
.cra_type = &crypto_ablkcipher_type,
599+
.cra_init = virtio_crypto_ablkcipher_init,
600+
.cra_exit = virtio_crypto_ablkcipher_exit,
601+
.cra_u = {
602+
.ablkcipher = {
603+
.setkey = virtio_crypto_ablkcipher_setkey,
604+
.decrypt = virtio_crypto_ablkcipher_decrypt,
605+
.encrypt = virtio_crypto_ablkcipher_encrypt,
606+
.min_keysize = AES_MIN_KEY_SIZE,
607+
.max_keysize = AES_MAX_KEY_SIZE,
608+
.ivsize = AES_BLOCK_SIZE,
609+
},
594610
},
595611
},
596612
} };
597613

598-
int virtio_crypto_algs_register(void)
614+
int virtio_crypto_algs_register(struct virtio_crypto *vcrypto)
599615
{
600616
int ret = 0;
617+
int i = 0;
601618

602619
mutex_lock(&algs_lock);
603-
if (++virtio_crypto_active_devs != 1)
604-
goto unlock;
605620

606-
ret = crypto_register_algs(virtio_crypto_algs,
607-
ARRAY_SIZE(virtio_crypto_algs));
608-
if (ret)
609-
virtio_crypto_active_devs--;
621+
for (i = 0; i < ARRAY_SIZE(virtio_crypto_algs); i++) {
622+
623+
uint32_t service = virtio_crypto_algs[i].service;
624+
uint32_t algonum = virtio_crypto_algs[i].algonum;
625+
626+
if (!virtcrypto_algo_is_supported(vcrypto, service, algonum))
627+
continue;
628+
629+
if (virtio_crypto_algs[i].active_devs == 0) {
630+
ret = crypto_register_alg(&virtio_crypto_algs[i].algo);
631+
if (ret)
632+
goto unlock;
633+
}
634+
635+
virtio_crypto_algs[i].active_devs++;
636+
dev_info(&vcrypto->vdev->dev, "Registered algo %s\n",
637+
virtio_crypto_algs[i].algo.cra_name);
638+
}
610639

611640
unlock:
612641
mutex_unlock(&algs_lock);
613642
return ret;
614643
}
615644

616-
void virtio_crypto_algs_unregister(void)
645+
void virtio_crypto_algs_unregister(struct virtio_crypto *vcrypto)
617646
{
647+
int i = 0;
648+
618649
mutex_lock(&algs_lock);
619-
if (--virtio_crypto_active_devs != 0)
620-
goto unlock;
621650

622-
crypto_unregister_algs(virtio_crypto_algs,
623-
ARRAY_SIZE(virtio_crypto_algs));
651+
for (i = 0; i < ARRAY_SIZE(virtio_crypto_algs); i++) {
652+
653+
uint32_t service = virtio_crypto_algs[i].service;
654+
uint32_t algonum = virtio_crypto_algs[i].algonum;
655+
656+
if (virtio_crypto_algs[i].active_devs == 0 ||
657+
!virtcrypto_algo_is_supported(vcrypto, service, algonum))
658+
continue;
659+
660+
if (virtio_crypto_algs[i].active_devs == 1)
661+
crypto_unregister_alg(&virtio_crypto_algs[i].algo);
662+
663+
virtio_crypto_algs[i].active_devs--;
664+
}
624665

625-
unlock:
626666
mutex_unlock(&algs_lock);
627667
}

drivers/crypto/virtio/virtio_crypto_common.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,12 @@ int virtcrypto_dev_in_use(struct virtio_crypto *vcrypto_dev);
116116
int virtcrypto_dev_get(struct virtio_crypto *vcrypto_dev);
117117
void virtcrypto_dev_put(struct virtio_crypto *vcrypto_dev);
118118
int virtcrypto_dev_started(struct virtio_crypto *vcrypto_dev);
119-
struct virtio_crypto *virtcrypto_get_dev_node(int node);
119+
bool virtcrypto_algo_is_supported(struct virtio_crypto *vcrypto_dev,
120+
uint32_t service,
121+
uint32_t algo);
122+
struct virtio_crypto *virtcrypto_get_dev_node(int node,
123+
uint32_t service,
124+
uint32_t algo);
120125
int virtcrypto_dev_start(struct virtio_crypto *vcrypto);
121126
void virtcrypto_dev_stop(struct virtio_crypto *vcrypto);
122127
int virtio_crypto_ablkcipher_crypt_req(
@@ -136,7 +141,7 @@ static inline int virtio_crypto_get_current_node(void)
136141
return node;
137142
}
138143

139-
int virtio_crypto_algs_register(void);
140-
void virtio_crypto_algs_unregister(void);
144+
int virtio_crypto_algs_register(struct virtio_crypto *vcrypto);
145+
void virtio_crypto_algs_unregister(struct virtio_crypto *vcrypto);
141146

142147
#endif /* _VIRTIO_CRYPTO_COMMON_H */

drivers/crypto/virtio/virtio_crypto_mgr.c

Lines changed: 75 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -181,14 +181,20 @@ int virtcrypto_dev_started(struct virtio_crypto *vcrypto_dev)
181181
/*
182182
* virtcrypto_get_dev_node() - Get vcrypto_dev on the node.
183183
* @node: Node id the driver works.
184+
* @service: Crypto service that needs to be supported by the
185+
* dev
186+
* @algo: The algorithm number that needs to be supported by the
187+
* dev
184188
*
185-
* Function returns the virtio crypto device used fewest on the node.
189+
* Function returns the virtio crypto device used fewest on the node,
190+
* and supports the given crypto service and algorithm.
186191
*
187192
* To be used by virtio crypto device specific drivers.
188193
*
189194
* Return: pointer to vcrypto_dev or NULL if not found.
190195
*/
191-
struct virtio_crypto *virtcrypto_get_dev_node(int node)
196+
struct virtio_crypto *virtcrypto_get_dev_node(int node, uint32_t service,
197+
uint32_t algo)
192198
{
193199
struct virtio_crypto *vcrypto_dev = NULL, *tmp_dev;
194200
unsigned long best = ~0;
@@ -199,7 +205,8 @@ struct virtio_crypto *virtcrypto_get_dev_node(int node)
199205

200206
if ((node == dev_to_node(&tmp_dev->vdev->dev) ||
201207
dev_to_node(&tmp_dev->vdev->dev) < 0) &&
202-
virtcrypto_dev_started(tmp_dev)) {
208+
virtcrypto_dev_started(tmp_dev) &&
209+
virtcrypto_algo_is_supported(tmp_dev, service, algo)) {
203210
ctr = atomic_read(&tmp_dev->ref_count);
204211
if (best > ctr) {
205212
vcrypto_dev = tmp_dev;
@@ -214,7 +221,9 @@ struct virtio_crypto *virtcrypto_get_dev_node(int node)
214221
/* Get any started device */
215222
list_for_each_entry(tmp_dev,
216223
virtcrypto_devmgr_get_head(), list) {
217-
if (virtcrypto_dev_started(tmp_dev)) {
224+
if (virtcrypto_dev_started(tmp_dev) &&
225+
virtcrypto_algo_is_supported(tmp_dev,
226+
service, algo)) {
218227
vcrypto_dev = tmp_dev;
219228
break;
220229
}
@@ -240,7 +249,7 @@ struct virtio_crypto *virtcrypto_get_dev_node(int node)
240249
*/
241250
int virtcrypto_dev_start(struct virtio_crypto *vcrypto)
242251
{
243-
if (virtio_crypto_algs_register()) {
252+
if (virtio_crypto_algs_register(vcrypto)) {
244253
pr_err("virtio_crypto: Failed to register crypto algs\n");
245254
return -EFAULT;
246255
}
@@ -260,5 +269,65 @@ int virtcrypto_dev_start(struct virtio_crypto *vcrypto)
260269
*/
261270
void virtcrypto_dev_stop(struct virtio_crypto *vcrypto)
262271
{
263-
virtio_crypto_algs_unregister();
272+
virtio_crypto_algs_unregister(vcrypto);
273+
}
274+
275+
/*
276+
* vcrypto_algo_is_supported()
277+
* @vcrypto: Pointer to virtio crypto device.
278+
* @service: The bit number for service validate.
279+
* See VIRTIO_CRYPTO_SERVICE_*
280+
* @algo : The bit number for the algorithm to validate.
281+
*
282+
*
283+
* Validate if the virtio crypto device supports a service and
284+
* algo.
285+
*
286+
* Return true if device supports a service and algo.
287+
*/
288+
289+
bool virtcrypto_algo_is_supported(struct virtio_crypto *vcrypto,
290+
uint32_t service,
291+
uint32_t algo)
292+
{
293+
uint32_t service_mask = 1u << service;
294+
uint32_t algo_mask = 0;
295+
bool low = true;
296+
297+
if (algo > 31) {
298+
algo -= 32;
299+
low = false;
300+
}
301+
302+
if (!(vcrypto->crypto_services & service_mask))
303+
return false;
304+
305+
switch (service) {
306+
case VIRTIO_CRYPTO_SERVICE_CIPHER:
307+
if (low)
308+
algo_mask = vcrypto->cipher_algo_l;
309+
else
310+
algo_mask = vcrypto->cipher_algo_h;
311+
break;
312+
313+
case VIRTIO_CRYPTO_SERVICE_HASH:
314+
algo_mask = vcrypto->hash_algo;
315+
break;
316+
317+
case VIRTIO_CRYPTO_SERVICE_MAC:
318+
if (low)
319+
algo_mask = vcrypto->mac_algo_l;
320+
else
321+
algo_mask = vcrypto->mac_algo_h;
322+
break;
323+
324+
case VIRTIO_CRYPTO_SERVICE_AEAD:
325+
algo_mask = vcrypto->aead_algo;
326+
break;
327+
}
328+
329+
if (!(algo_mask & (1u << algo)))
330+
return false;
331+
332+
return true;
264333
}

0 commit comments

Comments
 (0)