From 63044c4fd49f9e2ce8ee9c5ca24afe6ebbb9fb46 Mon Sep 17 00:00:00 2001 From: Giovanni Cabiddu Date: Thu, 2 Jun 2016 13:28:55 +0100 Subject: crypto: hash - shrink hash down to two types Move hash to 0xe to free up the space for acomp/scomp Signed-off-by: Giovanni Cabiddu Signed-off-by: Herbert Xu --- include/linux/crypto.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'include/linux/crypto.h') diff --git a/include/linux/crypto.h b/include/linux/crypto.h index 6e28c895c376..d844cbc365f7 100644 --- a/include/linux/crypto.h +++ b/include/linux/crypto.h @@ -48,15 +48,15 @@ #define CRYPTO_ALG_TYPE_BLKCIPHER 0x00000004 #define CRYPTO_ALG_TYPE_ABLKCIPHER 0x00000005 #define CRYPTO_ALG_TYPE_GIVCIPHER 0x00000006 -#define CRYPTO_ALG_TYPE_DIGEST 0x00000008 -#define CRYPTO_ALG_TYPE_HASH 0x00000008 -#define CRYPTO_ALG_TYPE_SHASH 0x00000009 -#define CRYPTO_ALG_TYPE_AHASH 0x0000000a #define CRYPTO_ALG_TYPE_RNG 0x0000000c #define CRYPTO_ALG_TYPE_AKCIPHER 0x0000000d +#define CRYPTO_ALG_TYPE_DIGEST 0x0000000e +#define CRYPTO_ALG_TYPE_HASH 0x0000000e +#define CRYPTO_ALG_TYPE_SHASH 0x0000000e +#define CRYPTO_ALG_TYPE_AHASH 0x0000000f #define CRYPTO_ALG_TYPE_HASH_MASK 0x0000000e -#define CRYPTO_ALG_TYPE_AHASH_MASK 0x0000000c +#define CRYPTO_ALG_TYPE_AHASH_MASK 0x0000000e #define CRYPTO_ALG_TYPE_BLKCIPHER_MASK 0x0000000c #define CRYPTO_ALG_LARVAL 0x00000010 -- cgit From 4e5f2c400765e3a3ce512dc1ae890bac53401798 Mon Sep 17 00:00:00 2001 From: Salvatore Benedetto Date: Wed, 22 Jun 2016 17:49:13 +0100 Subject: crypto: kpp - Key-agreement Protocol Primitives API (KPP) Add key-agreement protocol primitives (kpp) API which allows to implement primitives required by protocols such as DH and ECDH. The API is composed mainly by the following functions * set_secret() - It allows the user to set his secret, also referred to as his private key, along with the parameters known to both parties involved in the key-agreement session. * generate_public_key() - It generates the public key to be sent to the other counterpart involved in the key-agreement session. The function has to be called after set_params() and set_secret() * generate_secret() - It generates the shared secret for the session Other functions such as init() and exit() are provided for allowing cryptographic hardware to be inizialized properly before use Signed-off-by: Salvatore Benedetto Signed-off-by: Herbert Xu --- crypto/Kconfig | 10 ++ crypto/Makefile | 1 + crypto/crypto_user.c | 20 +++ crypto/kpp.c | 123 +++++++++++++++ include/crypto/internal/kpp.h | 64 ++++++++ include/crypto/kpp.h | 328 ++++++++++++++++++++++++++++++++++++++++ include/linux/crypto.h | 1 + include/uapi/linux/cryptouser.h | 5 + 8 files changed, 552 insertions(+) create mode 100644 crypto/kpp.c create mode 100644 include/crypto/internal/kpp.h create mode 100644 include/crypto/kpp.h (limited to 'include/linux/crypto.h') diff --git a/crypto/Kconfig b/crypto/Kconfig index 6881d1a5f859..e72c4270173d 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -93,6 +93,15 @@ config CRYPTO_AKCIPHER select CRYPTO_AKCIPHER2 select CRYPTO_ALGAPI +config CRYPTO_KPP2 + tristate + select CRYPTO_ALGAPI2 + +config CRYPTO_KPP + tristate + select CRYPTO_ALGAPI + select CRYPTO_KPP2 + config CRYPTO_RSA tristate "RSA algorithm" select CRYPTO_AKCIPHER @@ -115,6 +124,7 @@ config CRYPTO_MANAGER2 select CRYPTO_HASH2 select CRYPTO_BLKCIPHER2 select CRYPTO_AKCIPHER2 + select CRYPTO_KPP2 config CRYPTO_USER tristate "Userspace cryptographic algorithm configuration" diff --git a/crypto/Makefile b/crypto/Makefile index 0b82c4753743..07b0f51bd645 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -30,6 +30,7 @@ crypto_hash-y += shash.o obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o obj-$(CONFIG_CRYPTO_AKCIPHER2) += akcipher.o +obj-$(CONFIG_CRYPTO_KPP2) += kpp.o $(obj)/rsapubkey-asn1.o: $(obj)/rsapubkey-asn1.c $(obj)/rsapubkey-asn1.h $(obj)/rsaprivkey-asn1.o: $(obj)/rsaprivkey-asn1.c $(obj)/rsaprivkey-asn1.h diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c index 43fe85f20d57..d28513fb5a90 100644 --- a/crypto/crypto_user.c +++ b/crypto/crypto_user.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "internal.h" @@ -126,6 +127,21 @@ nla_put_failure: return -EMSGSIZE; } +static int crypto_report_kpp(struct sk_buff *skb, struct crypto_alg *alg) +{ + struct crypto_report_kpp rkpp; + + strncpy(rkpp.type, "kpp", sizeof(rkpp.type)); + + if (nla_put(skb, CRYPTOCFGA_REPORT_KPP, + sizeof(struct crypto_report_kpp), &rkpp)) + goto nla_put_failure; + return 0; + +nla_put_failure: + return -EMSGSIZE; +} + static int crypto_report_one(struct crypto_alg *alg, struct crypto_user_alg *ualg, struct sk_buff *skb) { @@ -176,6 +192,10 @@ static int crypto_report_one(struct crypto_alg *alg, goto nla_put_failure; break; + case CRYPTO_ALG_TYPE_KPP: + if (crypto_report_kpp(skb, alg)) + goto nla_put_failure; + break; } out: diff --git a/crypto/kpp.c b/crypto/kpp.c new file mode 100644 index 000000000000..d36ce05eee43 --- /dev/null +++ b/crypto/kpp.c @@ -0,0 +1,123 @@ +/* + * Key-agreement Protocol Primitives (KPP) + * + * Copyright (c) 2016, Intel Corporation + * Authors: Salvatore Benedetto + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "internal.h" + +#ifdef CONFIG_NET +static int crypto_kpp_report(struct sk_buff *skb, struct crypto_alg *alg) +{ + struct crypto_report_kpp rkpp; + + strncpy(rkpp.type, "kpp", sizeof(rkpp.type)); + + if (nla_put(skb, CRYPTOCFGA_REPORT_KPP, + sizeof(struct crypto_report_kpp), &rkpp)) + goto nla_put_failure; + return 0; + +nla_put_failure: + return -EMSGSIZE; +} +#else +static int crypto_kpp_report(struct sk_buff *skb, struct crypto_alg *alg) +{ + return -ENOSYS; +} +#endif + +static void crypto_kpp_show(struct seq_file *m, struct crypto_alg *alg) + __attribute__ ((unused)); + +static void crypto_kpp_show(struct seq_file *m, struct crypto_alg *alg) +{ + seq_puts(m, "type : kpp\n"); +} + +static void crypto_kpp_exit_tfm(struct crypto_tfm *tfm) +{ + struct crypto_kpp *kpp = __crypto_kpp_tfm(tfm); + struct kpp_alg *alg = crypto_kpp_alg(kpp); + + alg->exit(kpp); +} + +static int crypto_kpp_init_tfm(struct crypto_tfm *tfm) +{ + struct crypto_kpp *kpp = __crypto_kpp_tfm(tfm); + struct kpp_alg *alg = crypto_kpp_alg(kpp); + + if (alg->exit) + kpp->base.exit = crypto_kpp_exit_tfm; + + if (alg->init) + return alg->init(kpp); + + return 0; +} + +static const struct crypto_type crypto_kpp_type = { + .extsize = crypto_alg_extsize, + .init_tfm = crypto_kpp_init_tfm, +#ifdef CONFIG_PROC_FS + .show = crypto_kpp_show, +#endif + .report = crypto_kpp_report, + .maskclear = ~CRYPTO_ALG_TYPE_MASK, + .maskset = CRYPTO_ALG_TYPE_MASK, + .type = CRYPTO_ALG_TYPE_KPP, + .tfmsize = offsetof(struct crypto_kpp, base), +}; + +struct crypto_kpp *crypto_alloc_kpp(const char *alg_name, u32 type, u32 mask) +{ + return crypto_alloc_tfm(alg_name, &crypto_kpp_type, type, mask); +} +EXPORT_SYMBOL_GPL(crypto_alloc_kpp); + +static void kpp_prepare_alg(struct kpp_alg *alg) +{ + struct crypto_alg *base = &alg->base; + + base->cra_type = &crypto_kpp_type; + base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK; + base->cra_flags |= CRYPTO_ALG_TYPE_KPP; +} + +int crypto_register_kpp(struct kpp_alg *alg) +{ + struct crypto_alg *base = &alg->base; + + kpp_prepare_alg(alg); + return crypto_register_alg(base); +} +EXPORT_SYMBOL_GPL(crypto_register_kpp); + +void crypto_unregister_kpp(struct kpp_alg *alg) +{ + crypto_unregister_alg(&alg->base); +} +EXPORT_SYMBOL_GPL(crypto_unregister_kpp); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Key-agreement Protocol Primitives"); diff --git a/include/crypto/internal/kpp.h b/include/crypto/internal/kpp.h new file mode 100644 index 000000000000..ad3acf3649be --- /dev/null +++ b/include/crypto/internal/kpp.h @@ -0,0 +1,64 @@ +/* + * Key-agreement Protocol Primitives (KPP) + * + * Copyright (c) 2016, Intel Corporation + * Authors: Salvatore Benedetto + * + * 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_KPP_INT_H +#define _CRYPTO_KPP_INT_H +#include +#include + +/* + * Transform internal helpers. + */ +static inline void *kpp_request_ctx(struct kpp_request *req) +{ + return req->__ctx; +} + +static inline void *kpp_tfm_ctx(struct crypto_kpp *tfm) +{ + return tfm->base.__crt_ctx; +} + +static inline void kpp_request_complete(struct kpp_request *req, int err) +{ + req->base.complete(&req->base, err); +} + +static inline const char *kpp_alg_name(struct crypto_kpp *tfm) +{ + return crypto_kpp_tfm(tfm)->__crt_alg->cra_name; +} + +/** + * crypto_register_kpp() -- Register key-agreement protocol primitives algorithm + * + * Function registers an implementation of a key-agreement protocol primitive + * algorithm + * + * @alg: algorithm definition + * + * Return: zero on success; error code in case of error + */ +int crypto_register_kpp(struct kpp_alg *alg); + +/** + * crypto_unregister_kpp() -- Unregister key-agreement protocol primitive + * algorithm + * + * Function unregisters an implementation of a key-agreement protocol primitive + * algorithm + * + * @alg: algorithm definition + */ +void crypto_unregister_kpp(struct kpp_alg *alg); + +#endif diff --git a/include/crypto/kpp.h b/include/crypto/kpp.h new file mode 100644 index 000000000000..4fa897f3366b --- /dev/null +++ b/include/crypto/kpp.h @@ -0,0 +1,328 @@ +/* + * Key-agreement Protocol Primitives (KPP) + * + * Copyright (c) 2016, Intel Corporation + * Authors: Salvatore Benedetto + * + * 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_KPP_ +#define _CRYPTO_KPP_ +#include + +/** + * struct kpp_request + * + * @base: Common attributes for async crypto requests + * @src: Source data + * @dst: Destination data + * @src_len: Size of the input buffer + * @dst_len: Size of the output buffer. It needs to be at least + * as big as the expected result depending on the operation + * After operation it will be updated with the actual size of the + * result. In case of error where the dst sgl size was insufficient, + * it will be updated to the size required for the operation. + * @__ctx: Start of private context data + */ +struct kpp_request { + struct crypto_async_request base; + struct scatterlist *src; + struct scatterlist *dst; + unsigned int src_len; + unsigned int dst_len; + void *__ctx[] CRYPTO_MINALIGN_ATTR; +}; + +/** + * struct crypto_kpp - user-instantiated object which encapsulate + * algorithms and core processing logic + * + * @base: Common crypto API algorithm data structure + */ +struct crypto_kpp { + struct crypto_tfm base; +}; + +/** + * struct kpp_alg - generic key-agreement protocol primitives + * + * @set_secret: Function invokes the protocol specific function to + * store the secret private key along with parameters. + * The implementation knows how to decode thie buffer + * @generate_public_key: Function generate the public key to be sent to the + * counterpart. In case of error, where output is not big + * enough req->dst_len will be updated to the size + * required + * @compute_shared_secret: Function compute the shared secret as defined by + * the algorithm. The result is given back to the user. + * In case of error, where output is not big enough, + * req->dst_len will be updated to the size required + * @max_size: Function returns the size of the output buffer + * @init: Initialize the object. This is called only once at + * instantiation time. In case the cryptographic hardware + * needs to be initialized. Software fallback should be + * put in place here. + * @exit: Undo everything @init did. + * + * @reqsize: Request context size required by algorithm + * implementation + * @base Common crypto API algorithm data structure + */ +struct kpp_alg { + int (*set_secret)(struct crypto_kpp *tfm, void *buffer, + unsigned int len); + int (*generate_public_key)(struct kpp_request *req); + int (*compute_shared_secret)(struct kpp_request *req); + + int (*max_size)(struct crypto_kpp *tfm); + + int (*init)(struct crypto_kpp *tfm); + void (*exit)(struct crypto_kpp *tfm); + + unsigned int reqsize; + struct crypto_alg base; +}; + +/** + * DOC: Generic Key-agreement Protocol Primitevs API + * + * The KPP API is used with the algorithm type + * CRYPTO_ALG_TYPE_KPP (listed as type "kpp" in /proc/crypto) + */ + +/** + * crypto_alloc_kpp() - allocate KPP tfm handle + * @alg_name: is the name of the kpp algorithm (e.g. "dh", "ecdh") + * @type: specifies the type of the algorithm + * @mask: specifies the mask for the algorithm + * + * Allocate a handle for kpp algorithm. The returned struct crypto_kpp + * is requeried for any following API invocation + * + * Return: allocated handle in case of success; IS_ERR() is true in case of + * an error, PTR_ERR() returns the error code. + */ +struct crypto_kpp *crypto_alloc_kpp(const char *alg_name, u32 type, u32 mask); + +static inline struct crypto_tfm *crypto_kpp_tfm(struct crypto_kpp *tfm) +{ + return &tfm->base; +} + +static inline struct kpp_alg *__crypto_kpp_alg(struct crypto_alg *alg) +{ + return container_of(alg, struct kpp_alg, base); +} + +static inline struct crypto_kpp *__crypto_kpp_tfm(struct crypto_tfm *tfm) +{ + return container_of(tfm, struct crypto_kpp, base); +} + +static inline struct kpp_alg *crypto_kpp_alg(struct crypto_kpp *tfm) +{ + return __crypto_kpp_alg(crypto_kpp_tfm(tfm)->__crt_alg); +} + +static inline unsigned int crypto_kpp_reqsize(struct crypto_kpp *tfm) +{ + return crypto_kpp_alg(tfm)->reqsize; +} + +static inline void kpp_request_set_tfm(struct kpp_request *req, + struct crypto_kpp *tfm) +{ + req->base.tfm = crypto_kpp_tfm(tfm); +} + +static inline struct crypto_kpp *crypto_kpp_reqtfm(struct kpp_request *req) +{ + return __crypto_kpp_tfm(req->base.tfm); +} + +/** + * crypto_free_kpp() - free KPP tfm handle + * + * @tfm: KPP tfm handle allocated with crypto_alloc_kpp() + */ +static inline void crypto_free_kpp(struct crypto_kpp *tfm) +{ + crypto_destroy_tfm(tfm, crypto_kpp_tfm(tfm)); +} + +/** + * kpp_request_alloc() - allocates kpp request + * + * @tfm: KPP tfm handle allocated with crypto_alloc_kpp() + * @gfp: allocation flags + * + * Return: allocated handle in case of success or NULL in case of an error. + */ +static inline struct kpp_request *kpp_request_alloc(struct crypto_kpp *tfm, + gfp_t gfp) +{ + struct kpp_request *req; + + req = kmalloc(sizeof(*req) + crypto_kpp_reqsize(tfm), gfp); + if (likely(req)) + kpp_request_set_tfm(req, tfm); + + return req; +} + +/** + * kpp_request_free() - zeroize and free kpp request + * + * @req: request to free + */ +static inline void kpp_request_free(struct kpp_request *req) +{ + kzfree(req); +} + +/** + * kpp_request_set_callback() - Sets an asynchronous callback. + * + * Callback will be called when an asynchronous operation on a given + * request is finished. + * + * @req: request that the callback will be set for + * @flgs: specify for instance if the operation may backlog + * @cmpl: callback which will be called + * @data: private data used by the caller + */ +static inline void kpp_request_set_callback(struct kpp_request *req, + u32 flgs, + crypto_completion_t cmpl, + void *data) +{ + req->base.complete = cmpl; + req->base.data = data; + req->base.flags = flgs; +} + +/** + * kpp_request_set_input() - Sets input buffer + * + * Sets parameters required by generate_public_key + * + * @req: kpp request + * @input: ptr to input scatter list + * @input_len: size of the input scatter list + */ +static inline void kpp_request_set_input(struct kpp_request *req, + struct scatterlist *input, + unsigned int input_len) +{ + req->src = input; + req->src_len = input_len; +} + +/** + * kpp_request_set_output() - Sets output buffer + * + * Sets parameters required by kpp operation + * + * @req: kpp request + * @output: ptr to output scatter list + * @output_len: size of the output scatter list + */ +static inline void kpp_request_set_output(struct kpp_request *req, + struct scatterlist *output, + unsigned int output_len) +{ + req->dst = output; + req->dst_len = output_len; +} + +enum { + CRYPTO_KPP_SECRET_TYPE_UNKNOWN, +}; + +/** + * struct kpp_secret - small header for packing secret buffer + * + * @type: define type of secret. Each kpp type will define its own + * @len: specify the len of the secret, include the header, that + * follows the struct + */ +struct kpp_secret { + unsigned short type; + unsigned short len; +}; + +/** + * crypto_kpp_set_secret() - Invoke kpp operation + * + * Function invokes the specific kpp operation for a given alg. + * + * @tfm: tfm handle + * + * Return: zero on success; error code in case of error + */ +static inline int crypto_kpp_set_secret(struct crypto_kpp *tfm, void *buffer, + unsigned int len) +{ + struct kpp_alg *alg = crypto_kpp_alg(tfm); + + return alg->set_secret(tfm, buffer, len); +} + +/** + * crypto_kpp_generate_public_key() - Invoke kpp operation + * + * Function invokes the specific kpp operation for generating the public part + * for a given kpp algorithm + * + * @req: kpp key request + * + * Return: zero on success; error code in case of error + */ +static inline int crypto_kpp_generate_public_key(struct kpp_request *req) +{ + struct crypto_kpp *tfm = crypto_kpp_reqtfm(req); + struct kpp_alg *alg = crypto_kpp_alg(tfm); + + return alg->generate_public_key(req); +} + +/** + * crypto_kpp_compute_shared_secret() - Invoke kpp operation + * + * Function invokes the specific kpp operation for computing the shared secret + * for a given kpp algorithm. + * + * @req: kpp key request + * + * Return: zero on success; error code in case of error + */ +static inline int crypto_kpp_compute_shared_secret(struct kpp_request *req) +{ + struct crypto_kpp *tfm = crypto_kpp_reqtfm(req); + struct kpp_alg *alg = crypto_kpp_alg(tfm); + + return alg->compute_shared_secret(req); +} + +/** + * crypto_kpp_maxsize() - Get len for output buffer + * + * Function returns the output buffer size required + * + * @tfm: KPP tfm handle allocated with crypto_alloc_kpp() + * + * Return: minimum len for output buffer or error code if key hasn't been set + */ +static inline int crypto_kpp_maxsize(struct crypto_kpp *tfm) +{ + struct kpp_alg *alg = crypto_kpp_alg(tfm); + + return alg->max_size(tfm); +} + +#endif diff --git a/include/linux/crypto.h b/include/linux/crypto.h index d844cbc365f7..992cfc2e5df1 100644 --- a/include/linux/crypto.h +++ b/include/linux/crypto.h @@ -48,6 +48,7 @@ #define CRYPTO_ALG_TYPE_BLKCIPHER 0x00000004 #define CRYPTO_ALG_TYPE_ABLKCIPHER 0x00000005 #define CRYPTO_ALG_TYPE_GIVCIPHER 0x00000006 +#define CRYPTO_ALG_TYPE_KPP 0x00000008 #define CRYPTO_ALG_TYPE_RNG 0x0000000c #define CRYPTO_ALG_TYPE_AKCIPHER 0x0000000d #define CRYPTO_ALG_TYPE_DIGEST 0x0000000e diff --git a/include/uapi/linux/cryptouser.h b/include/uapi/linux/cryptouser.h index 2e67bb64c1da..79b5ded2001a 100644 --- a/include/uapi/linux/cryptouser.h +++ b/include/uapi/linux/cryptouser.h @@ -45,6 +45,7 @@ enum crypto_attr_type_t { CRYPTOCFGA_REPORT_RNG, /* struct crypto_report_rng */ CRYPTOCFGA_REPORT_CIPHER, /* struct crypto_report_cipher */ CRYPTOCFGA_REPORT_AKCIPHER, /* struct crypto_report_akcipher */ + CRYPTOCFGA_REPORT_KPP, /* struct crypto_report_kpp */ __CRYPTOCFGA_MAX #define CRYPTOCFGA_MAX (__CRYPTOCFGA_MAX - 1) @@ -107,5 +108,9 @@ struct crypto_report_akcipher { char type[CRYPTO_MAX_NAME]; }; +struct crypto_report_kpp { + char type[CRYPTO_MAX_NAME]; +}; + #define CRYPTO_REPORT_MAXSIZE (sizeof(struct crypto_user_alg) + \ sizeof(struct crypto_report_blkcipher)) -- cgit From 4e6c3df4d729f85997cbf276bfa8ffd8579b8e77 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 12 Jul 2016 13:17:31 +0800 Subject: crypto: skcipher - Add low-level skcipher interface This patch allows skcipher algorithms and instances to be created and registered with the crypto API. They are accessible through the top-level skcipher interface, along with ablkcipher/blkcipher algorithms and instances. This patch also introduces a new parameter called chunk size which is meant for ciphers such as CTR and CTS which ostensibly can handle arbitrary lengths, but still behave like block ciphers in that you can only process a partial block at the very end. For these ciphers the block size will continue to be set to 1 as it is now while the chunk size will be set to the underlying block size. Signed-off-by: Herbert Xu --- crypto/skcipher.c | 196 +++++++++++++++++++++++++++++++++++-- include/crypto/internal/skcipher.h | 87 ++++++++++++++++ include/crypto/skcipher.h | 130 ++++++++++++++++++++++++ include/linux/crypto.h | 1 + 4 files changed, 407 insertions(+), 7 deletions(-) (limited to 'include/linux/crypto.h') diff --git a/crypto/skcipher.c b/crypto/skcipher.c index 69230e9d4ac9..d248008e7f7b 100644 --- a/crypto/skcipher.c +++ b/crypto/skcipher.c @@ -16,7 +16,11 @@ #include #include +#include #include +#include +#include +#include #include "internal.h" @@ -25,10 +29,11 @@ static unsigned int crypto_skcipher_extsize(struct crypto_alg *alg) if (alg->cra_type == &crypto_blkcipher_type) return sizeof(struct crypto_blkcipher *); - BUG_ON(alg->cra_type != &crypto_ablkcipher_type && - alg->cra_type != &crypto_givcipher_type); + if (alg->cra_type == &crypto_ablkcipher_type || + alg->cra_type == &crypto_givcipher_type) + return sizeof(struct crypto_ablkcipher *); - return sizeof(struct crypto_ablkcipher *); + return crypto_alg_extsize(alg); } static int skcipher_setkey_blkcipher(struct crypto_skcipher *tfm, @@ -216,26 +221,118 @@ static int crypto_init_skcipher_ops_ablkcipher(struct crypto_tfm *tfm) return 0; } +static void crypto_skcipher_exit_tfm(struct crypto_tfm *tfm) +{ + struct crypto_skcipher *skcipher = __crypto_skcipher_cast(tfm); + struct skcipher_alg *alg = crypto_skcipher_alg(skcipher); + + alg->exit(skcipher); +} + static int crypto_skcipher_init_tfm(struct crypto_tfm *tfm) { + struct crypto_skcipher *skcipher = __crypto_skcipher_cast(tfm); + struct skcipher_alg *alg = crypto_skcipher_alg(skcipher); + if (tfm->__crt_alg->cra_type == &crypto_blkcipher_type) return crypto_init_skcipher_ops_blkcipher(tfm); - BUG_ON(tfm->__crt_alg->cra_type != &crypto_ablkcipher_type && - tfm->__crt_alg->cra_type != &crypto_givcipher_type); + if (tfm->__crt_alg->cra_type == &crypto_ablkcipher_type || + tfm->__crt_alg->cra_type == &crypto_givcipher_type) + return crypto_init_skcipher_ops_ablkcipher(tfm); + + skcipher->setkey = alg->setkey; + skcipher->encrypt = alg->encrypt; + skcipher->decrypt = alg->decrypt; + skcipher->ivsize = alg->ivsize; + skcipher->keysize = alg->max_keysize; + + if (alg->exit) + skcipher->base.exit = crypto_skcipher_exit_tfm; - return crypto_init_skcipher_ops_ablkcipher(tfm); + if (alg->init) + return alg->init(skcipher); + + return 0; +} + +static void crypto_skcipher_free_instance(struct crypto_instance *inst) +{ + struct skcipher_instance *skcipher = + container_of(inst, struct skcipher_instance, s.base); + + skcipher->free(skcipher); +} + +static void crypto_skcipher_show(struct seq_file *m, struct crypto_alg *alg) + __attribute__ ((unused)); +static void crypto_skcipher_show(struct seq_file *m, struct crypto_alg *alg) +{ + struct skcipher_alg *skcipher = container_of(alg, struct skcipher_alg, + base); + + seq_printf(m, "type : skcipher\n"); + seq_printf(m, "async : %s\n", + alg->cra_flags & CRYPTO_ALG_ASYNC ? "yes" : "no"); + seq_printf(m, "blocksize : %u\n", alg->cra_blocksize); + seq_printf(m, "min keysize : %u\n", skcipher->min_keysize); + seq_printf(m, "max keysize : %u\n", skcipher->max_keysize); + seq_printf(m, "ivsize : %u\n", skcipher->ivsize); + seq_printf(m, "chunksize : %u\n", skcipher->chunksize); } +#ifdef CONFIG_NET +static int crypto_skcipher_report(struct sk_buff *skb, struct crypto_alg *alg) +{ + struct crypto_report_blkcipher rblkcipher; + struct skcipher_alg *skcipher = container_of(alg, struct skcipher_alg, + base); + + strncpy(rblkcipher.type, "skcipher", sizeof(rblkcipher.type)); + strncpy(rblkcipher.geniv, "", sizeof(rblkcipher.geniv)); + + rblkcipher.blocksize = alg->cra_blocksize; + rblkcipher.min_keysize = skcipher->min_keysize; + rblkcipher.max_keysize = skcipher->max_keysize; + rblkcipher.ivsize = skcipher->ivsize; + + if (nla_put(skb, CRYPTOCFGA_REPORT_BLKCIPHER, + sizeof(struct crypto_report_blkcipher), &rblkcipher)) + goto nla_put_failure; + return 0; + +nla_put_failure: + return -EMSGSIZE; +} +#else +static int crypto_skcipher_report(struct sk_buff *skb, struct crypto_alg *alg) +{ + return -ENOSYS; +} +#endif + static const struct crypto_type crypto_skcipher_type2 = { .extsize = crypto_skcipher_extsize, .init_tfm = crypto_skcipher_init_tfm, + .free = crypto_skcipher_free_instance, +#ifdef CONFIG_PROC_FS + .show = crypto_skcipher_show, +#endif + .report = crypto_skcipher_report, .maskclear = ~CRYPTO_ALG_TYPE_MASK, .maskset = CRYPTO_ALG_TYPE_BLKCIPHER_MASK, - .type = CRYPTO_ALG_TYPE_BLKCIPHER, + .type = CRYPTO_ALG_TYPE_SKCIPHER, .tfmsize = offsetof(struct crypto_skcipher, base), }; +int crypto_grab_skcipher2(struct crypto_skcipher_spawn *spawn, + const char *name, u32 type, u32 mask) +{ + spawn->base.frontend = &crypto_skcipher_type2; + return crypto_grab_spawn(&spawn->base, name, type, mask); +} +EXPORT_SYMBOL_GPL(crypto_grab_skcipher2); + struct crypto_skcipher *crypto_alloc_skcipher(const char *alg_name, u32 type, u32 mask) { @@ -243,5 +340,90 @@ struct crypto_skcipher *crypto_alloc_skcipher(const char *alg_name, } EXPORT_SYMBOL_GPL(crypto_alloc_skcipher); +int crypto_has_skcipher2(const char *alg_name, u32 type, u32 mask) +{ + return crypto_type_has_alg(alg_name, &crypto_skcipher_type2, + type, mask); +} +EXPORT_SYMBOL_GPL(crypto_has_skcipher2); + +static int skcipher_prepare_alg(struct skcipher_alg *alg) +{ + struct crypto_alg *base = &alg->base; + + if (alg->ivsize > PAGE_SIZE / 8 || alg->chunksize > PAGE_SIZE / 8) + return -EINVAL; + + if (!alg->chunksize) + alg->chunksize = base->cra_blocksize; + + base->cra_type = &crypto_skcipher_type2; + base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK; + base->cra_flags |= CRYPTO_ALG_TYPE_SKCIPHER; + + return 0; +} + +int crypto_register_skcipher(struct skcipher_alg *alg) +{ + struct crypto_alg *base = &alg->base; + int err; + + err = skcipher_prepare_alg(alg); + if (err) + return err; + + return crypto_register_alg(base); +} +EXPORT_SYMBOL_GPL(crypto_register_skcipher); + +void crypto_unregister_skcipher(struct skcipher_alg *alg) +{ + crypto_unregister_alg(&alg->base); +} +EXPORT_SYMBOL_GPL(crypto_unregister_skcipher); + +int crypto_register_skciphers(struct skcipher_alg *algs, int count) +{ + int i, ret; + + for (i = 0; i < count; i++) { + ret = crypto_register_skcipher(&algs[i]); + if (ret) + goto err; + } + + return 0; + +err: + for (--i; i >= 0; --i) + crypto_unregister_skcipher(&algs[i]); + + return ret; +} +EXPORT_SYMBOL_GPL(crypto_register_skciphers); + +void crypto_unregister_skciphers(struct skcipher_alg *algs, int count) +{ + int i; + + for (i = count - 1; i >= 0; --i) + crypto_unregister_skcipher(&algs[i]); +} +EXPORT_SYMBOL_GPL(crypto_unregister_skciphers); + +int skcipher_register_instance(struct crypto_template *tmpl, + struct skcipher_instance *inst) +{ + int err; + + err = skcipher_prepare_alg(&inst->alg); + if (err) + return err; + + return crypto_register_instance(tmpl, skcipher_crypto_instance(inst)); +} +EXPORT_SYMBOL_GPL(skcipher_register_instance); + MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Symmetric key cipher type"); diff --git a/include/crypto/internal/skcipher.h b/include/crypto/internal/skcipher.h index 2cf7a61ece59..ce6619c339fe 100644 --- a/include/crypto/internal/skcipher.h +++ b/include/crypto/internal/skcipher.h @@ -19,12 +19,46 @@ struct rtattr; +struct skcipher_instance { + void (*free)(struct skcipher_instance *inst); + union { + struct { + char head[offsetof(struct skcipher_alg, base)]; + struct crypto_instance base; + } s; + struct skcipher_alg alg; + }; +}; + struct crypto_skcipher_spawn { struct crypto_spawn base; }; extern const struct crypto_type crypto_givcipher_type; +static inline struct crypto_instance *skcipher_crypto_instance( + struct skcipher_instance *inst) +{ + return &inst->s.base; +} + +static inline struct skcipher_instance *skcipher_alg_instance( + struct crypto_skcipher *skcipher) +{ + return container_of(crypto_skcipher_alg(skcipher), + struct skcipher_instance, alg); +} + +static inline void *skcipher_instance_ctx(struct skcipher_instance *inst) +{ + return crypto_instance_ctx(skcipher_crypto_instance(inst)); +} + +static inline void skcipher_request_complete(struct skcipher_request *req, int err) +{ + req->base.complete(&req->base, err); +} + static inline void crypto_set_skcipher_spawn( struct crypto_skcipher_spawn *spawn, struct crypto_instance *inst) { @@ -33,6 +67,8 @@ static inline void crypto_set_skcipher_spawn( int crypto_grab_skcipher(struct crypto_skcipher_spawn *spawn, const char *name, u32 type, u32 mask); +int crypto_grab_skcipher2(struct crypto_skcipher_spawn *spawn, + const char *name, u32 type, u32 mask); struct crypto_alg *crypto_lookup_skcipher(const char *name, u32 type, u32 mask); @@ -47,6 +83,12 @@ static inline struct crypto_alg *crypto_skcipher_spawn_alg( return spawn->base.alg; } +static inline struct skcipher_alg *crypto_spawn_skcipher_alg( + struct crypto_skcipher_spawn *spawn) +{ + return container_of(spawn->base.alg, struct skcipher_alg, base); +} + static inline struct crypto_ablkcipher *crypto_spawn_skcipher( struct crypto_skcipher_spawn *spawn) { @@ -55,6 +97,25 @@ static inline struct crypto_ablkcipher *crypto_spawn_skcipher( crypto_skcipher_mask(0))); } +static inline struct crypto_skcipher *crypto_spawn_skcipher2( + struct crypto_skcipher_spawn *spawn) +{ + return crypto_spawn_tfm2(&spawn->base); +} + +static inline void crypto_skcipher_set_reqsize( + struct crypto_skcipher *skcipher, unsigned int reqsize) +{ + skcipher->reqsize = reqsize; +} + +int crypto_register_skcipher(struct skcipher_alg *alg); +void crypto_unregister_skcipher(struct skcipher_alg *alg); +int crypto_register_skciphers(struct skcipher_alg *algs, int count); +void crypto_unregister_skciphers(struct skcipher_alg *algs, int count); +int skcipher_register_instance(struct crypto_template *tmpl, + struct skcipher_instance *inst); + int skcipher_null_givencrypt(struct skcipher_givcrypt_request *req); int skcipher_null_givdecrypt(struct skcipher_givcrypt_request *req); const char *crypto_default_geniv(const struct crypto_alg *alg); @@ -122,5 +183,31 @@ static inline u32 skcipher_request_flags(struct skcipher_request *req) return req->base.flags; } +static inline unsigned int crypto_skcipher_alg_min_keysize( + struct skcipher_alg *alg) +{ + if ((alg->base.cra_flags & CRYPTO_ALG_TYPE_MASK) == + CRYPTO_ALG_TYPE_BLKCIPHER) + return alg->base.cra_blkcipher.min_keysize; + + if (alg->base.cra_ablkcipher.encrypt) + return alg->base.cra_ablkcipher.min_keysize; + + return alg->min_keysize; +} + +static inline unsigned int crypto_skcipher_alg_max_keysize( + struct skcipher_alg *alg) +{ + if ((alg->base.cra_flags & CRYPTO_ALG_TYPE_MASK) == + CRYPTO_ALG_TYPE_BLKCIPHER) + return alg->base.cra_blkcipher.max_keysize; + + if (alg->base.cra_ablkcipher.encrypt) + return alg->base.cra_ablkcipher.max_keysize; + + return alg->max_keysize; +} + #endif /* _CRYPTO_INTERNAL_SKCIPHER_H */ diff --git a/include/crypto/skcipher.h b/include/crypto/skcipher.h index 0f987f50bb52..a381f57ea695 100644 --- a/include/crypto/skcipher.h +++ b/include/crypto/skcipher.h @@ -65,6 +65,75 @@ struct crypto_skcipher { struct crypto_tfm base; }; +/** + * struct skcipher_alg - symmetric key cipher definition + * @min_keysize: Minimum key size supported by the transformation. This is the + * smallest key length supported by this transformation algorithm. + * This must be set to one of the pre-defined values as this is + * not hardware specific. Possible values for this field can be + * found via git grep "_MIN_KEY_SIZE" include/crypto/ + * @max_keysize: Maximum key size supported by the transformation. This is the + * largest key length supported by this transformation algorithm. + * This must be set to one of the pre-defined values as this is + * not hardware specific. Possible values for this field can be + * found via git grep "_MAX_KEY_SIZE" include/crypto/ + * @setkey: Set key for the transformation. This function is used to either + * program a supplied key into the hardware or store the key in the + * transformation context for programming it later. Note that this + * function does modify the transformation context. This function can + * be called multiple times during the existence of the transformation + * object, so one must make sure the key is properly reprogrammed into + * the hardware. This function is also responsible for checking the key + * length for validity. In case a software fallback was put in place in + * the @cra_init call, this function might need to use the fallback if + * the algorithm doesn't support all of the key sizes. + * @encrypt: Encrypt a scatterlist of blocks. This function is used to encrypt + * the supplied scatterlist containing the blocks of data. The crypto + * API consumer is responsible for aligning the entries of the + * scatterlist properly and making sure the chunks are correctly + * sized. In case a software fallback was put in place in the + * @cra_init call, this function might need to use the fallback if + * the algorithm doesn't support all of the key sizes. In case the + * key was stored in transformation context, the key might need to be + * re-programmed into the hardware in this function. This function + * shall not modify the transformation context, as this function may + * be called in parallel with the same transformation object. + * @decrypt: Decrypt a single block. This is a reverse counterpart to @encrypt + * and the conditions are exactly the same. + * @init: Initialize the cryptographic transformation object. This function + * is used to initialize the cryptographic transformation object. + * This function is called only once at the instantiation time, right + * after the transformation context was allocated. In case the + * cryptographic hardware has some special requirements which need to + * be handled by software, this function shall check for the precise + * requirement of the transformation and put any software fallbacks + * in place. + * @exit: Deinitialize the cryptographic transformation object. This is a + * counterpart to @init, used to remove various changes set in + * @init. + * @ivsize: IV size applicable for transformation. The consumer must provide an + * IV of exactly that size to perform the encrypt or decrypt operation. + * @chunksize: Equal to the block size except for stream ciphers such as + * CTR where it is set to the underlying block size. + * + * All fields except @ivsize are mandatory and must be filled. + */ +struct skcipher_alg { + int (*setkey)(struct crypto_skcipher *tfm, const u8 *key, + unsigned int keylen); + int (*encrypt)(struct skcipher_request *req); + int (*decrypt)(struct skcipher_request *req); + int (*init)(struct crypto_skcipher *tfm); + void (*exit)(struct crypto_skcipher *tfm); + + unsigned int min_keysize; + unsigned int max_keysize; + unsigned int ivsize; + unsigned int chunksize; + + struct crypto_alg base; +}; + #define SKCIPHER_REQUEST_ON_STACK(name, tfm) \ char __##name##_desc[sizeof(struct skcipher_request) + \ crypto_skcipher_reqsize(tfm)] CRYPTO_MINALIGN_ATTR; \ @@ -231,12 +300,43 @@ static inline int crypto_has_skcipher(const char *alg_name, u32 type, crypto_skcipher_mask(mask)); } +/** + * crypto_has_skcipher2() - Search for the availability of an skcipher. + * @alg_name: is the cra_name / name or cra_driver_name / driver name of the + * skcipher + * @type: specifies the type of the skcipher + * @mask: specifies the mask for the skcipher + * + * Return: true when the skcipher is known to the kernel crypto API; false + * otherwise + */ +int crypto_has_skcipher2(const char *alg_name, u32 type, u32 mask); + static inline const char *crypto_skcipher_driver_name( struct crypto_skcipher *tfm) { return crypto_tfm_alg_driver_name(crypto_skcipher_tfm(tfm)); } +static inline struct skcipher_alg *crypto_skcipher_alg( + struct crypto_skcipher *tfm) +{ + return container_of(crypto_skcipher_tfm(tfm)->__crt_alg, + struct skcipher_alg, base); +} + +static inline unsigned int crypto_skcipher_alg_ivsize(struct skcipher_alg *alg) +{ + if ((alg->base.cra_flags & CRYPTO_ALG_TYPE_MASK) == + CRYPTO_ALG_TYPE_BLKCIPHER) + return alg->base.cra_blkcipher.ivsize; + + if (alg->base.cra_ablkcipher.encrypt) + return alg->base.cra_ablkcipher.ivsize; + + return alg->ivsize; +} + /** * crypto_skcipher_ivsize() - obtain IV size * @tfm: cipher handle @@ -251,6 +351,36 @@ static inline unsigned int crypto_skcipher_ivsize(struct crypto_skcipher *tfm) return tfm->ivsize; } +static inline unsigned int crypto_skcipher_alg_chunksize( + struct skcipher_alg *alg) +{ + if ((alg->base.cra_flags & CRYPTO_ALG_TYPE_MASK) == + CRYPTO_ALG_TYPE_BLKCIPHER) + return alg->base.cra_blocksize; + + if (alg->base.cra_ablkcipher.encrypt) + return alg->base.cra_blocksize; + + return alg->chunksize; +} + +/** + * crypto_skcipher_chunksize() - obtain chunk size + * @tfm: cipher handle + * + * The block size is set to one for ciphers such as CTR. However, + * you still need to provide incremental updates in multiples of + * the underlying block size as the IV does not have sub-block + * granularity. This is known in this API as the chunk size. + * + * Return: chunk size in bytes + */ +static inline unsigned int crypto_skcipher_chunksize( + struct crypto_skcipher *tfm) +{ + return crypto_skcipher_alg_chunksize(crypto_skcipher_alg(tfm)); +} + /** * crypto_skcipher_blocksize() - obtain block size of cipher * @tfm: cipher handle diff --git a/include/linux/crypto.h b/include/linux/crypto.h index 992cfc2e5df1..37a652d1639d 100644 --- a/include/linux/crypto.h +++ b/include/linux/crypto.h @@ -47,6 +47,7 @@ #define CRYPTO_ALG_TYPE_AEAD 0x00000003 #define CRYPTO_ALG_TYPE_BLKCIPHER 0x00000004 #define CRYPTO_ALG_TYPE_ABLKCIPHER 0x00000005 +#define CRYPTO_ALG_TYPE_SKCIPHER 0x00000005 #define CRYPTO_ALG_TYPE_GIVCIPHER 0x00000006 #define CRYPTO_ALG_TYPE_KPP 0x00000008 #define CRYPTO_ALG_TYPE_RNG 0x0000000c -- cgit From 3a01d0ee2b991c8c267620e63a4ab47cd8c30cc4 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 12 Jul 2016 13:17:50 +0800 Subject: crypto: skcipher - Remove top-level givcipher interface This patch removes the old crypto_grab_skcipher helper and replaces it with crypto_grab_skcipher2. As this is the final entry point into givcipher this patch also removes all traces of the top-level givcipher interface, including all implicit IV generators such as chainiv. The bottom-level givcipher interface remains until the drivers using it are converted. Signed-off-by: Herbert Xu --- crypto/Makefile | 2 - crypto/ablkcipher.c | 222 -------------------------- crypto/blkcipher.c | 185 ---------------------- crypto/chainiv.c | 317 ------------------------------------- crypto/eseqiv.c | 242 ---------------------------- crypto/seqiv.c | 162 +------------------ crypto/skcipher.c | 4 +- include/crypto/internal/skcipher.h | 63 ++------ include/crypto/skcipher.h | 76 --------- include/linux/crypto.h | 19 --- 10 files changed, 18 insertions(+), 1274 deletions(-) delete mode 100644 crypto/chainiv.c delete mode 100644 crypto/eseqiv.c (limited to 'include/linux/crypto.h') diff --git a/crypto/Makefile b/crypto/Makefile index df1bcfb090d2..99cc64ac70ef 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -20,8 +20,6 @@ crypto_blkcipher-y := ablkcipher.o crypto_blkcipher-y += blkcipher.o crypto_blkcipher-y += skcipher.o obj-$(CONFIG_CRYPTO_BLKCIPHER2) += crypto_blkcipher.o -obj-$(CONFIG_CRYPTO_BLKCIPHER2) += chainiv.o -obj-$(CONFIG_CRYPTO_BLKCIPHER2) += eseqiv.o obj-$(CONFIG_CRYPTO_SEQIV) += seqiv.o obj-$(CONFIG_CRYPTO_ECHAINIV) += echainiv.o diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c index 6b80516778c6..d676fc59521a 100644 --- a/crypto/ablkcipher.c +++ b/crypto/ablkcipher.c @@ -16,8 +16,6 @@ #include #include #include -#include -#include #include #include #include @@ -348,16 +346,6 @@ static unsigned int crypto_ablkcipher_ctxsize(struct crypto_alg *alg, u32 type, return alg->cra_ctxsize; } -int skcipher_null_givencrypt(struct skcipher_givcrypt_request *req) -{ - return crypto_ablkcipher_encrypt(&req->creq); -} - -int skcipher_null_givdecrypt(struct skcipher_givcrypt_request *req) -{ - return crypto_ablkcipher_decrypt(&req->creq); -} - static int crypto_init_ablkcipher_ops(struct crypto_tfm *tfm, u32 type, u32 mask) { @@ -370,10 +358,6 @@ static int crypto_init_ablkcipher_ops(struct crypto_tfm *tfm, u32 type, crt->setkey = setkey; crt->encrypt = alg->encrypt; crt->decrypt = alg->decrypt; - if (!alg->ivsize) { - crt->givencrypt = skcipher_null_givencrypt; - crt->givdecrypt = skcipher_null_givdecrypt; - } crt->base = __crypto_ablkcipher_cast(tfm); crt->ivsize = alg->ivsize; @@ -435,11 +419,6 @@ const struct crypto_type crypto_ablkcipher_type = { }; EXPORT_SYMBOL_GPL(crypto_ablkcipher_type); -static int no_givdecrypt(struct skcipher_givcrypt_request *req) -{ - return -ENOSYS; -} - static int crypto_init_givcipher_ops(struct crypto_tfm *tfm, u32 type, u32 mask) { @@ -453,8 +432,6 @@ static int crypto_init_givcipher_ops(struct crypto_tfm *tfm, u32 type, alg->setkey : setkey; crt->encrypt = alg->encrypt; crt->decrypt = alg->decrypt; - crt->givencrypt = alg->givencrypt ?: no_givdecrypt; - crt->givdecrypt = alg->givdecrypt ?: no_givdecrypt; crt->base = __crypto_ablkcipher_cast(tfm); crt->ivsize = alg->ivsize; @@ -515,202 +492,3 @@ const struct crypto_type crypto_givcipher_type = { .report = crypto_givcipher_report, }; EXPORT_SYMBOL_GPL(crypto_givcipher_type); - -const char *crypto_default_geniv(const struct crypto_alg *alg) -{ - if (((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) == - CRYPTO_ALG_TYPE_BLKCIPHER ? alg->cra_blkcipher.ivsize : - alg->cra_ablkcipher.ivsize) != - alg->cra_blocksize) - return "chainiv"; - - return "eseqiv"; -} - -static int crypto_givcipher_default(struct crypto_alg *alg, u32 type, u32 mask) -{ - struct rtattr *tb[3]; - struct { - struct rtattr attr; - struct crypto_attr_type data; - } ptype; - struct { - struct rtattr attr; - struct crypto_attr_alg data; - } palg; - struct crypto_template *tmpl; - struct crypto_instance *inst; - struct crypto_alg *larval; - const char *geniv; - int err; - - larval = crypto_larval_lookup(alg->cra_driver_name, - (type & ~CRYPTO_ALG_TYPE_MASK) | - CRYPTO_ALG_TYPE_GIVCIPHER, - mask | CRYPTO_ALG_TYPE_MASK); - err = PTR_ERR(larval); - if (IS_ERR(larval)) - goto out; - - err = -EAGAIN; - if (!crypto_is_larval(larval)) - goto drop_larval; - - ptype.attr.rta_len = sizeof(ptype); - ptype.attr.rta_type = CRYPTOA_TYPE; - ptype.data.type = type | CRYPTO_ALG_GENIV; - /* GENIV tells the template that we're making a default geniv. */ - ptype.data.mask = mask | CRYPTO_ALG_GENIV; - tb[0] = &ptype.attr; - - palg.attr.rta_len = sizeof(palg); - palg.attr.rta_type = CRYPTOA_ALG; - /* Must use the exact name to locate ourselves. */ - memcpy(palg.data.name, alg->cra_driver_name, CRYPTO_MAX_ALG_NAME); - tb[1] = &palg.attr; - - tb[2] = NULL; - - if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) == - CRYPTO_ALG_TYPE_BLKCIPHER) - geniv = alg->cra_blkcipher.geniv; - else - geniv = alg->cra_ablkcipher.geniv; - - if (!geniv) - geniv = crypto_default_geniv(alg); - - tmpl = crypto_lookup_template(geniv); - err = -ENOENT; - if (!tmpl) - goto kill_larval; - - if (tmpl->create) { - err = tmpl->create(tmpl, tb); - if (err) - goto put_tmpl; - goto ok; - } - - inst = tmpl->alloc(tb); - err = PTR_ERR(inst); - if (IS_ERR(inst)) - goto put_tmpl; - - err = crypto_register_instance(tmpl, inst); - if (err) { - tmpl->free(inst); - goto put_tmpl; - } - -ok: - /* Redo the lookup to use the instance we just registered. */ - err = -EAGAIN; - -put_tmpl: - crypto_tmpl_put(tmpl); -kill_larval: - crypto_larval_kill(larval); -drop_larval: - crypto_mod_put(larval); -out: - crypto_mod_put(alg); - return err; -} - -struct crypto_alg *crypto_lookup_skcipher(const char *name, u32 type, u32 mask) -{ - struct crypto_alg *alg; - - alg = crypto_alg_mod_lookup(name, type, mask); - if (IS_ERR(alg)) - return alg; - - if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) == - CRYPTO_ALG_TYPE_GIVCIPHER) - return alg; - - if (!((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) == - CRYPTO_ALG_TYPE_BLKCIPHER ? alg->cra_blkcipher.ivsize : - alg->cra_ablkcipher.ivsize)) - return alg; - - crypto_mod_put(alg); - alg = crypto_alg_mod_lookup(name, type | CRYPTO_ALG_TESTED, - mask & ~CRYPTO_ALG_TESTED); - if (IS_ERR(alg)) - return alg; - - if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) == - CRYPTO_ALG_TYPE_GIVCIPHER) { - if (~alg->cra_flags & (type ^ ~mask) & CRYPTO_ALG_TESTED) { - crypto_mod_put(alg); - alg = ERR_PTR(-ENOENT); - } - return alg; - } - - BUG_ON(!((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) == - CRYPTO_ALG_TYPE_BLKCIPHER ? alg->cra_blkcipher.ivsize : - alg->cra_ablkcipher.ivsize)); - - return ERR_PTR(crypto_givcipher_default(alg, type, mask)); -} -EXPORT_SYMBOL_GPL(crypto_lookup_skcipher); - -int crypto_grab_skcipher(struct crypto_skcipher_spawn *spawn, const char *name, - u32 type, u32 mask) -{ - struct crypto_alg *alg; - int err; - - type = crypto_skcipher_type(type); - mask = crypto_skcipher_mask(mask); - - alg = crypto_lookup_skcipher(name, type, mask); - if (IS_ERR(alg)) - return PTR_ERR(alg); - - err = crypto_init_spawn(&spawn->base, alg, spawn->base.inst, mask); - crypto_mod_put(alg); - return err; -} -EXPORT_SYMBOL_GPL(crypto_grab_skcipher); - -struct crypto_ablkcipher *crypto_alloc_ablkcipher(const char *alg_name, - u32 type, u32 mask) -{ - struct crypto_tfm *tfm; - int err; - - type = crypto_skcipher_type(type); - mask = crypto_skcipher_mask(mask); - - for (;;) { - struct crypto_alg *alg; - - alg = crypto_lookup_skcipher(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 __crypto_ablkcipher_cast(tfm); - - crypto_mod_put(alg); - err = PTR_ERR(tfm); - -err: - if (err != -EAGAIN) - break; - if (fatal_signal_pending(current)) { - err = -EINTR; - break; - } - } - - return ERR_PTR(err); -} -EXPORT_SYMBOL_GPL(crypto_alloc_ablkcipher); diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c index 8cc1622b2ee0..369999530108 100644 --- a/crypto/blkcipher.c +++ b/crypto/blkcipher.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -466,10 +465,6 @@ static int crypto_init_blkcipher_ops_async(struct crypto_tfm *tfm) crt->setkey = async_setkey; crt->encrypt = async_encrypt; crt->decrypt = async_decrypt; - if (!alg->ivsize) { - crt->givencrypt = skcipher_null_givencrypt; - crt->givdecrypt = skcipher_null_givdecrypt; - } crt->base = __crypto_ablkcipher_cast(tfm); crt->ivsize = alg->ivsize; @@ -560,185 +555,5 @@ const struct crypto_type crypto_blkcipher_type = { }; EXPORT_SYMBOL_GPL(crypto_blkcipher_type); -static int crypto_grab_nivcipher(struct crypto_skcipher_spawn *spawn, - const char *name, u32 type, u32 mask) -{ - struct crypto_alg *alg; - int err; - - type = crypto_skcipher_type(type); - mask = crypto_skcipher_mask(mask)| CRYPTO_ALG_GENIV; - - alg = crypto_alg_mod_lookup(name, type, mask); - if (IS_ERR(alg)) - return PTR_ERR(alg); - - err = crypto_init_spawn(&spawn->base, alg, spawn->base.inst, mask); - crypto_mod_put(alg); - return err; -} - -struct crypto_instance *skcipher_geniv_alloc(struct crypto_template *tmpl, - struct rtattr **tb, u32 type, - u32 mask) -{ - struct { - int (*setkey)(struct crypto_ablkcipher *tfm, const u8 *key, - unsigned int keylen); - int (*encrypt)(struct ablkcipher_request *req); - int (*decrypt)(struct ablkcipher_request *req); - - unsigned int min_keysize; - unsigned int max_keysize; - unsigned int ivsize; - - const char *geniv; - } balg; - const char *name; - struct crypto_skcipher_spawn *spawn; - struct crypto_attr_type *algt; - struct crypto_instance *inst; - struct crypto_alg *alg; - int err; - - algt = crypto_get_attr_type(tb); - if (IS_ERR(algt)) - return ERR_CAST(algt); - - if ((algt->type ^ (CRYPTO_ALG_TYPE_GIVCIPHER | CRYPTO_ALG_GENIV)) & - algt->mask) - return ERR_PTR(-EINVAL); - - name = crypto_attr_alg_name(tb[1]); - if (IS_ERR(name)) - return ERR_CAST(name); - - inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL); - if (!inst) - return ERR_PTR(-ENOMEM); - - spawn = crypto_instance_ctx(inst); - - /* Ignore async algorithms if necessary. */ - mask |= crypto_requires_sync(algt->type, algt->mask); - - crypto_set_skcipher_spawn(spawn, inst); - err = crypto_grab_nivcipher(spawn, name, type, mask); - if (err) - goto err_free_inst; - - alg = crypto_skcipher_spawn_alg(spawn); - - if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) == - CRYPTO_ALG_TYPE_BLKCIPHER) { - balg.ivsize = alg->cra_blkcipher.ivsize; - balg.min_keysize = alg->cra_blkcipher.min_keysize; - balg.max_keysize = alg->cra_blkcipher.max_keysize; - - balg.setkey = async_setkey; - balg.encrypt = async_encrypt; - balg.decrypt = async_decrypt; - - balg.geniv = alg->cra_blkcipher.geniv; - } else { - balg.ivsize = alg->cra_ablkcipher.ivsize; - balg.min_keysize = alg->cra_ablkcipher.min_keysize; - balg.max_keysize = alg->cra_ablkcipher.max_keysize; - - balg.setkey = alg->cra_ablkcipher.setkey; - balg.encrypt = alg->cra_ablkcipher.encrypt; - balg.decrypt = alg->cra_ablkcipher.decrypt; - - balg.geniv = alg->cra_ablkcipher.geniv; - } - - err = -EINVAL; - if (!balg.ivsize) - goto err_drop_alg; - - /* - * This is only true if we're constructing an algorithm with its - * default IV generator. For the default generator we elide the - * template name and double-check the IV generator. - */ - if (algt->mask & CRYPTO_ALG_GENIV) { - if (!balg.geniv) - balg.geniv = crypto_default_geniv(alg); - err = -EAGAIN; - if (strcmp(tmpl->name, balg.geniv)) - goto err_drop_alg; - - memcpy(inst->alg.cra_name, alg->cra_name, CRYPTO_MAX_ALG_NAME); - memcpy(inst->alg.cra_driver_name, alg->cra_driver_name, - CRYPTO_MAX_ALG_NAME); - } else { - err = -ENAMETOOLONG; - if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME, - "%s(%s)", tmpl->name, alg->cra_name) >= - CRYPTO_MAX_ALG_NAME) - goto err_drop_alg; - if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME, - "%s(%s)", tmpl->name, alg->cra_driver_name) >= - CRYPTO_MAX_ALG_NAME) - goto err_drop_alg; - } - - inst->alg.cra_flags = CRYPTO_ALG_TYPE_GIVCIPHER | CRYPTO_ALG_GENIV; - inst->alg.cra_flags |= alg->cra_flags & CRYPTO_ALG_ASYNC; - inst->alg.cra_priority = alg->cra_priority; - inst->alg.cra_blocksize = alg->cra_blocksize; - inst->alg.cra_alignmask = alg->cra_alignmask; - inst->alg.cra_type = &crypto_givcipher_type; - - inst->alg.cra_ablkcipher.ivsize = balg.ivsize; - inst->alg.cra_ablkcipher.min_keysize = balg.min_keysize; - inst->alg.cra_ablkcipher.max_keysize = balg.max_keysize; - inst->alg.cra_ablkcipher.geniv = balg.geniv; - - inst->alg.cra_ablkcipher.setkey = balg.setkey; - inst->alg.cra_ablkcipher.encrypt = balg.encrypt; - inst->alg.cra_ablkcipher.decrypt = balg.decrypt; - -out: - return inst; - -err_drop_alg: - crypto_drop_skcipher(spawn); -err_free_inst: - kfree(inst); - inst = ERR_PTR(err); - goto out; -} -EXPORT_SYMBOL_GPL(skcipher_geniv_alloc); - -void skcipher_geniv_free(struct crypto_instance *inst) -{ - crypto_drop_skcipher(crypto_instance_ctx(inst)); - kfree(inst); -} -EXPORT_SYMBOL_GPL(skcipher_geniv_free); - -int skcipher_geniv_init(struct crypto_tfm *tfm) -{ - struct crypto_instance *inst = (void *)tfm->__crt_alg; - struct crypto_ablkcipher *cipher; - - cipher = crypto_spawn_skcipher(crypto_instance_ctx(inst)); - if (IS_ERR(cipher)) - return PTR_ERR(cipher); - - tfm->crt_ablkcipher.base = cipher; - tfm->crt_ablkcipher.reqsize += crypto_ablkcipher_reqsize(cipher); - - return 0; -} -EXPORT_SYMBOL_GPL(skcipher_geniv_init); - -void skcipher_geniv_exit(struct crypto_tfm *tfm) -{ - crypto_free_ablkcipher(tfm->crt_ablkcipher.base); -} -EXPORT_SYMBOL_GPL(skcipher_geniv_exit); - MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Generic block chaining cipher type"); diff --git a/crypto/chainiv.c b/crypto/chainiv.c deleted file mode 100644 index b4340018c8d4..000000000000 --- a/crypto/chainiv.c +++ /dev/null @@ -1,317 +0,0 @@ -/* - * chainiv: Chain IV Generator - * - * Generate IVs simply be using the last block of the previous encryption. - * This is mainly useful for CBC with a synchronous algorithm. - * - * Copyright (c) 2007 Herbert Xu - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -enum { - CHAINIV_STATE_INUSE = 0, -}; - -struct chainiv_ctx { - spinlock_t lock; - char iv[]; -}; - -struct async_chainiv_ctx { - unsigned long state; - - spinlock_t lock; - int err; - - struct crypto_queue queue; - struct work_struct postponed; - - char iv[]; -}; - -static int chainiv_givencrypt(struct skcipher_givcrypt_request *req) -{ - struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req); - struct chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv); - struct ablkcipher_request *subreq = skcipher_givcrypt_reqctx(req); - unsigned int ivsize; - int err; - - ablkcipher_request_set_tfm(subreq, skcipher_geniv_cipher(geniv)); - ablkcipher_request_set_callback(subreq, req->creq.base.flags & - ~CRYPTO_TFM_REQ_MAY_SLEEP, - req->creq.base.complete, - req->creq.base.data); - ablkcipher_request_set_crypt(subreq, req->creq.src, req->creq.dst, - req->creq.nbytes, req->creq.info); - - spin_lock_bh(&ctx->lock); - - ivsize = crypto_ablkcipher_ivsize(geniv); - - memcpy(req->giv, ctx->iv, ivsize); - memcpy(subreq->info, ctx->iv, ivsize); - - err = crypto_ablkcipher_encrypt(subreq); - if (err) - goto unlock; - - memcpy(ctx->iv, subreq->info, ivsize); - -unlock: - spin_unlock_bh(&ctx->lock); - - return err; -} - -static int chainiv_init_common(struct crypto_tfm *tfm, char iv[]) -{ - struct crypto_ablkcipher *geniv = __crypto_ablkcipher_cast(tfm); - int err = 0; - - tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request); - - if (iv) { - err = crypto_rng_get_bytes(crypto_default_rng, iv, - crypto_ablkcipher_ivsize(geniv)); - crypto_put_default_rng(); - } - - return err ?: skcipher_geniv_init(tfm); -} - -static int chainiv_init(struct crypto_tfm *tfm) -{ - struct crypto_ablkcipher *geniv = __crypto_ablkcipher_cast(tfm); - struct chainiv_ctx *ctx = crypto_tfm_ctx(tfm); - char *iv; - - spin_lock_init(&ctx->lock); - - iv = NULL; - if (!crypto_get_default_rng()) { - crypto_ablkcipher_crt(geniv)->givencrypt = chainiv_givencrypt; - iv = ctx->iv; - } - - return chainiv_init_common(tfm, iv); -} - -static int async_chainiv_schedule_work(struct async_chainiv_ctx *ctx) -{ - int queued; - int err = ctx->err; - - if (!ctx->queue.qlen) { - smp_mb__before_atomic(); - clear_bit(CHAINIV_STATE_INUSE, &ctx->state); - - if (!ctx->queue.qlen || - test_and_set_bit(CHAINIV_STATE_INUSE, &ctx->state)) - goto out; - } - - queued = queue_work(kcrypto_wq, &ctx->postponed); - BUG_ON(!queued); - -out: - return err; -} - -static int async_chainiv_postpone_request(struct skcipher_givcrypt_request *req) -{ - struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req); - struct async_chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv); - int err; - - spin_lock_bh(&ctx->lock); - err = skcipher_enqueue_givcrypt(&ctx->queue, req); - spin_unlock_bh(&ctx->lock); - - if (test_and_set_bit(CHAINIV_STATE_INUSE, &ctx->state)) - return err; - - ctx->err = err; - return async_chainiv_schedule_work(ctx); -} - -static int async_chainiv_givencrypt_tail(struct skcipher_givcrypt_request *req) -{ - struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req); - struct async_chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv); - struct ablkcipher_request *subreq = skcipher_givcrypt_reqctx(req); - unsigned int ivsize = crypto_ablkcipher_ivsize(geniv); - - memcpy(req->giv, ctx->iv, ivsize); - memcpy(subreq->info, ctx->iv, ivsize); - - ctx->err = crypto_ablkcipher_encrypt(subreq); - if (ctx->err) - goto out; - - memcpy(ctx->iv, subreq->info, ivsize); - -out: - return async_chainiv_schedule_work(ctx); -} - -static int async_chainiv_givencrypt(struct skcipher_givcrypt_request *req) -{ - struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req); - struct async_chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv); - struct ablkcipher_request *subreq = skcipher_givcrypt_reqctx(req); - - ablkcipher_request_set_tfm(subreq, skcipher_geniv_cipher(geniv)); - ablkcipher_request_set_callback(subreq, req->creq.base.flags, - req->creq.base.complete, - req->creq.base.data); - ablkcipher_request_set_crypt(subreq, req->creq.src, req->creq.dst, - req->creq.nbytes, req->creq.info); - - if (test_and_set_bit(CHAINIV_STATE_INUSE, &ctx->state)) - goto postpone; - - if (ctx->queue.qlen) { - clear_bit(CHAINIV_STATE_INUSE, &ctx->state); - goto postpone; - } - - return async_chainiv_givencrypt_tail(req); - -postpone: - return async_chainiv_postpone_request(req); -} - -static void async_chainiv_do_postponed(struct work_struct *work) -{ - struct async_chainiv_ctx *ctx = container_of(work, - struct async_chainiv_ctx, - postponed); - struct skcipher_givcrypt_request *req; - struct ablkcipher_request *subreq; - int err; - - /* Only handle one request at a time to avoid hogging keventd. */ - spin_lock_bh(&ctx->lock); - req = skcipher_dequeue_givcrypt(&ctx->queue); - spin_unlock_bh(&ctx->lock); - - if (!req) { - async_chainiv_schedule_work(ctx); - return; - } - - subreq = skcipher_givcrypt_reqctx(req); - subreq->base.flags |= CRYPTO_TFM_REQ_MAY_SLEEP; - - err = async_chainiv_givencrypt_tail(req); - - local_bh_disable(); - skcipher_givcrypt_complete(req, err); - local_bh_enable(); -} - -static int async_chainiv_init(struct crypto_tfm *tfm) -{ - struct crypto_ablkcipher *geniv = __crypto_ablkcipher_cast(tfm); - struct async_chainiv_ctx *ctx = crypto_tfm_ctx(tfm); - char *iv; - - spin_lock_init(&ctx->lock); - - crypto_init_queue(&ctx->queue, 100); - INIT_WORK(&ctx->postponed, async_chainiv_do_postponed); - - iv = NULL; - if (!crypto_get_default_rng()) { - crypto_ablkcipher_crt(geniv)->givencrypt = - async_chainiv_givencrypt; - iv = ctx->iv; - } - - return chainiv_init_common(tfm, iv); -} - -static void async_chainiv_exit(struct crypto_tfm *tfm) -{ - struct async_chainiv_ctx *ctx = crypto_tfm_ctx(tfm); - - BUG_ON(test_bit(CHAINIV_STATE_INUSE, &ctx->state) || ctx->queue.qlen); - - skcipher_geniv_exit(tfm); -} - -static struct crypto_template chainiv_tmpl; - -static struct crypto_instance *chainiv_alloc(struct rtattr **tb) -{ - struct crypto_attr_type *algt; - struct crypto_instance *inst; - - algt = crypto_get_attr_type(tb); - if (IS_ERR(algt)) - return ERR_CAST(algt); - - inst = skcipher_geniv_alloc(&chainiv_tmpl, tb, 0, 0); - if (IS_ERR(inst)) - goto out; - - inst->alg.cra_init = chainiv_init; - inst->alg.cra_exit = skcipher_geniv_exit; - - inst->alg.cra_ctxsize = sizeof(struct chainiv_ctx); - - if (!crypto_requires_sync(algt->type, algt->mask)) { - inst->alg.cra_flags |= CRYPTO_ALG_ASYNC; - - inst->alg.cra_init = async_chainiv_init; - inst->alg.cra_exit = async_chainiv_exit; - - inst->alg.cra_ctxsize = sizeof(struct async_chainiv_ctx); - } - - inst->alg.cra_ctxsize += inst->alg.cra_ablkcipher.ivsize; - -out: - return inst; -} - -static struct crypto_template chainiv_tmpl = { - .name = "chainiv", - .alloc = chainiv_alloc, - .free = skcipher_geniv_free, - .module = THIS_MODULE, -}; - -static int __init chainiv_module_init(void) -{ - return crypto_register_template(&chainiv_tmpl); -} - -static void chainiv_module_exit(void) -{ - crypto_unregister_template(&chainiv_tmpl); -} - -module_init(chainiv_module_init); -module_exit(chainiv_module_exit); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Chain IV Generator"); -MODULE_ALIAS_CRYPTO("chainiv"); diff --git a/crypto/eseqiv.c b/crypto/eseqiv.c deleted file mode 100644 index 16dda72fc4f8..000000000000 --- a/crypto/eseqiv.c +++ /dev/null @@ -1,242 +0,0 @@ -/* - * eseqiv: Encrypted Sequence Number IV Generator - * - * This generator generates an IV based on a sequence number by xoring it - * with a salt and then encrypting it with the same key as used to encrypt - * the plain text. This algorithm requires that the block size be equal - * to the IV size. It is mainly useful for CBC. - * - * Copyright (c) 2007 Herbert Xu - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct eseqiv_request_ctx { - struct scatterlist src[2]; - struct scatterlist dst[2]; - char tail[]; -}; - -struct eseqiv_ctx { - spinlock_t lock; - unsigned int reqoff; - char salt[]; -}; - -static void eseqiv_complete2(struct skcipher_givcrypt_request *req) -{ - struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req); - struct eseqiv_request_ctx *reqctx = skcipher_givcrypt_reqctx(req); - - memcpy(req->giv, PTR_ALIGN((u8 *)reqctx->tail, - crypto_ablkcipher_alignmask(geniv) + 1), - crypto_ablkcipher_ivsize(geniv)); -} - -static void eseqiv_complete(struct crypto_async_request *base, int err) -{ - struct skcipher_givcrypt_request *req = base->data; - - if (err) - goto out; - - eseqiv_complete2(req); - -out: - skcipher_givcrypt_complete(req, err); -} - -static int eseqiv_givencrypt(struct skcipher_givcrypt_request *req) -{ - struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req); - struct eseqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv); - struct eseqiv_request_ctx *reqctx = skcipher_givcrypt_reqctx(req); - struct ablkcipher_request *subreq; - crypto_completion_t compl; - void *data; - struct scatterlist *osrc, *odst; - struct scatterlist *dst; - struct page *srcp; - struct page *dstp; - u8 *giv; - u8 *vsrc; - u8 *vdst; - __be64 seq; - unsigned int ivsize; - unsigned int len; - int err; - - subreq = (void *)(reqctx->tail + ctx->reqoff); - ablkcipher_request_set_tfm(subreq, skcipher_geniv_cipher(geniv)); - - giv = req->giv; - compl = req->creq.base.complete; - data = req->creq.base.data; - - osrc = req->creq.src; - odst = req->creq.dst; - srcp = sg_page(osrc); - dstp = sg_page(odst); - vsrc = PageHighMem(srcp) ? NULL : page_address(srcp) + osrc->offset; - vdst = PageHighMem(dstp) ? NULL : page_address(dstp) + odst->offset; - - ivsize = crypto_ablkcipher_ivsize(geniv); - - if (vsrc != giv + ivsize && vdst != giv + ivsize) { - giv = PTR_ALIGN((u8 *)reqctx->tail, - crypto_ablkcipher_alignmask(geniv) + 1); - compl = eseqiv_complete; - data = req; - } - - ablkcipher_request_set_callback(subreq, req->creq.base.flags, compl, - data); - - sg_init_table(reqctx->src, 2); - sg_set_buf(reqctx->src, giv, ivsize); - scatterwalk_crypto_chain(reqctx->src, osrc, vsrc == giv + ivsize, 2); - - dst = reqctx->src; - if (osrc != odst) { - sg_init_table(reqctx->dst, 2); - sg_set_buf(reqctx->dst, giv, ivsize); - scatterwalk_crypto_chain(reqctx->dst, odst, vdst == giv + ivsize, 2); - - dst = reqctx->dst; - } - - ablkcipher_request_set_crypt(subreq, reqctx->src, dst, - req->creq.nbytes + ivsize, - req->creq.info); - - memcpy(req->creq.info, ctx->salt, ivsize); - - len = ivsize; - if (ivsize > sizeof(u64)) { - memset(req->giv, 0, ivsize - sizeof(u64)); - len = sizeof(u64); - } - seq = cpu_to_be64(req->seq); - memcpy(req->giv + ivsize - len, &seq, len); - - err = crypto_ablkcipher_encrypt(subreq); - if (err) - goto out; - - if (giv != req->giv) - eseqiv_complete2(req); - -out: - return err; -} - -static int eseqiv_init(struct crypto_tfm *tfm) -{ - struct crypto_ablkcipher *geniv = __crypto_ablkcipher_cast(tfm); - struct eseqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv); - unsigned long alignmask; - unsigned int reqsize; - int err; - - spin_lock_init(&ctx->lock); - - alignmask = crypto_tfm_ctx_alignment() - 1; - reqsize = sizeof(struct eseqiv_request_ctx); - - if (alignmask & reqsize) { - alignmask &= reqsize; - alignmask--; - } - - alignmask = ~alignmask; - alignmask &= crypto_ablkcipher_alignmask(geniv); - - reqsize += alignmask; - reqsize += crypto_ablkcipher_ivsize(geniv); - reqsize = ALIGN(reqsize, crypto_tfm_ctx_alignment()); - - ctx->reqoff = reqsize - sizeof(struct eseqiv_request_ctx); - - tfm->crt_ablkcipher.reqsize = reqsize + - sizeof(struct ablkcipher_request); - - err = 0; - if (!crypto_get_default_rng()) { - crypto_ablkcipher_crt(geniv)->givencrypt = eseqiv_givencrypt; - err = crypto_rng_get_bytes(crypto_default_rng, ctx->salt, - crypto_ablkcipher_ivsize(geniv)); - crypto_put_default_rng(); - } - - return err ?: skcipher_geniv_init(tfm); -} - -static struct crypto_template eseqiv_tmpl; - -static struct crypto_instance *eseqiv_alloc(struct rtattr **tb) -{ - struct crypto_instance *inst; - int err; - - inst = skcipher_geniv_alloc(&eseqiv_tmpl, tb, 0, 0); - if (IS_ERR(inst)) - goto out; - - err = -EINVAL; - if (inst->alg.cra_ablkcipher.ivsize != inst->alg.cra_blocksize) - goto free_inst; - - inst->alg.cra_init = eseqiv_init; - inst->alg.cra_exit = skcipher_geniv_exit; - - inst->alg.cra_ctxsize = sizeof(struct eseqiv_ctx); - inst->alg.cra_ctxsize += inst->alg.cra_ablkcipher.ivsize; - -out: - return inst; - -free_inst: - skcipher_geniv_free(inst); - inst = ERR_PTR(err); - goto out; -} - -static struct crypto_template eseqiv_tmpl = { - .name = "eseqiv", - .alloc = eseqiv_alloc, - .free = skcipher_geniv_free, - .module = THIS_MODULE, -}; - -static int __init eseqiv_module_init(void) -{ - return crypto_register_template(&eseqiv_tmpl); -} - -static void __exit eseqiv_module_exit(void) -{ - crypto_unregister_template(&eseqiv_tmpl); -} - -module_init(eseqiv_module_init); -module_exit(eseqiv_module_exit); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Encrypted Sequence Number IV Generator"); -MODULE_ALIAS_CRYPTO("eseqiv"); diff --git a/crypto/seqiv.c b/crypto/seqiv.c index a859b3ae239d..c7049231861f 100644 --- a/crypto/seqiv.c +++ b/crypto/seqiv.c @@ -14,50 +14,17 @@ */ #include -#include -#include #include +#include #include #include #include #include #include -#include #include -struct seqiv_ctx { - spinlock_t lock; - u8 salt[] __attribute__ ((aligned(__alignof__(u32)))); -}; - static void seqiv_free(struct crypto_instance *inst); -static void seqiv_complete2(struct skcipher_givcrypt_request *req, int err) -{ - struct ablkcipher_request *subreq = skcipher_givcrypt_reqctx(req); - struct crypto_ablkcipher *geniv; - - if (err == -EINPROGRESS) - return; - - if (err) - goto out; - - geniv = skcipher_givcrypt_reqtfm(req); - memcpy(req->creq.info, subreq->info, crypto_ablkcipher_ivsize(geniv)); - -out: - kfree(subreq->info); -} - -static void seqiv_complete(struct crypto_async_request *base, int err) -{ - struct skcipher_givcrypt_request *req = base->data; - - seqiv_complete2(req, err); - skcipher_givcrypt_complete(req, err); -} - static void seqiv_aead_encrypt_complete2(struct aead_request *req, int err) { struct aead_request *subreq = aead_request_ctx(req); @@ -85,65 +52,6 @@ static void seqiv_aead_encrypt_complete(struct crypto_async_request *base, aead_request_complete(req, err); } -static void seqiv_geniv(struct seqiv_ctx *ctx, u8 *info, u64 seq, - unsigned int ivsize) -{ - unsigned int len = ivsize; - - if (ivsize > sizeof(u64)) { - memset(info, 0, ivsize - sizeof(u64)); - len = sizeof(u64); - } - seq = cpu_to_be64(seq); - memcpy(info + ivsize - len, &seq, len); - crypto_xor(info, ctx->salt, ivsize); -} - -static int seqiv_givencrypt(struct skcipher_givcrypt_request *req) -{ - struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req); - struct seqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv); - struct ablkcipher_request *subreq = skcipher_givcrypt_reqctx(req); - crypto_completion_t compl; - void *data; - u8 *info; - unsigned int ivsize; - int err; - - ablkcipher_request_set_tfm(subreq, skcipher_geniv_cipher(geniv)); - - compl = req->creq.base.complete; - data = req->creq.base.data; - info = req->creq.info; - - ivsize = crypto_ablkcipher_ivsize(geniv); - - if (unlikely(!IS_ALIGNED((unsigned long)info, - crypto_ablkcipher_alignmask(geniv) + 1))) { - info = kmalloc(ivsize, req->creq.base.flags & - CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL: - GFP_ATOMIC); - if (!info) - return -ENOMEM; - - compl = seqiv_complete; - data = req; - } - - ablkcipher_request_set_callback(subreq, req->creq.base.flags, compl, - data); - ablkcipher_request_set_crypt(subreq, req->creq.src, req->creq.dst, - req->creq.nbytes, info); - - seqiv_geniv(ctx, info, req->seq, ivsize); - memcpy(req->giv, info, ivsize); - - err = crypto_ablkcipher_encrypt(subreq); - if (unlikely(info != req->creq.info)) - seqiv_complete2(req, err); - return err; -} - static int seqiv_aead_encrypt(struct aead_request *req) { struct crypto_aead *geniv = crypto_aead_reqtfm(req); @@ -233,62 +141,6 @@ static int seqiv_aead_decrypt(struct aead_request *req) return crypto_aead_decrypt(subreq); } -static int seqiv_init(struct crypto_tfm *tfm) -{ - struct crypto_ablkcipher *geniv = __crypto_ablkcipher_cast(tfm); - struct seqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv); - int err; - - spin_lock_init(&ctx->lock); - - tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request); - - err = 0; - if (!crypto_get_default_rng()) { - crypto_ablkcipher_crt(geniv)->givencrypt = seqiv_givencrypt; - err = crypto_rng_get_bytes(crypto_default_rng, ctx->salt, - crypto_ablkcipher_ivsize(geniv)); - crypto_put_default_rng(); - } - - return err ?: skcipher_geniv_init(tfm); -} - -static int seqiv_ablkcipher_create(struct crypto_template *tmpl, - struct rtattr **tb) -{ - struct crypto_instance *inst; - int err; - - inst = skcipher_geniv_alloc(tmpl, tb, 0, 0); - - if (IS_ERR(inst)) - return PTR_ERR(inst); - - err = -EINVAL; - if (inst->alg.cra_ablkcipher.ivsize < sizeof(u64)) - goto free_inst; - - inst->alg.cra_init = seqiv_init; - inst->alg.cra_exit = skcipher_geniv_exit; - - inst->alg.cra_ctxsize += inst->alg.cra_ablkcipher.ivsize; - inst->alg.cra_ctxsize += sizeof(struct seqiv_ctx); - - inst->alg.cra_alignmask |= __alignof__(u32) - 1; - - err = crypto_register_instance(tmpl, inst); - if (err) - goto free_inst; - -out: - return err; - -free_inst: - skcipher_geniv_free(inst); - goto out; -} - static int seqiv_aead_create(struct crypto_template *tmpl, struct rtattr **tb) { struct aead_instance *inst; @@ -334,26 +186,20 @@ free_inst: static int seqiv_create(struct crypto_template *tmpl, struct rtattr **tb) { struct crypto_attr_type *algt; - int err; algt = crypto_get_attr_type(tb); if (IS_ERR(algt)) return PTR_ERR(algt); if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & CRYPTO_ALG_TYPE_MASK) - err = seqiv_ablkcipher_create(tmpl, tb); - else - err = seqiv_aead_create(tmpl, tb); + return -EINVAL; - return err; + return seqiv_aead_create(tmpl, tb); } static void seqiv_free(struct crypto_instance *inst) { - if ((inst->alg.cra_flags ^ CRYPTO_ALG_TYPE_AEAD) & CRYPTO_ALG_TYPE_MASK) - skcipher_geniv_free(inst); - else - aead_geniv_free(aead_instance(inst)); + aead_geniv_free(aead_instance(inst)); } static struct crypto_template seqiv_tmpl = { diff --git a/crypto/skcipher.c b/crypto/skcipher.c index d248008e7f7b..f7d0018dcaee 100644 --- a/crypto/skcipher.c +++ b/crypto/skcipher.c @@ -325,13 +325,13 @@ static const struct crypto_type crypto_skcipher_type2 = { .tfmsize = offsetof(struct crypto_skcipher, base), }; -int crypto_grab_skcipher2(struct crypto_skcipher_spawn *spawn, +int crypto_grab_skcipher(struct crypto_skcipher_spawn *spawn, const char *name, u32 type, u32 mask) { spawn->base.frontend = &crypto_skcipher_type2; return crypto_grab_spawn(&spawn->base, name, type, mask); } -EXPORT_SYMBOL_GPL(crypto_grab_skcipher2); +EXPORT_SYMBOL_GPL(crypto_grab_skcipher); struct crypto_skcipher *crypto_alloc_skcipher(const char *alg_name, u32 type, u32 mask) diff --git a/include/crypto/internal/skcipher.h b/include/crypto/internal/skcipher.h index ce6619c339fe..a21a95e1a375 100644 --- a/include/crypto/internal/skcipher.h +++ b/include/crypto/internal/skcipher.h @@ -67,8 +67,12 @@ static inline void crypto_set_skcipher_spawn( int crypto_grab_skcipher(struct crypto_skcipher_spawn *spawn, const char *name, u32 type, u32 mask); -int crypto_grab_skcipher2(struct crypto_skcipher_spawn *spawn, - const char *name, u32 type, u32 mask); + +static inline int crypto_grab_skcipher2(struct crypto_skcipher_spawn *spawn, + const char *name, u32 type, u32 mask) +{ + return crypto_grab_skcipher(spawn, name, type, mask); +} struct crypto_alg *crypto_lookup_skcipher(const char *name, u32 type, u32 mask); @@ -77,30 +81,28 @@ static inline void crypto_drop_skcipher(struct crypto_skcipher_spawn *spawn) crypto_drop_spawn(&spawn->base); } -static inline struct crypto_alg *crypto_skcipher_spawn_alg( +static inline struct skcipher_alg *crypto_skcipher_spawn_alg( struct crypto_skcipher_spawn *spawn) { - return spawn->base.alg; + return container_of(spawn->base.alg, struct skcipher_alg, base); } static inline struct skcipher_alg *crypto_spawn_skcipher_alg( struct crypto_skcipher_spawn *spawn) { - return container_of(spawn->base.alg, struct skcipher_alg, base); + return crypto_skcipher_spawn_alg(spawn); } -static inline struct crypto_ablkcipher *crypto_spawn_skcipher( +static inline struct crypto_skcipher *crypto_spawn_skcipher( struct crypto_skcipher_spawn *spawn) { - return __crypto_ablkcipher_cast( - crypto_spawn_tfm(&spawn->base, crypto_skcipher_type(0), - crypto_skcipher_mask(0))); + return crypto_spawn_tfm2(&spawn->base); } static inline struct crypto_skcipher *crypto_spawn_skcipher2( struct crypto_skcipher_spawn *spawn) { - return crypto_spawn_tfm2(&spawn->base); + return crypto_spawn_skcipher(spawn); } static inline void crypto_skcipher_set_reqsize( @@ -116,53 +118,12 @@ void crypto_unregister_skciphers(struct skcipher_alg *algs, int count); int skcipher_register_instance(struct crypto_template *tmpl, struct skcipher_instance *inst); -int skcipher_null_givencrypt(struct skcipher_givcrypt_request *req); -int skcipher_null_givdecrypt(struct skcipher_givcrypt_request *req); -const char *crypto_default_geniv(const struct crypto_alg *alg); - -struct crypto_instance *skcipher_geniv_alloc(struct crypto_template *tmpl, - struct rtattr **tb, u32 type, - u32 mask); -void skcipher_geniv_free(struct crypto_instance *inst); -int skcipher_geniv_init(struct crypto_tfm *tfm); -void skcipher_geniv_exit(struct crypto_tfm *tfm); - -static inline struct crypto_ablkcipher *skcipher_geniv_cipher( - struct crypto_ablkcipher *geniv) -{ - return crypto_ablkcipher_crt(geniv)->base; -} - -static inline int skcipher_enqueue_givcrypt( - struct crypto_queue *queue, struct skcipher_givcrypt_request *request) -{ - return ablkcipher_enqueue_request(queue, &request->creq); -} - -static inline struct skcipher_givcrypt_request *skcipher_dequeue_givcrypt( - struct crypto_queue *queue) -{ - return skcipher_givcrypt_cast(crypto_dequeue_request(queue)); -} - -static inline void *skcipher_givcrypt_reqctx( - struct skcipher_givcrypt_request *req) -{ - return ablkcipher_request_ctx(&req->creq); -} - static inline void ablkcipher_request_complete(struct ablkcipher_request *req, int err) { req->base.complete(&req->base, err); } -static inline void skcipher_givcrypt_complete( - struct skcipher_givcrypt_request *req, int err) -{ - ablkcipher_request_complete(&req->creq, err); -} - static inline u32 ablkcipher_request_flags(struct ablkcipher_request *req) { return req->base.flags; diff --git a/include/crypto/skcipher.h b/include/crypto/skcipher.h index a381f57ea695..59c8f6c593e6 100644 --- a/include/crypto/skcipher.h +++ b/include/crypto/skcipher.h @@ -139,82 +139,6 @@ struct skcipher_alg { crypto_skcipher_reqsize(tfm)] CRYPTO_MINALIGN_ATTR; \ struct skcipher_request *name = (void *)__##name##_desc -static inline struct crypto_ablkcipher *skcipher_givcrypt_reqtfm( - struct skcipher_givcrypt_request *req) -{ - return crypto_ablkcipher_reqtfm(&req->creq); -} - -static inline int crypto_skcipher_givencrypt( - struct skcipher_givcrypt_request *req) -{ - struct ablkcipher_tfm *crt = - crypto_ablkcipher_crt(skcipher_givcrypt_reqtfm(req)); - return crt->givencrypt(req); -}; - -static inline int crypto_skcipher_givdecrypt( - struct skcipher_givcrypt_request *req) -{ - struct ablkcipher_tfm *crt = - crypto_ablkcipher_crt(skcipher_givcrypt_reqtfm(req)); - return crt->givdecrypt(req); -}; - -static inline void skcipher_givcrypt_set_tfm( - struct skcipher_givcrypt_request *req, struct crypto_ablkcipher *tfm) -{ - req->creq.base.tfm = crypto_ablkcipher_tfm(tfm); -} - -static inline struct skcipher_givcrypt_request *skcipher_givcrypt_cast( - struct crypto_async_request *req) -{ - return container_of(ablkcipher_request_cast(req), - struct skcipher_givcrypt_request, creq); -} - -static inline struct skcipher_givcrypt_request *skcipher_givcrypt_alloc( - struct crypto_ablkcipher *tfm, gfp_t gfp) -{ - struct skcipher_givcrypt_request *req; - - req = kmalloc(sizeof(struct skcipher_givcrypt_request) + - crypto_ablkcipher_reqsize(tfm), gfp); - - if (likely(req)) - skcipher_givcrypt_set_tfm(req, tfm); - - return req; -} - -static inline void skcipher_givcrypt_free(struct skcipher_givcrypt_request *req) -{ - kfree(req); -} - -static inline void skcipher_givcrypt_set_callback( - struct skcipher_givcrypt_request *req, u32 flags, - crypto_completion_t compl, void *data) -{ - ablkcipher_request_set_callback(&req->creq, flags, compl, data); -} - -static inline void skcipher_givcrypt_set_crypt( - struct skcipher_givcrypt_request *req, - struct scatterlist *src, struct scatterlist *dst, - unsigned int nbytes, void *iv) -{ - ablkcipher_request_set_crypt(&req->creq, src, dst, nbytes, iv); -} - -static inline void skcipher_givcrypt_set_giv( - struct skcipher_givcrypt_request *req, u8 *giv, u64 seq) -{ - req->giv = giv; - req->seq = seq; -} - /** * DOC: Symmetric Key Cipher API * diff --git a/include/linux/crypto.h b/include/linux/crypto.h index 37a652d1639d..7cee5551625b 100644 --- a/include/linux/crypto.h +++ b/include/linux/crypto.h @@ -488,8 +488,6 @@ struct ablkcipher_tfm { unsigned int keylen); int (*encrypt)(struct ablkcipher_request *req); int (*decrypt)(struct ablkcipher_request *req); - int (*givencrypt)(struct skcipher_givcrypt_request *req); - int (*givdecrypt)(struct skcipher_givcrypt_request *req); struct crypto_ablkcipher *base; @@ -714,23 +712,6 @@ static inline u32 crypto_skcipher_mask(u32 mask) * state information is unused by the kernel crypto API. */ -/** - * crypto_alloc_ablkcipher() - allocate asynchronous block cipher handle - * @alg_name: is the cra_name / name or cra_driver_name / driver name of the - * ablkcipher cipher - * @type: specifies the type of the cipher - * @mask: specifies the mask for the cipher - * - * Allocate a cipher handle for an ablkcipher. The returned struct - * crypto_ablkcipher is the cipher handle that is required for any subsequent - * API invocation for that ablkcipher. - * - * Return: allocated cipher handle in case of success; IS_ERR() is true in case - * of an error, PTR_ERR() returns the error code. - */ -struct crypto_ablkcipher *crypto_alloc_ablkcipher(const char *alg_name, - u32 type, u32 mask); - static inline struct crypto_tfm *crypto_ablkcipher_tfm( struct crypto_ablkcipher *tfm) { -- cgit