From 56b20012d77d20bbf8eb42974468738bc3a6b29f Mon Sep 17 00:00:00 2001 From: Alexander Boyko Date: Thu, 10 Jan 2013 18:54:59 +0400 Subject: crypto: crc32 - add crc32 pclmulqdq implementation and wrappers for table implementation This patch adds crc32 algorithms to shash crypto api. One is wrapper to gerneric crc32_le function. Second is crc32 pclmulqdq implementation. It use hardware provided PCLMULQDQ instruction to accelerate the CRC32 disposal. This instruction present from Intel Westmere and AMD Bulldozer CPUs. For intel core i5 I got 450MB/s for table implementation and 2100MB/s for pclmulqdq implementation. Signed-off-by: Alexander Boyko Signed-off-by: Herbert Xu --- crypto/Kconfig | 21 ++++++++ crypto/Makefile | 1 + crypto/crc32.c | 158 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 180 insertions(+) create mode 100644 crypto/crc32.c diff --git a/crypto/Kconfig b/crypto/Kconfig index 4641d956..e8b51e06 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -355,6 +355,27 @@ config CRYPTO_CRC32C_SPARC64 CRC32c CRC algorithm implemented using sparc64 crypto instructions, when available. +config CRYPTO_CRC32 + tristate "CRC32 CRC algorithm" + select CRYPTO_HASH + select CRC32 + help + CRC-32-IEEE 802.3 cyclic redundancy-check algorithm. + Shash crypto api wrappers to crc32_le function. + +config CRYPTO_CRC32_PCLMUL + tristate "CRC32 PCLMULQDQ hardware acceleration" + depends on X86 + select CRYPTO_HASH + select CRC32 + help + From Intel Westmere and AMD Bulldozer processor with SSE4.2 + and PCLMULQDQ supported, the processor will support + CRC32 PCLMULQDQ implementation using hardware accelerated PCLMULQDQ + instruction. This option will create 'crc32-plcmul' module, + which will enable any routine to use the CRC-32-IEEE 802.3 checksum + and gain better performance as compared with the table implementation. + config CRYPTO_GHASH tristate "GHASH digest algorithm" select CRYPTO_GF128MUL diff --git a/crypto/Makefile b/crypto/Makefile index d59dec74..be1a1beb 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -81,6 +81,7 @@ obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o obj-$(CONFIG_CRYPTO_ZLIB) += zlib.o obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o +obj-$(CONFIG_CRYPTO_CRC32) += crc32.o obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o authencesn.o obj-$(CONFIG_CRYPTO_LZO) += lzo.o obj-$(CONFIG_CRYPTO_842) += 842.o diff --git a/crypto/crc32.c b/crypto/crc32.c new file mode 100644 index 00000000..9d1c4156 --- /dev/null +++ b/crypto/crc32.c @@ -0,0 +1,158 @@ +/* GPL HEADER START + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License version 2 for more details (a copy is included + * in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; If not, see http://www.gnu.org/licenses + * + * Please visit http://www.xyratex.com/contact if you need additional + * information or have any questions. + * + * GPL HEADER END + */ + +/* + * Copyright 2012 Xyratex Technology Limited + */ + +/* + * This is crypto api shash wrappers to crc32_le. + */ + +#include +#include +#include +#include +#include +#include + +#define CHKSUM_BLOCK_SIZE 1 +#define CHKSUM_DIGEST_SIZE 4 + +static u32 __crc32_le(u32 crc, unsigned char const *p, size_t len) +{ + return crc32_le(crc, p, len); +} + +/** No default init with ~0 */ +static int crc32_cra_init(struct crypto_tfm *tfm) +{ + u32 *key = crypto_tfm_ctx(tfm); + + *key = 0; + + return 0; +} + + +/* + * Setting the seed allows arbitrary accumulators and flexible XOR policy + * If your algorithm starts with ~0, then XOR with ~0 before you set + * the seed. + */ +static int crc32_setkey(struct crypto_shash *hash, const u8 *key, + unsigned int keylen) +{ + u32 *mctx = crypto_shash_ctx(hash); + + if (keylen != sizeof(u32)) { + crypto_shash_set_flags(hash, CRYPTO_TFM_RES_BAD_KEY_LEN); + return -EINVAL; + } + *mctx = le32_to_cpup((__le32 *)key); + return 0; +} + +static int crc32_init(struct shash_desc *desc) +{ + u32 *mctx = crypto_shash_ctx(desc->tfm); + u32 *crcp = shash_desc_ctx(desc); + + *crcp = *mctx; + + return 0; +} + +static int crc32_update(struct shash_desc *desc, const u8 *data, + unsigned int len) +{ + u32 *crcp = shash_desc_ctx(desc); + + *crcp = __crc32_le(*crcp, data, len); + return 0; +} + +/* No final XOR 0xFFFFFFFF, like crc32_le */ +static int __crc32_finup(u32 *crcp, const u8 *data, unsigned int len, + u8 *out) +{ + *(__le32 *)out = cpu_to_le32(__crc32_le(*crcp, data, len)); + return 0; +} + +static int crc32_finup(struct shash_desc *desc, const u8 *data, + unsigned int len, u8 *out) +{ + return __crc32_finup(shash_desc_ctx(desc), data, len, out); +} + +static int crc32_final(struct shash_desc *desc, u8 *out) +{ + u32 *crcp = shash_desc_ctx(desc); + + *(__le32 *)out = cpu_to_le32p(crcp); + return 0; +} + +static int crc32_digest(struct shash_desc *desc, const u8 *data, + unsigned int len, u8 *out) +{ + return __crc32_finup(crypto_shash_ctx(desc->tfm), data, len, + out); +} +static struct shash_alg alg = { + .setkey = crc32_setkey, + .init = crc32_init, + .update = crc32_update, + .final = crc32_final, + .finup = crc32_finup, + .digest = crc32_digest, + .descsize = sizeof(u32), + .digestsize = CHKSUM_DIGEST_SIZE, + .base = { + .cra_name = "crc32", + .cra_driver_name = "crc32-table", + .cra_priority = 100, + .cra_blocksize = CHKSUM_BLOCK_SIZE, + .cra_ctxsize = sizeof(u32), + .cra_module = THIS_MODULE, + .cra_init = crc32_cra_init, + } +}; + +static int __init crc32_mod_init(void) +{ + return crypto_register_shash(&alg); +} + +static void __exit crc32_mod_fini(void) +{ + crypto_unregister_shash(&alg); +} + +module_init(crc32_mod_init); +module_exit(crc32_mod_fini); + +MODULE_AUTHOR("Alexander Boyko "); +MODULE_DESCRIPTION("CRC32 calculations wrapper for lib/crc32"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 90df61c376d68903c14f0c5e74254f493f8861a2 Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Sat, 19 Jan 2013 13:31:36 +0200 Subject: crypto: testmgr - add test vector for fcrypt fcrypt is used only as pcbc(fcrypt), but testmgr does not know this. Use the zero key, zero plaintext pcbc(fcrypt) test vector for testing plain 'fcrypt' to hide "no test for fcrypt" warnings. Signed-off-by: Jussi Kivilinna Acked-by: David S. Miller Signed-off-by: Herbert Xu --- crypto/testmgr.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/crypto/testmgr.c b/crypto/testmgr.c index edf4a081..efd8b20e 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -2268,6 +2268,21 @@ static const struct alg_test_desc alg_test_descs[] = { } } } + }, { + .alg = "ecb(fcrypt)", + .test = alg_test_skcipher, + .suite = { + .cipher = { + .enc = { + .vecs = fcrypt_pcbc_enc_tv_template, + .count = 1 + }, + .dec = { + .vecs = fcrypt_pcbc_dec_tv_template, + .count = 1 + } + } + } }, { .alg = "ecb(khazad)", .test = alg_test_skcipher, -- cgit v1.2.3 From ea0d1aff21b1bd3252424f200c7de510403edfa5 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 22 Jan 2013 12:29:26 +0100 Subject: crypto: use ERR_CAST Replace PTR_ERR followed by ERR_PTR by ERR_CAST, to be more concise. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @@ expression err,x; @@ - err = PTR_ERR(x); if (IS_ERR(x)) - return ERR_PTR(err); + return ERR_CAST(x); // Signed-off-by: Julia Lawall Signed-off-by: Herbert Xu --- crypto/aead.c | 6 ++---- crypto/algapi.c | 4 +--- crypto/authenc.c | 3 +-- crypto/authencesn.c | 3 +-- crypto/blkcipher.c | 6 ++---- crypto/ccm.c | 23 +++++++---------------- crypto/chainiv.c | 3 +-- crypto/ctr.c | 3 +-- crypto/cts.c | 3 +-- crypto/gcm.c | 29 +++++++++-------------------- crypto/seqiv.c | 3 +-- 11 files changed, 27 insertions(+), 59 deletions(-) diff --git a/crypto/aead.c b/crypto/aead.c index 0b8121eb..4d04e12f 100644 --- a/crypto/aead.c +++ b/crypto/aead.c @@ -282,18 +282,16 @@ struct crypto_instance *aead_geniv_alloc(struct crypto_template *tmpl, int err; algt = crypto_get_attr_type(tb); - err = PTR_ERR(algt); if (IS_ERR(algt)) - return ERR_PTR(err); + return ERR_CAST(algt); if ((algt->type ^ (CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_GENIV)) & algt->mask) return ERR_PTR(-EINVAL); name = crypto_attr_alg_name(tb[1]); - err = PTR_ERR(name); if (IS_ERR(name)) - return ERR_PTR(err); + return ERR_CAST(name); inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL); if (!inst) diff --git a/crypto/algapi.c b/crypto/algapi.c index c3b9bfee..08c57c8a 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -749,12 +749,10 @@ struct crypto_alg *crypto_attr_alg2(struct rtattr *rta, u32 type, u32 mask) { const char *name; - int err; name = crypto_attr_alg_name(rta); - err = PTR_ERR(name); if (IS_ERR(name)) - return ERR_PTR(err); + return ERR_CAST(name); return crypto_find_alg(name, frontend, type, mask); } diff --git a/crypto/authenc.c b/crypto/authenc.c index d0583a44..ffce19de 100644 --- a/crypto/authenc.c +++ b/crypto/authenc.c @@ -592,9 +592,8 @@ static struct crypto_instance *crypto_authenc_alloc(struct rtattr **tb) int err; algt = crypto_get_attr_type(tb); - err = PTR_ERR(algt); if (IS_ERR(algt)) - return ERR_PTR(err); + return ERR_CAST(algt); if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask) return ERR_PTR(-EINVAL); diff --git a/crypto/authencesn.c b/crypto/authencesn.c index 136b68b9..ab53762f 100644 --- a/crypto/authencesn.c +++ b/crypto/authencesn.c @@ -715,9 +715,8 @@ static struct crypto_instance *crypto_authenc_esn_alloc(struct rtattr **tb) int err; algt = crypto_get_attr_type(tb); - err = PTR_ERR(algt); if (IS_ERR(algt)) - return ERR_PTR(err); + return ERR_CAST(algt); if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask) return ERR_PTR(-EINVAL); diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c index a8d85a1d..e9e7244d 100644 --- a/crypto/blkcipher.c +++ b/crypto/blkcipher.c @@ -588,18 +588,16 @@ struct crypto_instance *skcipher_geniv_alloc(struct crypto_template *tmpl, int err; algt = crypto_get_attr_type(tb); - err = PTR_ERR(algt); if (IS_ERR(algt)) - return ERR_PTR(err); + 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]); - err = PTR_ERR(name); if (IS_ERR(name)) - return ERR_PTR(err); + return ERR_CAST(name); inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL); if (!inst) diff --git a/crypto/ccm.c b/crypto/ccm.c index 32fe1bb5..499c9171 100644 --- a/crypto/ccm.c +++ b/crypto/ccm.c @@ -484,18 +484,16 @@ static struct crypto_instance *crypto_ccm_alloc_common(struct rtattr **tb, int err; algt = crypto_get_attr_type(tb); - err = PTR_ERR(algt); if (IS_ERR(algt)) - return ERR_PTR(err); + return ERR_CAST(algt); if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask) return ERR_PTR(-EINVAL); cipher = crypto_alg_mod_lookup(cipher_name, CRYPTO_ALG_TYPE_CIPHER, CRYPTO_ALG_TYPE_MASK); - err = PTR_ERR(cipher); if (IS_ERR(cipher)) - return ERR_PTR(err); + return ERR_CAST(cipher); err = -EINVAL; if (cipher->cra_blocksize != 16) @@ -573,15 +571,13 @@ out_put_cipher: static struct crypto_instance *crypto_ccm_alloc(struct rtattr **tb) { - int err; const char *cipher_name; char ctr_name[CRYPTO_MAX_ALG_NAME]; char full_name[CRYPTO_MAX_ALG_NAME]; cipher_name = crypto_attr_alg_name(tb[1]); - err = PTR_ERR(cipher_name); if (IS_ERR(cipher_name)) - return ERR_PTR(err); + return ERR_CAST(cipher_name); if (snprintf(ctr_name, CRYPTO_MAX_ALG_NAME, "ctr(%s)", cipher_name) >= CRYPTO_MAX_ALG_NAME) @@ -612,20 +608,17 @@ static struct crypto_template crypto_ccm_tmpl = { static struct crypto_instance *crypto_ccm_base_alloc(struct rtattr **tb) { - int err; const char *ctr_name; const char *cipher_name; char full_name[CRYPTO_MAX_ALG_NAME]; ctr_name = crypto_attr_alg_name(tb[1]); - err = PTR_ERR(ctr_name); if (IS_ERR(ctr_name)) - return ERR_PTR(err); + return ERR_CAST(ctr_name); cipher_name = crypto_attr_alg_name(tb[2]); - err = PTR_ERR(cipher_name); if (IS_ERR(cipher_name)) - return ERR_PTR(err); + return ERR_CAST(cipher_name); if (snprintf(full_name, CRYPTO_MAX_ALG_NAME, "ccm_base(%s,%s)", ctr_name, cipher_name) >= CRYPTO_MAX_ALG_NAME) @@ -760,17 +753,15 @@ static struct crypto_instance *crypto_rfc4309_alloc(struct rtattr **tb) int err; algt = crypto_get_attr_type(tb); - err = PTR_ERR(algt); if (IS_ERR(algt)) - return ERR_PTR(err); + return ERR_CAST(algt); if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask) return ERR_PTR(-EINVAL); ccm_name = crypto_attr_alg_name(tb[1]); - err = PTR_ERR(ccm_name); if (IS_ERR(ccm_name)) - return ERR_PTR(err); + return ERR_CAST(ccm_name); inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL); if (!inst) diff --git a/crypto/chainiv.c b/crypto/chainiv.c index ba200b07..834d8dd3 100644 --- a/crypto/chainiv.c +++ b/crypto/chainiv.c @@ -291,9 +291,8 @@ static struct crypto_instance *chainiv_alloc(struct rtattr **tb) int err; algt = crypto_get_attr_type(tb); - err = PTR_ERR(algt); if (IS_ERR(algt)) - return ERR_PTR(err); + return ERR_CAST(algt); err = crypto_get_default_rng(); if (err) diff --git a/crypto/ctr.c b/crypto/ctr.c index 4ca7222c..095dcb66 100644 --- a/crypto/ctr.c +++ b/crypto/ctr.c @@ -334,9 +334,8 @@ static struct crypto_instance *crypto_rfc3686_alloc(struct rtattr **tb) alg = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_BLKCIPHER, CRYPTO_ALG_TYPE_MASK); - err = PTR_ERR(alg); if (IS_ERR(alg)) - return ERR_PTR(err); + return ERR_CAST(alg); /* We only support 16-byte blocks. */ err = -EINVAL; diff --git a/crypto/cts.c b/crypto/cts.c index ccf9c5de..042223f8 100644 --- a/crypto/cts.c +++ b/crypto/cts.c @@ -282,9 +282,8 @@ static struct crypto_instance *crypto_cts_alloc(struct rtattr **tb) alg = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_BLKCIPHER, CRYPTO_ALG_TYPE_MASK); - err = PTR_ERR(alg); if (IS_ERR(alg)) - return ERR_PTR(err); + return ERR_CAST(alg); inst = ERR_PTR(-EINVAL); if (!is_power_of_2(alg->cra_blocksize)) diff --git a/crypto/gcm.c b/crypto/gcm.c index 1a252639..137ad1ec 100644 --- a/crypto/gcm.c +++ b/crypto/gcm.c @@ -701,9 +701,8 @@ static struct crypto_instance *crypto_gcm_alloc_common(struct rtattr **tb, int err; algt = crypto_get_attr_type(tb); - err = PTR_ERR(algt); if (IS_ERR(algt)) - return ERR_PTR(err); + return ERR_CAST(algt); if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask) return ERR_PTR(-EINVAL); @@ -711,9 +710,8 @@ static struct crypto_instance *crypto_gcm_alloc_common(struct rtattr **tb, ghash_alg = crypto_find_alg(ghash_name, &crypto_ahash_type, CRYPTO_ALG_TYPE_HASH, CRYPTO_ALG_TYPE_AHASH_MASK); - err = PTR_ERR(ghash_alg); if (IS_ERR(ghash_alg)) - return ERR_PTR(err); + return ERR_CAST(ghash_alg); err = -ENOMEM; inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL); @@ -787,15 +785,13 @@ out_put_ghash: static struct crypto_instance *crypto_gcm_alloc(struct rtattr **tb) { - int err; const char *cipher_name; char ctr_name[CRYPTO_MAX_ALG_NAME]; char full_name[CRYPTO_MAX_ALG_NAME]; cipher_name = crypto_attr_alg_name(tb[1]); - err = PTR_ERR(cipher_name); if (IS_ERR(cipher_name)) - return ERR_PTR(err); + return ERR_CAST(cipher_name); if (snprintf(ctr_name, CRYPTO_MAX_ALG_NAME, "ctr(%s)", cipher_name) >= CRYPTO_MAX_ALG_NAME) @@ -826,20 +822,17 @@ static struct crypto_template crypto_gcm_tmpl = { static struct crypto_instance *crypto_gcm_base_alloc(struct rtattr **tb) { - int err; const char *ctr_name; const char *ghash_name; char full_name[CRYPTO_MAX_ALG_NAME]; ctr_name = crypto_attr_alg_name(tb[1]); - err = PTR_ERR(ctr_name); if (IS_ERR(ctr_name)) - return ERR_PTR(err); + return ERR_CAST(ctr_name); ghash_name = crypto_attr_alg_name(tb[2]); - err = PTR_ERR(ghash_name); if (IS_ERR(ghash_name)) - return ERR_PTR(err); + return ERR_CAST(ghash_name); if (snprintf(full_name, CRYPTO_MAX_ALG_NAME, "gcm_base(%s,%s)", ctr_name, ghash_name) >= CRYPTO_MAX_ALG_NAME) @@ -971,17 +964,15 @@ static struct crypto_instance *crypto_rfc4106_alloc(struct rtattr **tb) int err; algt = crypto_get_attr_type(tb); - err = PTR_ERR(algt); if (IS_ERR(algt)) - return ERR_PTR(err); + return ERR_CAST(algt); if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask) return ERR_PTR(-EINVAL); ccm_name = crypto_attr_alg_name(tb[1]); - err = PTR_ERR(ccm_name); if (IS_ERR(ccm_name)) - return ERR_PTR(err); + return ERR_CAST(ccm_name); inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL); if (!inst) @@ -1222,17 +1213,15 @@ static struct crypto_instance *crypto_rfc4543_alloc(struct rtattr **tb) int err; algt = crypto_get_attr_type(tb); - err = PTR_ERR(algt); if (IS_ERR(algt)) - return ERR_PTR(err); + return ERR_CAST(algt); if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask) return ERR_PTR(-EINVAL); ccm_name = crypto_attr_alg_name(tb[1]); - err = PTR_ERR(ccm_name); if (IS_ERR(ccm_name)) - return ERR_PTR(err); + return ERR_CAST(ccm_name); inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL); if (!inst) diff --git a/crypto/seqiv.c b/crypto/seqiv.c index 4c449122..f2cba4ed 100644 --- a/crypto/seqiv.c +++ b/crypto/seqiv.c @@ -305,9 +305,8 @@ static struct crypto_instance *seqiv_alloc(struct rtattr **tb) int err; algt = crypto_get_attr_type(tb); - err = PTR_ERR(algt); if (IS_ERR(algt)) - return ERR_PTR(err); + return ERR_CAST(algt); err = crypto_get_default_rng(); if (err) -- cgit v1.2.3 From f9db44b2ad38f1e6f9ff88359da550b5ec0e5d74 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Tue, 5 Feb 2013 18:19:13 +0100 Subject: crypto: user - fix info leaks in report API Three errors resulting in kernel memory disclosure: 1/ The structures used for the netlink based crypto algorithm report API are located on the stack. As snprintf() does not fill the remainder of the buffer with null bytes, those stack bytes will be disclosed to users of the API. Switch to strncpy() to fix this. 2/ crypto_report_one() does not initialize all field of struct crypto_user_alg. Fix this to fix the heap info leak. 3/ For the module name we should copy only as many bytes as module_name() returns -- not as much as the destination buffer could hold. But the current code does not and therefore copies random data from behind the end of the module name, as the module name is always shorter than CRYPTO_MAX_ALG_NAME. Also switch to use strncpy() to copy the algorithm's name and driver_name. They are strings, after all. Signed-off-by: Mathias Krause Cc: Steffen Klassert Signed-off-by: Herbert Xu --- crypto/ablkcipher.c | 12 ++++++------ crypto/aead.c | 9 ++++----- crypto/ahash.c | 2 +- crypto/blkcipher.c | 6 +++--- crypto/crypto_user.c | 22 +++++++++++----------- crypto/pcompress.c | 3 +-- crypto/rng.c | 2 +- crypto/shash.c | 3 ++- 8 files changed, 29 insertions(+), 30 deletions(-) diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c index 533de955..7d4a8d28 100644 --- a/crypto/ablkcipher.c +++ b/crypto/ablkcipher.c @@ -388,9 +388,9 @@ static int crypto_ablkcipher_report(struct sk_buff *skb, struct crypto_alg *alg) { struct crypto_report_blkcipher rblkcipher; - snprintf(rblkcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "ablkcipher"); - snprintf(rblkcipher.geniv, CRYPTO_MAX_ALG_NAME, "%s", - alg->cra_ablkcipher.geniv ?: ""); + strncpy(rblkcipher.type, "ablkcipher", sizeof(rblkcipher.type)); + strncpy(rblkcipher.geniv, alg->cra_ablkcipher.geniv ?: "", + sizeof(rblkcipher.geniv)); rblkcipher.blocksize = alg->cra_blocksize; rblkcipher.min_keysize = alg->cra_ablkcipher.min_keysize; @@ -469,9 +469,9 @@ static int crypto_givcipher_report(struct sk_buff *skb, struct crypto_alg *alg) { struct crypto_report_blkcipher rblkcipher; - snprintf(rblkcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "givcipher"); - snprintf(rblkcipher.geniv, CRYPTO_MAX_ALG_NAME, "%s", - alg->cra_ablkcipher.geniv ?: ""); + strncpy(rblkcipher.type, "givcipher", sizeof(rblkcipher.type)); + strncpy(rblkcipher.geniv, alg->cra_ablkcipher.geniv ?: "", + sizeof(rblkcipher.geniv)); rblkcipher.blocksize = alg->cra_blocksize; rblkcipher.min_keysize = alg->cra_ablkcipher.min_keysize; diff --git a/crypto/aead.c b/crypto/aead.c index 4d04e12f..547491e3 100644 --- a/crypto/aead.c +++ b/crypto/aead.c @@ -117,9 +117,8 @@ static int crypto_aead_report(struct sk_buff *skb, struct crypto_alg *alg) struct crypto_report_aead raead; struct aead_alg *aead = &alg->cra_aead; - snprintf(raead.type, CRYPTO_MAX_ALG_NAME, "%s", "aead"); - snprintf(raead.geniv, CRYPTO_MAX_ALG_NAME, "%s", - aead->geniv ?: ""); + strncpy(raead.type, "aead", sizeof(raead.type)); + strncpy(raead.geniv, aead->geniv ?: "", sizeof(raead.geniv)); raead.blocksize = alg->cra_blocksize; raead.maxauthsize = aead->maxauthsize; @@ -203,8 +202,8 @@ static int crypto_nivaead_report(struct sk_buff *skb, struct crypto_alg *alg) struct crypto_report_aead raead; struct aead_alg *aead = &alg->cra_aead; - snprintf(raead.type, CRYPTO_MAX_ALG_NAME, "%s", "nivaead"); - snprintf(raead.geniv, CRYPTO_MAX_ALG_NAME, "%s", aead->geniv); + strncpy(raead.type, "nivaead", sizeof(raead.type)); + strncpy(raead.geniv, aead->geniv, sizeof(raead.geniv)); raead.blocksize = alg->cra_blocksize; raead.maxauthsize = aead->maxauthsize; diff --git a/crypto/ahash.c b/crypto/ahash.c index 3887856c..793a27f2 100644 --- a/crypto/ahash.c +++ b/crypto/ahash.c @@ -404,7 +404,7 @@ static int crypto_ahash_report(struct sk_buff *skb, struct crypto_alg *alg) { struct crypto_report_hash rhash; - snprintf(rhash.type, CRYPTO_MAX_ALG_NAME, "%s", "ahash"); + strncpy(rhash.type, "ahash", sizeof(rhash.type)); rhash.blocksize = alg->cra_blocksize; rhash.digestsize = __crypto_hash_alg_common(alg)->digestsize; diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c index e9e7244d..a79e7e9a 100644 --- a/crypto/blkcipher.c +++ b/crypto/blkcipher.c @@ -499,9 +499,9 @@ static int crypto_blkcipher_report(struct sk_buff *skb, struct crypto_alg *alg) { struct crypto_report_blkcipher rblkcipher; - snprintf(rblkcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "blkcipher"); - snprintf(rblkcipher.geniv, CRYPTO_MAX_ALG_NAME, "%s", - alg->cra_blkcipher.geniv ?: ""); + strncpy(rblkcipher.type, "blkcipher", sizeof(rblkcipher.type)); + strncpy(rblkcipher.geniv, alg->cra_blkcipher.geniv ?: "", + sizeof(rblkcipher.geniv)); rblkcipher.blocksize = alg->cra_blocksize; rblkcipher.min_keysize = alg->cra_blkcipher.min_keysize; diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c index 35d700a9..f6d9baf7 100644 --- a/crypto/crypto_user.c +++ b/crypto/crypto_user.c @@ -75,7 +75,7 @@ static int crypto_report_cipher(struct sk_buff *skb, struct crypto_alg *alg) { struct crypto_report_cipher rcipher; - snprintf(rcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "cipher"); + strncpy(rcipher.type, "cipher", sizeof(rcipher.type)); rcipher.blocksize = alg->cra_blocksize; rcipher.min_keysize = alg->cra_cipher.cia_min_keysize; @@ -94,8 +94,7 @@ static int crypto_report_comp(struct sk_buff *skb, struct crypto_alg *alg) { struct crypto_report_comp rcomp; - snprintf(rcomp.type, CRYPTO_MAX_ALG_NAME, "%s", "compression"); - + strncpy(rcomp.type, "compression", sizeof(rcomp.type)); if (nla_put(skb, CRYPTOCFGA_REPORT_COMPRESS, sizeof(struct crypto_report_comp), &rcomp)) goto nla_put_failure; @@ -108,12 +107,14 @@ nla_put_failure: static int crypto_report_one(struct crypto_alg *alg, struct crypto_user_alg *ualg, struct sk_buff *skb) { - memcpy(&ualg->cru_name, &alg->cra_name, sizeof(ualg->cru_name)); - memcpy(&ualg->cru_driver_name, &alg->cra_driver_name, - sizeof(ualg->cru_driver_name)); - memcpy(&ualg->cru_module_name, module_name(alg->cra_module), - CRYPTO_MAX_ALG_NAME); - + strncpy(ualg->cru_name, alg->cra_name, sizeof(ualg->cru_name)); + strncpy(ualg->cru_driver_name, alg->cra_driver_name, + sizeof(ualg->cru_driver_name)); + strncpy(ualg->cru_module_name, module_name(alg->cra_module), + sizeof(ualg->cru_module_name)); + + ualg->cru_type = 0; + ualg->cru_mask = 0; ualg->cru_flags = alg->cra_flags; ualg->cru_refcnt = atomic_read(&alg->cra_refcnt); @@ -122,8 +123,7 @@ static int crypto_report_one(struct crypto_alg *alg, if (alg->cra_flags & CRYPTO_ALG_LARVAL) { struct crypto_report_larval rl; - snprintf(rl.type, CRYPTO_MAX_ALG_NAME, "%s", "larval"); - + strncpy(rl.type, "larval", sizeof(rl.type)); if (nla_put(skb, CRYPTOCFGA_REPORT_LARVAL, sizeof(struct crypto_report_larval), &rl)) goto nla_put_failure; diff --git a/crypto/pcompress.c b/crypto/pcompress.c index 04e083ff..7140fe70 100644 --- a/crypto/pcompress.c +++ b/crypto/pcompress.c @@ -53,8 +53,7 @@ static int crypto_pcomp_report(struct sk_buff *skb, struct crypto_alg *alg) { struct crypto_report_comp rpcomp; - snprintf(rpcomp.type, CRYPTO_MAX_ALG_NAME, "%s", "pcomp"); - + strncpy(rpcomp.type, "pcomp", sizeof(rpcomp.type)); if (nla_put(skb, CRYPTOCFGA_REPORT_COMPRESS, sizeof(struct crypto_report_comp), &rpcomp)) goto nla_put_failure; diff --git a/crypto/rng.c b/crypto/rng.c index f3b7894d..e0a25c24 100644 --- a/crypto/rng.c +++ b/crypto/rng.c @@ -65,7 +65,7 @@ static int crypto_rng_report(struct sk_buff *skb, struct crypto_alg *alg) { struct crypto_report_rng rrng; - snprintf(rrng.type, CRYPTO_MAX_ALG_NAME, "%s", "rng"); + strncpy(rrng.type, "rng", sizeof(rrng.type)); rrng.seedsize = alg->cra_rng.seedsize; diff --git a/crypto/shash.c b/crypto/shash.c index f426330f..929058a6 100644 --- a/crypto/shash.c +++ b/crypto/shash.c @@ -530,7 +530,8 @@ static int crypto_shash_report(struct sk_buff *skb, struct crypto_alg *alg) struct crypto_report_hash rhash; struct shash_alg *salg = __crypto_shash_alg(alg); - snprintf(rhash.type, CRYPTO_MAX_ALG_NAME, "%s", "shash"); + strncpy(rhash.type, "shash", sizeof(rhash.type)); + rhash.blocksize = alg->cra_blocksize; rhash.digestsize = salg->digestsize; -- cgit v1.2.3 From 50540e6eba0e59c3a5e4551b9aa7868df4f7bd8d Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Tue, 5 Feb 2013 18:19:14 +0100 Subject: crypto: user - fix empty string test in report API The current test for empty strings fails because it is testing the address of a field, not a pointer. So the test will always be true. Test the first character in the string to not be null instead. Signed-off-by: Mathias Krause Cc: Steffen Klassert Signed-off-by: Herbert Xu --- crypto/crypto_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c index f6d9baf7..423a2670 100644 --- a/crypto/crypto_user.c +++ b/crypto/crypto_user.c @@ -196,7 +196,7 @@ static int crypto_report(struct sk_buff *in_skb, struct nlmsghdr *in_nlh, struct crypto_dump_info info; int err; - if (!p->cru_driver_name) + if (!p->cru_driver_name[0]) return -EINVAL; alg = crypto_alg_match(p, 1); -- cgit v1.2.3 From 25633c1e43f8d2a9343a14bd019a05fad5615af5 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Tue, 5 Feb 2013 18:19:15 +0100 Subject: crypto: user - ensure user supplied strings are nul-terminated To avoid misuse, ensure cru_name and cru_driver_name are always nul-terminated strings. Signed-off-by: Mathias Krause Signed-off-by: Herbert Xu --- crypto/crypto_user.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c index 423a2670..dfd511fb 100644 --- a/crypto/crypto_user.c +++ b/crypto/crypto_user.c @@ -30,6 +30,8 @@ #include "internal.h" +#define null_terminated(x) (strnlen(x, sizeof(x)) < sizeof(x)) + static DEFINE_MUTEX(crypto_cfg_mutex); /* The crypto netlink socket */ @@ -196,6 +198,9 @@ static int crypto_report(struct sk_buff *in_skb, struct nlmsghdr *in_nlh, struct crypto_dump_info info; int err; + if (!null_terminated(p->cru_name) || !null_terminated(p->cru_driver_name)) + return -EINVAL; + if (!p->cru_driver_name[0]) return -EINVAL; @@ -260,6 +265,9 @@ static int crypto_update_alg(struct sk_buff *skb, struct nlmsghdr *nlh, struct nlattr *priority = attrs[CRYPTOCFGA_PRIORITY_VAL]; LIST_HEAD(list); + if (!null_terminated(p->cru_name) || !null_terminated(p->cru_driver_name)) + return -EINVAL; + if (priority && !strlen(p->cru_driver_name)) return -EINVAL; @@ -287,6 +295,9 @@ static int crypto_del_alg(struct sk_buff *skb, struct nlmsghdr *nlh, struct crypto_alg *alg; struct crypto_user_alg *p = nlmsg_data(nlh); + if (!null_terminated(p->cru_name) || !null_terminated(p->cru_driver_name)) + return -EINVAL; + alg = crypto_alg_match(p, 1); if (!alg) return -ENOENT; @@ -368,6 +379,9 @@ static int crypto_add_alg(struct sk_buff *skb, struct nlmsghdr *nlh, struct crypto_user_alg *p = nlmsg_data(nlh); struct nlattr *priority = attrs[CRYPTOCFGA_PRIORITY_VAL]; + if (!null_terminated(p->cru_name) || !null_terminated(p->cru_driver_name)) + return -EINVAL; + if (strlen(p->cru_driver_name)) exact = 1; -- cgit v1.2.3