Skip to content

Commit 3c3a24c

Browse files
committed
crypto: api - Add crypto_clone_tfm
This patch adds the helper crypto_clone_tfm. The purpose is to allocate a tfm object with GFP_ATOMIC. As we cannot sleep, the object has to be cloned from an existing tfm object. This allows code paths that cannot otherwise allocate a crypto_tfm object to do so. Once a new tfm has been obtained its key could then be changed without impacting other users. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Reviewed-by: Simon Horman <simon.horman@corigine.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
1 parent ae131f4 commit 3c3a24c

File tree

2 files changed

+52
-9
lines changed

2 files changed

+52
-9
lines changed

crypto/api.c

Lines changed: 50 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -488,28 +488,44 @@ struct crypto_tfm *crypto_alloc_base(const char *alg_name, u32 type, u32 mask)
488488
}
489489
EXPORT_SYMBOL_GPL(crypto_alloc_base);
490490

491-
void *crypto_create_tfm_node(struct crypto_alg *alg,
492-
const struct crypto_type *frontend,
493-
int node)
491+
static void *crypto_alloc_tfmmem(struct crypto_alg *alg,
492+
const struct crypto_type *frontend, int node,
493+
gfp_t gfp)
494494
{
495-
char *mem;
496-
struct crypto_tfm *tfm = NULL;
495+
struct crypto_tfm *tfm;
497496
unsigned int tfmsize;
498497
unsigned int total;
499-
int err = -ENOMEM;
498+
char *mem;
500499

501500
tfmsize = frontend->tfmsize;
502501
total = tfmsize + sizeof(*tfm) + frontend->extsize(alg);
503502

504-
mem = kzalloc_node(total, GFP_KERNEL, node);
503+
mem = kzalloc_node(total, gfp, node);
505504
if (mem == NULL)
506-
goto out_err;
505+
return ERR_PTR(-ENOMEM);
507506

508507
tfm = (struct crypto_tfm *)(mem + tfmsize);
509508
tfm->__crt_alg = alg;
510509
tfm->node = node;
511510
refcount_set(&tfm->refcnt, 1);
512511

512+
return mem;
513+
}
514+
515+
void *crypto_create_tfm_node(struct crypto_alg *alg,
516+
const struct crypto_type *frontend,
517+
int node)
518+
{
519+
struct crypto_tfm *tfm;
520+
char *mem;
521+
int err;
522+
523+
mem = crypto_alloc_tfmmem(alg, frontend, node, GFP_KERNEL);
524+
if (IS_ERR(mem))
525+
goto out;
526+
527+
tfm = (struct crypto_tfm *)(mem + frontend->tfmsize);
528+
513529
err = frontend->init_tfm(tfm);
514530
if (err)
515531
goto out_free_tfm;
@@ -525,13 +541,38 @@ void *crypto_create_tfm_node(struct crypto_alg *alg,
525541
if (err == -EAGAIN)
526542
crypto_shoot_alg(alg);
527543
kfree(mem);
528-
out_err:
529544
mem = ERR_PTR(err);
530545
out:
531546
return mem;
532547
}
533548
EXPORT_SYMBOL_GPL(crypto_create_tfm_node);
534549

550+
void *crypto_clone_tfm(const struct crypto_type *frontend,
551+
struct crypto_tfm *otfm)
552+
{
553+
struct crypto_alg *alg = otfm->__crt_alg;
554+
struct crypto_tfm *tfm;
555+
char *mem;
556+
557+
mem = ERR_PTR(-ESTALE);
558+
if (unlikely(!crypto_mod_get(alg)))
559+
goto out;
560+
561+
mem = crypto_alloc_tfmmem(alg, frontend, otfm->node, GFP_ATOMIC);
562+
if (IS_ERR(mem)) {
563+
crypto_mod_put(alg);
564+
goto out;
565+
}
566+
567+
tfm = (struct crypto_tfm *)(mem + frontend->tfmsize);
568+
tfm->crt_flags = otfm->crt_flags;
569+
tfm->exit = otfm->exit;
570+
571+
out:
572+
return mem;
573+
}
574+
EXPORT_SYMBOL_GPL(crypto_clone_tfm);
575+
535576
struct crypto_alg *crypto_find_alg(const char *alg_name,
536577
const struct crypto_type *frontend,
537578
u32 type, u32 mask)

crypto/internal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type,
106106
u32 mask);
107107
void *crypto_create_tfm_node(struct crypto_alg *alg,
108108
const struct crypto_type *frontend, int node);
109+
void *crypto_clone_tfm(const struct crypto_type *frontend,
110+
struct crypto_tfm *otfm);
109111

110112
static inline void *crypto_create_tfm(struct crypto_alg *alg,
111113
const struct crypto_type *frontend)

0 commit comments

Comments
 (0)