From: Herbert Xu <herbert.xu@redhat.com> Date: Mon, 7 Jan 2008 20:56:02 +1100 Subject: [crypto] api: add new top-level crypto_api Message-id: 20080107095602.GA24258@gondor.apana.org.au O-Subject: Re: [PATCH 1/32] [CRYPTO] api: Add new top-level crypto_api Bugzilla: 253051 [CRYPTO] api: Add new top-level crypto_api This changeset backports the new top-level crypto API structure to 2.6.18. For ABI compatibility it will coexist with the old top-level API. Where names conflict the new API has been renamed as ncrypto instead of crypto. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Acked-by: "David S. Miller" <davem@redhat.com> Acked-by: James Morris <jmorris@redhat.com> diff --git a/crypto/Kconfig b/crypto/Kconfig index b2037ed..1f2ebe0 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -9,6 +9,12 @@ config CRYPTO help This option provides the core Cryptographic API. +config CRYPTO_API + tristate + depends on CRYPTO + help + This option provides the (backported) core Cryptographic API. + config CRYPTO_HMAC bool "HMAC support" depends on CRYPTO diff --git a/crypto/Makefile b/crypto/Makefile index ded7e7b..59c93e8 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -7,6 +7,7 @@ proc-crypto-$(CONFIG_PROC_FS) = proc.o obj-$(CONFIG_CRYPTO) += api.o scatterwalk.o cipher.o digest.o compress.o \ $(proc-crypto-y) +obj-$(CONFIG_CRYPTO_API) += crypto_api.o obj-$(CONFIG_CRYPTO_HMAC) += hmac.o obj-$(CONFIG_CRYPTO_NULL) += crypto_null.o obj-$(CONFIG_CRYPTO_MD4) += md4.o diff --git a/crypto/crypto_api.c b/crypto/crypto_api.c new file mode 100644 index 0000000..a7fd196 --- /dev/null +++ b/crypto/crypto_api.c @@ -0,0 +1,403 @@ +/* + * Scatterlist Cryptographic API. + * + * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> + * Copyright (c) 2002 David S. Miller (davem@redhat.com) + * Copyright (c) 2005 Herbert Xu <herbert@gondor.apana.org.au> + * + * Portions derived from Cryptoapi, by Alexander Kjeldaas <astor@fast.no> + * and Nettle, by Niels Möller. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ + +#include <linux/err.h> +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/kmod.h> +#include <linux/module.h> +#include <linux/param.h> +#include <linux/sched.h> +#include <linux/slab.h> +#include <linux/string.h> + +#include "ninternal.h" + +LIST_HEAD(ncrypto_alg_list); +EXPORT_SYMBOL_GPL(ncrypto_alg_list); +DECLARE_RWSEM(ncrypto_alg_sem); +EXPORT_SYMBOL_GPL(ncrypto_alg_sem); + +BLOCKING_NOTIFIER_HEAD(crypto_chain); +EXPORT_SYMBOL_GPL(crypto_chain); + +static inline struct ncrypto_alg *ncrypto_alg_get(struct ncrypto_alg *alg) +{ + atomic_inc(&alg->cra_refcnt); + return alg; +} + +struct ncrypto_alg *crypto_mod_get(struct ncrypto_alg *alg) +{ + return try_module_get(alg->cra_module) ? ncrypto_alg_get(alg) : NULL; +} +EXPORT_SYMBOL_GPL(crypto_mod_get); + +void crypto_mod_put(struct ncrypto_alg *alg) +{ + struct module *module = alg->cra_module; + + ncrypto_alg_put(alg); + module_put(module); +} +EXPORT_SYMBOL_GPL(crypto_mod_put); + +struct ncrypto_alg *__crypto_alg_lookup(const char *name, u32 type, u32 mask) +{ + struct ncrypto_alg *q, *alg = NULL; + int best = -2; + + list_for_each_entry(q, &ncrypto_alg_list, cra_list) { + int exact, fuzzy; + + if (crypto_is_moribund(q)) + continue; + + if ((q->cra_flags ^ type) & mask) + continue; + + if (crypto_is_larval(q) && + ((struct crypto_larval *)q)->mask != mask) + continue; + + exact = !strcmp(q->cra_driver_name, name); + fuzzy = !strcmp(q->cra_name, name); + if (!exact && !(fuzzy && q->cra_priority > best)) + continue; + + if (unlikely(!crypto_mod_get(q))) + continue; + + best = q->cra_priority; + if (alg) + crypto_mod_put(alg); + alg = q; + + if (exact) + break; + } + + return alg; +} +EXPORT_SYMBOL_GPL(__crypto_alg_lookup); + +static void crypto_larval_destroy(struct ncrypto_alg *alg) +{ + struct crypto_larval *larval = (void *)alg; + + BUG_ON(!crypto_is_larval(alg)); + if (larval->adult) + crypto_mod_put(larval->adult); + kfree(larval); +} + +static struct ncrypto_alg *crypto_larval_alloc(const char *name, u32 type, + u32 mask) +{ + struct ncrypto_alg *alg; + struct crypto_larval *larval; + + larval = kzalloc(sizeof(*larval), GFP_KERNEL); + if (!larval) + return ERR_PTR(-ENOMEM); + + larval->mask = mask; + larval->alg.cra_flags = NCRYPTO_ALG_LARVAL | type; + larval->alg.cra_priority = -1; + larval->alg.cra_destroy = crypto_larval_destroy; + + atomic_set(&larval->alg.cra_refcnt, 2); + strlcpy(larval->alg.cra_name, name, CRYPTO_MAX_ALG_NAME); + init_completion(&larval->completion); + + down_write(&ncrypto_alg_sem); + alg = __crypto_alg_lookup(name, type, mask); + if (!alg) { + alg = &larval->alg; + list_add(&alg->cra_list, &ncrypto_alg_list); + } + up_write(&ncrypto_alg_sem); + + if (alg != &larval->alg) + kfree(larval); + + return alg; +} + +void crypto_larval_kill(struct ncrypto_alg *alg) +{ + struct crypto_larval *larval = (void *)alg; + + down_write(&ncrypto_alg_sem); + list_del(&alg->cra_list); + up_write(&ncrypto_alg_sem); + complete_all(&larval->completion); + ncrypto_alg_put(alg); +} +EXPORT_SYMBOL_GPL(crypto_larval_kill); + +static struct ncrypto_alg *crypto_larval_wait(struct ncrypto_alg *alg) +{ + struct crypto_larval *larval = (void *)alg; + + wait_for_completion_interruptible_timeout(&larval->completion, 60 * HZ); + alg = larval->adult; + if (alg) { + if (!crypto_mod_get(alg)) + alg = ERR_PTR(-EAGAIN); + } else + alg = ERR_PTR(-ENOENT); + crypto_mod_put(&larval->alg); + + return alg; +} + +static struct ncrypto_alg *crypto_alg_lookup(const char *name, u32 type, + u32 mask) +{ + struct ncrypto_alg *alg; + + down_read(&ncrypto_alg_sem); + alg = __crypto_alg_lookup(name, type, mask); + up_read(&ncrypto_alg_sem); + + return alg; +} + +struct ncrypto_alg *crypto_larval_lookup(const char *name, u32 type, u32 mask) +{ + struct ncrypto_alg *alg; + + if (!name) + return ERR_PTR(-ENOENT); + + mask &= ~(NCRYPTO_ALG_LARVAL | NCRYPTO_ALG_DEAD); + type &= mask; + + alg = try_then_request_module(crypto_alg_lookup(name, type, mask), + name); + if (alg) + return crypto_is_larval(alg) ? crypto_larval_wait(alg) : alg; + + return crypto_larval_alloc(name, type, mask); +} +EXPORT_SYMBOL_GPL(crypto_larval_lookup); + +struct ncrypto_alg *ncrypto_alg_mod_lookup(const char *name, u32 type, u32 mask) +{ + struct ncrypto_alg *alg; + struct ncrypto_alg *larval; + int ok; + + larval = crypto_larval_lookup(name, type, mask); + if (IS_ERR(larval) || !crypto_is_larval(larval)) + return larval; + + ok = crypto_notify(CRYPTO_MSG_ALG_REQUEST, larval); + if (ok == NOTIFY_DONE) { + request_module("cryptomgr"); + ok = crypto_notify(CRYPTO_MSG_ALG_REQUEST, larval); + } + + if (ok == NOTIFY_STOP) + alg = crypto_larval_wait(larval); + else { + crypto_mod_put(larval); + alg = ERR_PTR(-ENOENT); + } + crypto_larval_kill(larval); + return alg; +} +EXPORT_SYMBOL_GPL(ncrypto_alg_mod_lookup); + +static int crypto_init_ops(struct ncrypto_tfm *tfm, u32 type, u32 mask) +{ + return tfm->__crt_alg->cra_type->init(tfm, type, mask); +} + +static void crypto_exit_ops(struct ncrypto_tfm *tfm) +{ + const struct crypto_type *type = tfm->__crt_alg->cra_type; + + if (type->exit) + type->exit(tfm); + return; +} + +static unsigned int crypto_ctxsize(struct ncrypto_alg *alg, u32 type, u32 mask) +{ + unsigned int len; + + len = alg->cra_alignmask & ~(ncrypto_tfm_ctx_alignment() - 1); + return len + alg->cra_type->ctxsize(alg, type, mask); +} + +void crypto_shoot_alg(struct ncrypto_alg *alg) +{ + down_write(&ncrypto_alg_sem); + alg->cra_flags |= NCRYPTO_ALG_DYING; + up_write(&ncrypto_alg_sem); +} +EXPORT_SYMBOL_GPL(crypto_shoot_alg); + +struct ncrypto_tfm *__crypto_alloc_tfm(struct ncrypto_alg *alg, u32 type, + u32 mask) +{ + struct ncrypto_tfm *tfm = NULL; + unsigned int tfm_size; + int err = -ENOMEM; + + tfm_size = sizeof(*tfm) + crypto_ctxsize(alg, type, mask); + tfm = kzalloc(tfm_size, GFP_KERNEL); + if (tfm == NULL) + goto out_err; + + tfm->__crt_alg = alg; + + err = crypto_init_ops(tfm, type, mask); + if (err) + goto out_free_tfm; + + if (alg->cra_init && (err = alg->cra_init(tfm))) { + if (err == -EAGAIN) + crypto_shoot_alg(alg); + goto cra_init_failed; + } + + goto out; + +cra_init_failed: + crypto_exit_ops(tfm); +out_free_tfm: + kfree(tfm); +out_err: + tfm = ERR_PTR(err); +out: + return tfm; +} +EXPORT_SYMBOL_GPL(__crypto_alloc_tfm); + +/* + * crypto_alloc_base - Locate algorithm and allocate transform + * @alg_name: Name of algorithm + * @type: Type of algorithm + * @mask: Mask for type comparison + * + * crypto_alloc_base() will first attempt to locate an already loaded + * algorithm. If that fails and the kernel supports dynamically loadable + * modules, it will then attempt to load a module of the same name or + * alias. If that fails it will send a query to any loaded crypto manager + * to construct an algorithm on the fly. A refcount is grabbed on the + * algorithm which is then associated with the new transform. + * + * The returned transform is of a non-determinate type. Most people + * should use one of the more specific allocation functions such as + * crypto_alloc_blkcipher. + * + * In case of error the return value is an error pointer. + */ +struct ncrypto_tfm *crypto_alloc_base(const char *alg_name, u32 type, u32 mask) +{ + struct ncrypto_tfm *tfm; + int err; + + for (;;) { + struct ncrypto_alg *alg; + + alg = ncrypto_alg_mod_lookup(alg_name, type, mask); + if (IS_ERR(alg)) { + err = PTR_ERR(alg); + goto err; + } + + tfm = __crypto_alloc_tfm(alg, type, mask); + if (!IS_ERR(tfm)) + return tfm; + + crypto_mod_put(alg); + err = PTR_ERR(tfm); + +err: + if (err != -EAGAIN) + break; + if (signal_pending(current)) { + err = -EINTR; + break; + } + } + + return ERR_PTR(err); +} +EXPORT_SYMBOL_GPL(crypto_alloc_base); + +/* + * ncrypto_free_tfm - Free crypto transform + * @tfm: Transform to free + * + * ncrypto_free_tfm() frees up the transform and any associated resources, + * then drops the refcount on the associated algorithm. + */ +void ncrypto_free_tfm(struct ncrypto_tfm *tfm) +{ + struct ncrypto_alg *alg; + int size; + + if (unlikely(!tfm)) + return; + + alg = tfm->__crt_alg; + size = sizeof(*tfm) + alg->cra_ctxsize; + + if (alg->cra_exit) + alg->cra_exit(tfm); + crypto_exit_ops(tfm); + crypto_mod_put(alg); + memset(tfm, 0, size); + kfree(tfm); +} + +EXPORT_SYMBOL_GPL(ncrypto_free_tfm); + +int crypto_has_alg(const char *name, u32 type, u32 mask) +{ + int ret = 0; + struct ncrypto_alg *alg = ncrypto_alg_mod_lookup(name, type, mask); + + if (!IS_ERR(alg)) { + crypto_mod_put(alg); + ret = 1; + } + + return ret; +} +EXPORT_SYMBOL_GPL(crypto_has_alg); + +static int __init crypto_api_init(void) +{ + return 0; +} + +static void __exit crypto_api_exit(void) +{ +} + +module_init(crypto_api_init); +module_exit(crypto_api_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Cryptographic API (backported)"); diff --git a/crypto/ninternal.h b/crypto/ninternal.h new file mode 100644 index 0000000..981ea36 --- /dev/null +++ b/crypto/ninternal.h @@ -0,0 +1,80 @@ +/* + * Cryptographic API. + * + * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> + * Copyright (c) 2005 Herbert Xu <herbert@gondor.apana.org.au> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ +#ifndef _CRYPTO_NINTERNAL_H +#define _CRYPTO_NINTERNAL_H + +#include <crypto/algapi.h> +#include <linux/notifier.h> + +#include "internal.h" + +/* Crypto notification events. */ +enum { + CRYPTO_MSG_ALG_REQUEST, + CRYPTO_MSG_ALG_REGISTER, + CRYPTO_MSG_ALG_UNREGISTER, + CRYPTO_MSG_TMPL_REGISTER, + CRYPTO_MSG_TMPL_UNREGISTER, +}; + +struct crypto_larval { + struct ncrypto_alg alg; + struct ncrypto_alg *adult; + struct completion completion; + u32 mask; +}; + +extern struct list_head ncrypto_alg_list; +extern struct rw_semaphore ncrypto_alg_sem; +extern struct blocking_notifier_head crypto_chain; + +struct ncrypto_alg *crypto_mod_get(struct ncrypto_alg *alg); +struct ncrypto_alg *__crypto_alg_lookup(const char *name, u32 type, u32 mask); +struct ncrypto_alg *ncrypto_alg_mod_lookup(const char *name, u32 type, + u32 mask); + +void crypto_larval_kill(struct ncrypto_alg *alg); +struct ncrypto_alg *crypto_larval_lookup(const char *name, u32 type, u32 mask); +void crypto_larval_error(const char *name, u32 type, u32 mask); + +void crypto_shoot_alg(struct ncrypto_alg *alg); +struct ncrypto_tfm *__crypto_alloc_tfm(struct ncrypto_alg *alg, u32 type, + u32 mask); + +static inline void ncrypto_alg_put(struct ncrypto_alg *alg) +{ + if (atomic_dec_and_test(&alg->cra_refcnt) && alg->cra_destroy) + alg->cra_destroy(alg); +} + +static inline int crypto_is_larval(struct ncrypto_alg *alg) +{ + return alg->cra_flags & NCRYPTO_ALG_LARVAL; +} + +static inline int crypto_is_dead(struct ncrypto_alg *alg) +{ + return alg->cra_flags & NCRYPTO_ALG_DEAD; +} + +static inline int crypto_is_moribund(struct ncrypto_alg *alg) +{ + return alg->cra_flags & (NCRYPTO_ALG_DEAD | NCRYPTO_ALG_DYING); +} + +static inline int crypto_notify(unsigned long val, void *v) +{ + return blocking_notifier_call_chain(&crypto_chain, val, v); +} + +#endif /* _CRYPTO_NINTERNAL_H */ diff --git a/include/crypto/algapi.h b/include/crypto/algapi.h new file mode 100644 index 0000000..28c0284 --- /dev/null +++ b/include/crypto/algapi.h @@ -0,0 +1,30 @@ +/* + * Cryptographic API for algorithms (i.e., low-level API). + * + * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ +#ifndef _CRYPTO_ALGAPI_H +#define _CRYPTO_ALGAPI_H + +#include <linux/ncrypto.h> +#include <linux/kernel.h> + +struct seq_file; + +struct crypto_type { + unsigned int (*ctxsize)(struct ncrypto_alg *alg, u32 type, u32 mask); + int (*init)(struct ncrypto_tfm *tfm, u32 type, u32 mask); + void (*exit)(struct ncrypto_tfm *tfm); + void (*show)(struct seq_file *m, struct ncrypto_alg *alg); +}; + +void crypto_mod_put(struct ncrypto_alg *alg); + +#endif /* _CRYPTO_ALGAPI_H */ + diff --git a/include/linux/crypto.h b/include/linux/crypto.h index 3abe2ac..cda3885 100644 --- a/include/linux/crypto.h +++ b/include/linux/crypto.h @@ -46,6 +46,7 @@ #define CRYPTO_TFM_REQ_WEAK_KEY 0x00000100 #define CRYPTO_TFM_REQ_MAY_SLEEP 0x00000200 +#define CRYPTO_TFM_REQ_MAY_BACKLOG 0x00000400 #define CRYPTO_TFM_RES_WEAK_KEY 0x00100000 #define CRYPTO_TFM_RES_BAD_KEY_LEN 0x00200000 #define CRYPTO_TFM_RES_BAD_KEY_SCHED 0x00400000 diff --git a/include/linux/ncrypto.h b/include/linux/ncrypto.h new file mode 100644 index 0000000..fb0b543 --- /dev/null +++ b/include/linux/ncrypto.h @@ -0,0 +1,203 @@ +/* + * Scatterlist Cryptographic API. + * + * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> + * Copyright (c) 2002 David S. Miller (davem@redhat.com) + * Copyright (c) 2005 Herbert Xu <herbert@gondor.apana.org.au> + * + * Portions derived from Cryptoapi, by Alexander Kjeldaas <astor@fast.no> + * and Nettle, by Niels M�ller. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ +#ifndef _LINUX_NCRYPTO_H +#define _LINUX_NCRYPTO_H + +#include <asm/atomic.h> +#include <linux/crypto.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/scatterlist.h> +#include <linux/slab.h> + +#define NCRYPTO_ALG_TYPE_MASK 0x0000000f +#define NCRYPTO_ALG_TYPE_CIPHER 0x00000001 +#define NCRYPTO_ALG_TYPE_DIGEST 0x00000002 +#define NCRYPTO_ALG_TYPE_COMPRESS 0x00000008 + +#define NCRYPTO_ALG_LARVAL 0x00000010 +#define NCRYPTO_ALG_DEAD 0x00000020 +#define NCRYPTO_ALG_DYING 0x00000040 +#define NCRYPTO_ALG_ASYNC 0x00000080 + +/* + * The macro CRYPTO_MINALIGN_ATTR (along with the void * type in the actual + * declaration) is used to ensure that the crypto_tfm context structure is + * aligned correctly for the given architecture so that there are no alignment + * faults for C data types. In particular, this is required on platforms such + * as arm where pointers are 32-bit aligned but there are data types such as + * u64 which require 64-bit alignment. + */ +#if defined(ARCH_KMALLOC_MINALIGN) +#define CRYPTO_MINALIGN ARCH_KMALLOC_MINALIGN +#elif defined(ARCH_SLAB_MINALIGN) +#define CRYPTO_MINALIGN ARCH_SLAB_MINALIGN +#else +#define CRYPTO_MINALIGN __alignof__(unsigned long long) +#endif + +#ifdef CRYPTO_MINALIGN +#define CRYPTO_MINALIGN_ATTR __attribute__ ((__aligned__(CRYPTO_MINALIGN))) +#else +#define CRYPTO_MINALIGN_ATTR +#endif + +#ifndef PTR_ALIGN +#define PTR_ALIGN(p, a) ((typeof(p))ALIGN((unsigned long)(p), (a))) +#endif +#ifndef IS_ALIGNED +#define IS_ALIGNED(x,a) (((x) % ((typeof(x))(a))) == 0) +#endif + +struct crypto_async_request; +struct ncrypto_tfm; +struct crypto_type; +struct module; + +typedef void (*crypto_completion_t)(struct crypto_async_request *req, int err); + +struct crypto_async_request { + struct list_head list; + crypto_completion_t complete; + void *data; + struct ncrypto_tfm *tfm; + + u32 flags; +}; + +struct ncrypto_alg { + struct list_head cra_list; + struct list_head cra_users; + + u32 cra_flags; + unsigned int cra_blocksize; + unsigned int cra_ctxsize; + unsigned int cra_alignmask; + + int cra_priority; + atomic_t cra_refcnt; + + char cra_name[CRYPTO_MAX_ALG_NAME]; + char cra_driver_name[CRYPTO_MAX_ALG_NAME]; + + const struct crypto_type *cra_type; + + union { + } cra_u; + + int (*cra_init)(struct ncrypto_tfm *tfm); + void (*cra_exit)(struct ncrypto_tfm *tfm); + void (*cra_destroy)(struct ncrypto_alg *alg); + + struct module *cra_module; +}; + +/* + * Algorithm registration interface. + */ +int ncrypto_register_alg(struct ncrypto_alg *alg); +int ncrypto_unregister_alg(struct ncrypto_alg *alg); + +/* + * Algorithm query interface. + */ +#ifdef CONFIG_CRYPTO +int crypto_has_alg(const char *name, u32 type, u32 mask); +#else +static inline int crypto_has_alg(const char *name, u32 type, u32 mask) +{ + return 0; +} +#endif + +struct ncrypto_tfm { + + u32 crt_flags; + + union { + } crt_u; + + struct ncrypto_alg *__crt_alg; + + void *__crt_ctx[] CRYPTO_MINALIGN_ATTR; +}; + +enum { + CRYPTOA_UNSPEC, + CRYPTOA_ALG, + CRYPTOA_TYPE, + CRYPTOA_U32, + __CRYPTOA_MAX, +}; + +#define CRYPTOA_MAX (__CRYPTOA_MAX - 1) + +/* Maximum number of (rtattr) parameters for each template. */ +#define CRYPTO_MAX_ATTRS 32 + +struct crypto_attr_alg { + char name[CRYPTO_MAX_ALG_NAME]; +}; + +struct crypto_attr_type { + u32 type; + u32 mask; +}; + +struct crypto_attr_u32 { + u32 num; +}; + +struct ncrypto_tfm *crypto_alloc_base(const char *alg_name, u32 type, u32 mask); +void ncrypto_free_tfm(struct ncrypto_tfm *tfm); + +static inline void sg_set_page(struct scatterlist *sg, struct page *page, + unsigned int len, unsigned int offset) +{ + sg->page = page; + sg->offset = offset; + sg->length = len; +} + +#define sg_page(sg) ((sg)->page) + +static inline void sg_mark_end(struct scatterlist *sg) +{ +} + +static inline void sg_init_table(struct scatterlist *sgl, unsigned int nents) +{ + memset(sgl, 0, sizeof(*sgl) * nents); +} + +static inline unsigned int ncrypto_tfm_alg_alignmask(struct ncrypto_tfm *tfm) +{ + return tfm->__crt_alg->cra_alignmask; +} + +static inline void *ncrypto_tfm_ctx(struct ncrypto_tfm *tfm) +{ + return tfm->__crt_ctx; +} + +static inline unsigned int ncrypto_tfm_ctx_alignment(void) +{ + struct ncrypto_tfm *tfm; + return __alignof__(tfm->__crt_ctx); +} + +#endif /* _LINUX_NCRYPTO_H */