From 4f0fc1600edbdb3612b931aa5076ca984f7ee8fe Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Mon, 21 Aug 2017 13:51:28 +0300 Subject: crypto: sm3 - add OSCCA SM3 secure hash Add OSCCA SM3 secure hash (OSCCA GM/T 0004-2012 SM3) generic hash transformation. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Herbert Xu --- crypto/Kconfig | 11 +++ crypto/Makefile | 1 + crypto/sm3_generic.c | 210 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 222 insertions(+) create mode 100644 crypto/sm3_generic.c (limited to 'crypto') diff --git a/crypto/Kconfig b/crypto/Kconfig index 0a121f9ddf8e..97fb7360207b 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -859,6 +859,17 @@ config CRYPTO_SHA3 References: http://keccak.noekeon.org/ +config CRYPTO_SM3 + tristate "SM3 digest algorithm" + select CRYPTO_HASH + help + SM3 secure hash function as defined by OSCCA GM/T 0004-2012 SM3). + It is part of the Chinese Commercial Cryptography suite. + + References: + http://www.oscca.gov.cn/UpFile/20101222141857786.pdf + https://datatracker.ietf.org/doc/html/draft-shen-sm3-hash + config CRYPTO_TGR192 tristate "Tiger digest algorithms" select CRYPTO_HASH diff --git a/crypto/Makefile b/crypto/Makefile index d41f0331b085..723b0b41dab9 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -70,6 +70,7 @@ obj-$(CONFIG_CRYPTO_SHA1) += sha1_generic.o obj-$(CONFIG_CRYPTO_SHA256) += sha256_generic.o obj-$(CONFIG_CRYPTO_SHA512) += sha512_generic.o obj-$(CONFIG_CRYPTO_SHA3) += sha3_generic.o +obj-$(CONFIG_CRYPTO_SM3) += sm3_generic.o obj-$(CONFIG_CRYPTO_WP512) += wp512.o CFLAGS_wp512.o := $(call cc-option,-fno-schedule-insns) # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79149 obj-$(CONFIG_CRYPTO_TGR192) += tgr192.o diff --git a/crypto/sm3_generic.c b/crypto/sm3_generic.c new file mode 100644 index 000000000000..9e823d99f095 --- /dev/null +++ b/crypto/sm3_generic.c @@ -0,0 +1,210 @@ +/* + * SM3 secure hash, as specified by OSCCA GM/T 0004-2012 SM3 and + * described at https://tools.ietf.org/html/draft-shen-sm3-hash-01 + * + * Copyright (C) 2017 ARM Limited or its affiliates. + * Written by Gilad Ben-Yossef + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 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 for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +const u8 sm3_zero_message_hash[SM3_DIGEST_SIZE] = { + 0x1A, 0xB2, 0x1D, 0x83, 0x55, 0xCF, 0xA1, 0x7F, + 0x8e, 0x61, 0x19, 0x48, 0x31, 0xE8, 0x1A, 0x8F, + 0x22, 0xBE, 0xC8, 0xC7, 0x28, 0xFE, 0xFB, 0x74, + 0x7E, 0xD0, 0x35, 0xEB, 0x50, 0x82, 0xAA, 0x2B +}; +EXPORT_SYMBOL_GPL(sm3_zero_message_hash); + +static inline u32 p0(u32 x) +{ + return x ^ rol32(x, 9) ^ rol32(x, 17); +} + +static inline u32 p1(u32 x) +{ + return x ^ rol32(x, 15) ^ rol32(x, 23); +} + +static inline u32 ff(unsigned int n, u32 a, u32 b, u32 c) +{ + return (n < 16) ? (a ^ b ^ c) : ((a & b) | (a & c) | (b & c)); +} + +static inline u32 gg(unsigned int n, u32 e, u32 f, u32 g) +{ + return (n < 16) ? (e ^ f ^ g) : ((e & f) | ((~e) & g)); +} + +static inline u32 t(unsigned int n) +{ + return (n < 16) ? SM3_T1 : SM3_T2; +} + +static void sm3_expand(u32 *t, u32 *w, u32 *wt) +{ + int i; + unsigned int tmp; + + /* load the input */ + for (i = 0; i <= 15; i++) + w[i] = get_unaligned_be32((__u32 *)t + i); + + for (i = 16; i <= 67; i++) { + tmp = w[i - 16] ^ w[i - 9] ^ rol32(w[i - 3], 15); + w[i] = p1(tmp) ^ (rol32(w[i - 13], 7)) ^ w[i - 6]; + } + + for (i = 0; i <= 63; i++) + wt[i] = w[i] ^ w[i + 4]; +} + +static void sm3_compress(u32 *w, u32 *wt, u32 *m) +{ + u32 ss1; + u32 ss2; + u32 tt1; + u32 tt2; + u32 a, b, c, d, e, f, g, h; + int i; + + a = m[0]; + b = m[1]; + c = m[2]; + d = m[3]; + e = m[4]; + f = m[5]; + g = m[6]; + h = m[7]; + + for (i = 0; i <= 63; i++) { + + ss1 = rol32((rol32(a, 12) + e + rol32(t(i), i)), 7); + + ss2 = ss1 ^ rol32(a, 12); + + tt1 = ff(i, a, b, c) + d + ss2 + *wt; + wt++; + + tt2 = gg(i, e, f, g) + h + ss1 + *w; + w++; + + d = c; + c = rol32(b, 9); + b = a; + a = tt1; + h = g; + g = rol32(f, 19); + f = e; + e = p0(tt2); + } + + m[0] = a ^ m[0]; + m[1] = b ^ m[1]; + m[2] = c ^ m[2]; + m[3] = d ^ m[3]; + m[4] = e ^ m[4]; + m[5] = f ^ m[5]; + m[6] = g ^ m[6]; + m[7] = h ^ m[7]; + + a = b = c = d = e = f = g = h = ss1 = ss2 = tt1 = tt2 = 0; +} + +static void sm3_transform(struct sm3_state *sst, u8 const *src) +{ + unsigned int w[68]; + unsigned int wt[64]; + + sm3_expand((u32 *)src, w, wt); + sm3_compress(w, wt, sst->state); + + memzero_explicit(w, sizeof(w)); + memzero_explicit(wt, sizeof(wt)); +} + +static void sm3_generic_block_fn(struct sm3_state *sst, u8 const *src, + int blocks) +{ + while (blocks--) { + sm3_transform(sst, src); + src += SM3_BLOCK_SIZE; + } +} + +int crypto_sm3_update(struct shash_desc *desc, const u8 *data, + unsigned int len) +{ + return sm3_base_do_update(desc, data, len, sm3_generic_block_fn); +} +EXPORT_SYMBOL(crypto_sm3_update); + +static int sm3_final(struct shash_desc *desc, u8 *out) +{ + sm3_base_do_finalize(desc, sm3_generic_block_fn); + return sm3_base_finish(desc, out); +} + +int crypto_sm3_finup(struct shash_desc *desc, const u8 *data, + unsigned int len, u8 *hash) +{ + sm3_base_do_update(desc, data, len, sm3_generic_block_fn); + return sm3_final(desc, hash); +} +EXPORT_SYMBOL(crypto_sm3_finup); + +static struct shash_alg sm3_alg = { + .digestsize = SM3_DIGEST_SIZE, + .init = sm3_base_init, + .update = crypto_sm3_update, + .final = sm3_final, + .finup = crypto_sm3_finup, + .descsize = sizeof(struct sm3_state), + .base = { + .cra_name = "sm3", + .cra_driver_name = "sm3-generic", + .cra_flags = CRYPTO_ALG_TYPE_SHASH, + .cra_blocksize = SM3_BLOCK_SIZE, + .cra_module = THIS_MODULE, + } +}; + +static int __init sm3_generic_mod_init(void) +{ + return crypto_register_shash(&sm3_alg); +} + +static void __exit sm3_generic_mod_fini(void) +{ + crypto_unregister_shash(&sm3_alg); +} + +module_init(sm3_generic_mod_init); +module_exit(sm3_generic_mod_fini); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("SM3 Secure Hash Algorithm"); + +MODULE_ALIAS_CRYPTO("sm3"); +MODULE_ALIAS_CRYPTO("sm3-generic"); -- cgit From b7e2753040a2fef0f748c615121577da3f846781 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Mon, 21 Aug 2017 13:51:29 +0300 Subject: crypto: sm3 - add SM3 test vectors Add testmgr and tcrypt tests and vectors for SM3 secure hash. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Herbert Xu --- crypto/tcrypt.c | 14 +++++++++++- crypto/testmgr.c | 6 +++++ crypto/testmgr.h | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) (limited to 'crypto') diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index 0022a18d36ee..a309c819be70 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c @@ -70,7 +70,7 @@ static int mode; static char *tvmem[TVMEMSIZE]; static char *check[] = { - "des", "md5", "des3_ede", "rot13", "sha1", "sha224", "sha256", + "des", "md5", "des3_ede", "rot13", "sha1", "sha224", "sha256", "sm3", "blowfish", "twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6", "arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea", "khazad", "wp512", "wp384", "wp256", "tnepres", "xeta", "fcrypt", @@ -1269,6 +1269,10 @@ static int do_test(const char *alg, u32 type, u32 mask, int m) ret += tcrypt_test("sha3-512"); break; + case 52: + ret += tcrypt_test("sm3"); + break; + case 100: ret += tcrypt_test("hmac(md5)"); break; @@ -1712,6 +1716,10 @@ static int do_test(const char *alg, u32 type, u32 mask, int m) test_hash_speed("sha3-512", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; + case 326: + test_hash_speed("sm3", sec, generic_hash_speed_template); + if (mode > 300 && mode < 400) break; + case 399: break; @@ -1820,6 +1828,10 @@ static int do_test(const char *alg, u32 type, u32 mask, int m) test_mb_ahash_speed("sha512", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; + case 425: + test_mb_ahash_speed("sm3", sec, generic_hash_speed_template); + if (mode > 400 && mode < 500) break; + case 499: break; diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 7125ba3880af..baf96cecaf49 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -3499,6 +3499,12 @@ static const struct alg_test_desc alg_test_descs[] = { .suite = { .hash = __VECS(sha512_tv_template) } + }, { + .alg = "sm3", + .test = alg_test_hash, + .suite = { + .hash = __VECS(sm3_tv_template) + } }, { .alg = "tgr128", .test = alg_test_hash, diff --git a/crypto/testmgr.h b/crypto/testmgr.h index d54971d2d1c8..a714b6293959 100644 --- a/crypto/testmgr.h +++ b/crypto/testmgr.h @@ -1497,6 +1497,73 @@ static const struct hash_testvec crct10dif_tv_template[] = { } }; +/* Example vectors below taken from + * http://www.oscca.gov.cn/UpFile/20101222141857786.pdf + * + * The rest taken from + * https://github.com/adamws/oscca-sm3 + */ +static const struct hash_testvec sm3_tv_template[] = { + { + .plaintext = "", + .psize = 0, + .digest = (u8 *)(u8 []) { + 0x1A, 0xB2, 0x1D, 0x83, 0x55, 0xCF, 0xA1, 0x7F, + 0x8e, 0x61, 0x19, 0x48, 0x31, 0xE8, 0x1A, 0x8F, + 0x22, 0xBE, 0xC8, 0xC7, 0x28, 0xFE, 0xFB, 0x74, + 0x7E, 0xD0, 0x35, 0xEB, 0x50, 0x82, 0xAA, 0x2B } + }, { + .plaintext = "a", + .psize = 1, + .digest = (u8 *)(u8 []) { + 0x62, 0x34, 0x76, 0xAC, 0x18, 0xF6, 0x5A, 0x29, + 0x09, 0xE4, 0x3C, 0x7F, 0xEC, 0x61, 0xB4, 0x9C, + 0x7E, 0x76, 0x4A, 0x91, 0xA1, 0x8C, 0xCB, 0x82, + 0xF1, 0x91, 0x7A, 0x29, 0xC8, 0x6C, 0x5E, 0x88 } + }, { + /* A.1. Example 1 */ + .plaintext = "abc", + .psize = 3, + .digest = (u8 *)(u8 []) { + 0x66, 0xC7, 0xF0, 0xF4, 0x62, 0xEE, 0xED, 0xD9, + 0xD1, 0xF2, 0xD4, 0x6B, 0xDC, 0x10, 0xE4, 0xE2, + 0x41, 0x67, 0xC4, 0x87, 0x5C, 0xF2, 0xF7, 0xA2, + 0x29, 0x7D, 0xA0, 0x2B, 0x8F, 0x4B, 0xA8, 0xE0 } + }, { + .plaintext = "abcdefghijklmnopqrstuvwxyz", + .psize = 26, + .digest = (u8 *)(u8 []) { + 0xB8, 0x0F, 0xE9, 0x7A, 0x4D, 0xA2, 0x4A, 0xFC, + 0x27, 0x75, 0x64, 0xF6, 0x6A, 0x35, 0x9E, 0xF4, + 0x40, 0x46, 0x2A, 0xD2, 0x8D, 0xCC, 0x6D, 0x63, + 0xAD, 0xB2, 0x4D, 0x5C, 0x20, 0xA6, 0x15, 0x95 } + }, { + /* A.1. Example 2 */ + .plaintext = "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdab" + "cdabcdabcdabcdabcd", + .psize = 64, + .digest = (u8 *)(u8 []) { + 0xDE, 0xBE, 0x9F, 0xF9, 0x22, 0x75, 0xB8, 0xA1, + 0x38, 0x60, 0x48, 0x89, 0xC1, 0x8E, 0x5A, 0x4D, + 0x6F, 0xDB, 0x70, 0xE5, 0x38, 0x7E, 0x57, 0x65, + 0x29, 0x3D, 0xCB, 0xA3, 0x9C, 0x0C, 0x57, 0x32 } + }, { + .plaintext = "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd" + "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd" + "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd" + "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd" + "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd" + "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd" + "abcdabcdabcdabcdabcdabcdabcdabcd", + .psize = 256, + .digest = (u8 *)(u8 []) { + 0xB9, 0x65, 0x76, 0x4C, 0x8B, 0xEB, 0xB0, 0x91, + 0xC7, 0x60, 0x2B, 0x74, 0xAF, 0xD3, 0x4E, 0xEF, + 0xB5, 0x31, 0xDC, 0xCB, 0x4E, 0x00, 0x76, 0xD9, + 0xB7, 0xCD, 0x81, 0x31, 0x99, 0xB4, 0x59, 0x71 } + } +}; + /* * SHA1 test vectors from from FIPS PUB 180-1 * Long vector from CAVS 5.0 -- cgit From e0ab7e9c6b92ae8e57de157fa7f419ebd18abb25 Mon Sep 17 00:00:00 2001 From: Corentin LABBE Date: Tue, 22 Aug 2017 10:08:17 +0200 Subject: crypto: gcm - Use GCM IV size constant This patch replace GCM IV size value by their constant name. Signed-off-by: Corentin Labbe Signed-off-by: Herbert Xu --- crypto/gcm.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'crypto') diff --git a/crypto/gcm.c b/crypto/gcm.c index 3841b5eafa7e..80cf6cfe082b 100644 --- a/crypto/gcm.c +++ b/crypto/gcm.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include "internal.h" #include @@ -197,8 +198,8 @@ static void crypto_gcm_init_common(struct aead_request *req) struct scatterlist *sg; memset(pctx->auth_tag, 0, sizeof(pctx->auth_tag)); - memcpy(pctx->iv, req->iv, 12); - memcpy(pctx->iv + 12, &counter, 4); + memcpy(pctx->iv, req->iv, GCM_AES_IV_SIZE); + memcpy(pctx->iv + GCM_AES_IV_SIZE, &counter, 4); sg_init_table(pctx->src, 3); sg_set_buf(pctx->src, pctx->auth_tag, sizeof(pctx->auth_tag)); @@ -695,7 +696,7 @@ static int crypto_gcm_create_common(struct crypto_template *tmpl, inst->alg.base.cra_alignmask = ghash->base.cra_alignmask | ctr->base.cra_alignmask; inst->alg.base.cra_ctxsize = sizeof(struct crypto_gcm_ctx); - inst->alg.ivsize = 12; + inst->alg.ivsize = GCM_AES_IV_SIZE; inst->alg.chunksize = crypto_skcipher_alg_chunksize(ctr); inst->alg.maxauthsize = 16; inst->alg.init = crypto_gcm_init_tfm; @@ -832,20 +833,20 @@ static struct aead_request *crypto_rfc4106_crypt(struct aead_request *req) u8 *iv = PTR_ALIGN((u8 *)(subreq + 1) + crypto_aead_reqsize(child), crypto_aead_alignmask(child) + 1); - scatterwalk_map_and_copy(iv + 12, req->src, 0, req->assoclen - 8, 0); + scatterwalk_map_and_copy(iv + GCM_AES_IV_SIZE, req->src, 0, req->assoclen - 8, 0); memcpy(iv, ctx->nonce, 4); memcpy(iv + 4, req->iv, 8); sg_init_table(rctx->src, 3); - sg_set_buf(rctx->src, iv + 12, req->assoclen - 8); + sg_set_buf(rctx->src, iv + GCM_AES_IV_SIZE, req->assoclen - 8); sg = scatterwalk_ffwd(rctx->src + 1, req->src, req->assoclen); if (sg != rctx->src + 1) sg_chain(rctx->src, 2, sg); if (req->src != req->dst) { sg_init_table(rctx->dst, 3); - sg_set_buf(rctx->dst, iv + 12, req->assoclen - 8); + sg_set_buf(rctx->dst, iv + GCM_AES_IV_SIZE, req->assoclen - 8); sg = scatterwalk_ffwd(rctx->dst + 1, req->dst, req->assoclen); if (sg != rctx->dst + 1) sg_chain(rctx->dst, 2, sg); @@ -957,7 +958,7 @@ static int crypto_rfc4106_create(struct crypto_template *tmpl, err = -EINVAL; /* Underlying IV size must be 12. */ - if (crypto_aead_alg_ivsize(alg) != 12) + if (crypto_aead_alg_ivsize(alg) != GCM_AES_IV_SIZE) goto out_drop_alg; /* Not a stream cipher? */ @@ -980,7 +981,7 @@ static int crypto_rfc4106_create(struct crypto_template *tmpl, inst->alg.base.cra_ctxsize = sizeof(struct crypto_rfc4106_ctx); - inst->alg.ivsize = 8; + inst->alg.ivsize = GCM_RFC4106_IV_SIZE; inst->alg.chunksize = crypto_aead_alg_chunksize(alg); inst->alg.maxauthsize = crypto_aead_alg_maxauthsize(alg); @@ -1134,7 +1135,7 @@ static int crypto_rfc4543_init_tfm(struct crypto_aead *tfm) tfm, sizeof(struct crypto_rfc4543_req_ctx) + ALIGN(crypto_aead_reqsize(aead), crypto_tfm_ctx_alignment()) + - align + 12); + align + GCM_AES_IV_SIZE); return 0; @@ -1199,7 +1200,7 @@ static int crypto_rfc4543_create(struct crypto_template *tmpl, err = -EINVAL; /* Underlying IV size must be 12. */ - if (crypto_aead_alg_ivsize(alg) != 12) + if (crypto_aead_alg_ivsize(alg) != GCM_AES_IV_SIZE) goto out_drop_alg; /* Not a stream cipher? */ @@ -1222,7 +1223,7 @@ static int crypto_rfc4543_create(struct crypto_template *tmpl, inst->alg.base.cra_ctxsize = sizeof(struct crypto_rfc4543_ctx); - inst->alg.ivsize = 8; + inst->alg.ivsize = GCM_RFC4543_IV_SIZE; inst->alg.chunksize = crypto_aead_alg_chunksize(alg); inst->alg.maxauthsize = crypto_aead_alg_maxauthsize(alg); -- cgit From 52872f5288ea38ab9e2bb352a47b71051f7aefcc Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Mon, 28 Aug 2017 22:00:07 +0800 Subject: crypto: drop unnecessary return statements Fix checkpatch.pl warnings: WARNING: void function return statements are not generally useful FILE: crypto/rmd128.c:218: FILE: crypto/rmd160.c:261: FILE: crypto/rmd256.c:233: FILE: crypto/rmd320.c:280: FILE: crypto/tcrypt.c:385: FILE: drivers/crypto/ixp4xx_crypto.c:538: FILE: drivers/crypto/marvell/cesa.c:81: FILE: drivers/crypto/ux500/cryp/cryp_core.c:1755: Signed-off-by: Geliang Tang Signed-off-by: Herbert Xu --- crypto/rmd128.c | 2 -- crypto/rmd160.c | 2 -- crypto/rmd256.c | 2 -- crypto/rmd320.c | 2 -- crypto/tcrypt.c | 1 - 5 files changed, 9 deletions(-) (limited to 'crypto') diff --git a/crypto/rmd128.c b/crypto/rmd128.c index 049486ede938..40e053b97b69 100644 --- a/crypto/rmd128.c +++ b/crypto/rmd128.c @@ -213,8 +213,6 @@ static void rmd128_transform(u32 *state, const __le32 *in) state[2] = state[3] + aa + bbb; state[3] = state[0] + bb + ccc; state[0] = ddd; - - return; } static int rmd128_init(struct shash_desc *desc) diff --git a/crypto/rmd160.c b/crypto/rmd160.c index de585e51d455..5f3e6ea35268 100644 --- a/crypto/rmd160.c +++ b/crypto/rmd160.c @@ -256,8 +256,6 @@ static void rmd160_transform(u32 *state, const __le32 *in) state[3] = state[4] + aa + bbb; state[4] = state[0] + bb + ccc; state[0] = ddd; - - return; } static int rmd160_init(struct shash_desc *desc) diff --git a/crypto/rmd256.c b/crypto/rmd256.c index 4ec02a754e09..f50c025cc962 100644 --- a/crypto/rmd256.c +++ b/crypto/rmd256.c @@ -228,8 +228,6 @@ static void rmd256_transform(u32 *state, const __le32 *in) state[5] += bbb; state[6] += ccc; state[7] += ddd; - - return; } static int rmd256_init(struct shash_desc *desc) diff --git a/crypto/rmd320.c b/crypto/rmd320.c index 770f2cb369f8..e1315e4869e8 100644 --- a/crypto/rmd320.c +++ b/crypto/rmd320.c @@ -275,8 +275,6 @@ static void rmd320_transform(u32 *state, const __le32 *in) state[7] += ccc; state[8] += ddd; state[9] += eee; - - return; } static int rmd320_init(struct shash_desc *desc) diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index a309c819be70..a371c072b62f 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c @@ -381,7 +381,6 @@ out_noaxbuf: testmgr_free_buf(xbuf); out_noxbuf: kfree(iv); - return; } static void test_hash_sg_init(struct scatterlist *sg) -- cgit From e781c17c22fdd390e54b972c010acdc862ac66df Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 14 Sep 2017 19:02:19 +0100 Subject: crypto: algboss - remove redundant setting of len to zero The variable len is set to zero, never read and then later updated to p - name, so clearly the zero'ing of len is redundant and can be removed. Detected by clang scan-build: " warning: Value stored to 'len' is never read" Signed-off-by: Colin Ian King Signed-off-by: Herbert Xu --- crypto/algboss.c | 1 - 1 file changed, 1 deletion(-) (limited to 'crypto') diff --git a/crypto/algboss.c b/crypto/algboss.c index 960d8548171b..5e6df2a087fa 100644 --- a/crypto/algboss.c +++ b/crypto/algboss.c @@ -122,7 +122,6 @@ static int cryptomgr_schedule_probe(struct crypto_larval *larval) int notnum = 0; name = ++p; - len = 0; for (; isalnum(*p) || *p == '-' || *p == '_'; p++) notnum |= !isdigit(*p); -- cgit From 616129cc6e75fb4da6681c16c981fa82dfe5e4c7 Mon Sep 17 00:00:00 2001 From: Christophe Jaillet Date: Sun, 8 Oct 2017 11:39:49 +0200 Subject: crypto: lrw - Fix an error handling path in 'create()' All error handling paths 'goto err_drop_spawn' except this one. In order to avoid some resources leak, we should do it as well here. Fixes: 700cb3f5fe75 ("crypto: lrw - Convert to skcipher") Signed-off-by: Christophe JAILLET Signed-off-by: Herbert Xu --- crypto/lrw.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'crypto') diff --git a/crypto/lrw.c b/crypto/lrw.c index a8bfae4451bf..eb681e9fe574 100644 --- a/crypto/lrw.c +++ b/crypto/lrw.c @@ -610,8 +610,10 @@ static int create(struct crypto_template *tmpl, struct rtattr **tb) ecb_name[len - 1] = 0; if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME, - "lrw(%s)", ecb_name) >= CRYPTO_MAX_ALG_NAME) - return -ENAMETOOLONG; + "lrw(%s)", ecb_name) >= CRYPTO_MAX_ALG_NAME) { + err = -ENAMETOOLONG; + goto err_drop_spawn; + } } inst->alg.base.cra_flags = alg->base.cra_flags & CRYPTO_ALG_ASYNC; -- cgit From d38efad2bf1c27fcb375dee9ac8c5c99e02ab38c Mon Sep 17 00:00:00 2001 From: Christophe Jaillet Date: Sun, 8 Oct 2017 11:39:50 +0200 Subject: crypto: lrw - Check for incorrect cipher name If the cipher name does not start with 'ecb(' we should bail out, as done in the 'create()' function in 'crypto/xts.c'. Fixes: 700cb3f5fe75 ("crypto: lrw - Convert to skcipher") Signed-off-by: Christophe JAILLET Signed-off-by: Herbert Xu --- crypto/lrw.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'crypto') diff --git a/crypto/lrw.c b/crypto/lrw.c index eb681e9fe574..92df312b8c6e 100644 --- a/crypto/lrw.c +++ b/crypto/lrw.c @@ -614,7 +614,8 @@ static int create(struct crypto_template *tmpl, struct rtattr **tb) err = -ENAMETOOLONG; goto err_drop_spawn; } - } + } else + goto err_drop_spawn; inst->alg.base.cra_flags = alg->base.cra_flags & CRYPTO_ALG_ASYNC; inst->alg.base.cra_priority = alg->base.cra_priority; -- cgit From 6e97e08d4311d2413df0e891a10301bf4258fe3e Mon Sep 17 00:00:00 2001 From: Tudor-Dan Ambarus Date: Fri, 29 Sep 2017 12:13:08 +0300 Subject: crypto: ecdh - return unsigned value for crypto_ecdh_key_len() ECDH_KPP_SECRET_MIN_SIZE and params->key_size are both returning unsigned values. Signed-off-by: Tudor Ambarus Signed-off-by: Herbert Xu --- crypto/ecdh_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crypto') diff --git a/crypto/ecdh_helper.c b/crypto/ecdh_helper.c index f05bea5fd257..d3af8e8b0b5e 100644 --- a/crypto/ecdh_helper.c +++ b/crypto/ecdh_helper.c @@ -28,7 +28,7 @@ static inline const u8 *ecdh_unpack_data(void *dst, const void *src, size_t sz) return src + sz; } -int crypto_ecdh_key_len(const struct ecdh *params) +unsigned int crypto_ecdh_key_len(const struct ecdh *params) { return ECDH_KPP_SECRET_MIN_SIZE + params->key_size; } -- cgit From cb195b362537ca97ceccefbbba6b4071ed77434f Mon Sep 17 00:00:00 2001 From: Tudor-Dan Ambarus Date: Fri, 29 Sep 2017 12:21:04 +0300 Subject: crypto: dh - return unsigned int for dh_data_size() p->key_size, p->p_size, p->g_size are all of unsigned int type. Signed-off-by: Tudor Ambarus Signed-off-by: Herbert Xu --- crypto/dh_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crypto') diff --git a/crypto/dh_helper.c b/crypto/dh_helper.c index 8ba8a3f82620..69869dad344a 100644 --- a/crypto/dh_helper.c +++ b/crypto/dh_helper.c @@ -28,7 +28,7 @@ static inline const u8 *dh_unpack_data(void *dst, const void *src, size_t size) return src + size; } -static inline int dh_data_size(const struct dh *p) +static inline unsigned int dh_data_size(const struct dh *p) { return p->key_size + p->p_size + p->g_size; } -- cgit From 5b3f3a8bede7d3af2dc9ea20b0ad971d4e5e83cc Mon Sep 17 00:00:00 2001 From: Tudor-Dan Ambarus Date: Fri, 29 Sep 2017 12:21:05 +0300 Subject: crypto: dh - return unsigned value for crypto_dh_key_len() DH_KPP_SECRET_MIN_SIZE and dh_data_size() are both returning unsigned values. Signed-off-by: Tudor Ambarus Signed-off-by: Herbert Xu --- crypto/dh_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crypto') diff --git a/crypto/dh_helper.c b/crypto/dh_helper.c index 69869dad344a..a413b311e568 100644 --- a/crypto/dh_helper.c +++ b/crypto/dh_helper.c @@ -33,7 +33,7 @@ static inline unsigned int dh_data_size(const struct dh *p) return p->key_size + p->p_size + p->g_size; } -int crypto_dh_key_len(const struct dh *p) +unsigned int crypto_dh_key_len(const struct dh *p) { return DH_KPP_SECRET_MIN_SIZE + dh_data_size(p); } -- cgit From 9e49451d7a15365d172a75a7ab8f1c305458253a Mon Sep 17 00:00:00 2001 From: Stephan Mueller Date: Tue, 3 Oct 2017 04:19:59 +0200 Subject: crypto: keywrap - simplify code The code is simplified by using two __be64 values for the operation instead of using two arrays of u8. This allows to get rid of the memory alignment code. In addition, the crypto_xor can be replaced with a native XOR operation. Finally, the definition of the variables is re-arranged such that the data structures come before simple variables to potentially reduce memory space. Signed-off-by: Stephan Mueller Signed-off-by: Herbert Xu --- crypto/keywrap.c | 84 ++++++++++++++++++-------------------------------------- 1 file changed, 26 insertions(+), 58 deletions(-) (limited to 'crypto') diff --git a/crypto/keywrap.c b/crypto/keywrap.c index 72014f963ba7..744e35134c45 100644 --- a/crypto/keywrap.c +++ b/crypto/keywrap.c @@ -93,18 +93,10 @@ struct crypto_kw_ctx { struct crypto_kw_block { #define SEMIBSIZE 8 - u8 A[SEMIBSIZE]; - u8 R[SEMIBSIZE]; + __be64 A; + __be64 R; }; -/* convert 64 bit integer into its string representation */ -static inline void crypto_kw_cpu_to_be64(u64 val, u8 *buf) -{ - __be64 *a = (__be64 *)buf; - - *a = cpu_to_be64(val); -} - /* * Fast forward the SGL to the "end" length minus SEMIBSIZE. * The start in the SGL defined by the fast-forward is returned with @@ -139,17 +131,10 @@ static int crypto_kw_decrypt(struct blkcipher_desc *desc, struct crypto_blkcipher *tfm = desc->tfm; struct crypto_kw_ctx *ctx = crypto_blkcipher_ctx(tfm); struct crypto_cipher *child = ctx->child; - - unsigned long alignmask = max_t(unsigned long, SEMIBSIZE, - crypto_cipher_alignmask(child)); - unsigned int i; - - u8 blockbuf[sizeof(struct crypto_kw_block) + alignmask]; - struct crypto_kw_block *block = (struct crypto_kw_block *) - PTR_ALIGN(blockbuf + 0, alignmask + 1); - - u64 t = 6 * ((nbytes) >> 3); + struct crypto_kw_block block; struct scatterlist *lsrc, *ldst; + u64 t = 6 * ((nbytes) >> 3); + unsigned int i; int ret = 0; /* @@ -160,7 +145,7 @@ static int crypto_kw_decrypt(struct blkcipher_desc *desc, return -EINVAL; /* Place the IV into block A */ - memcpy(block->A, desc->info, SEMIBSIZE); + memcpy(&block.A, desc->info, SEMIBSIZE); /* * src scatterlist is read-only. dst scatterlist is r/w. During the @@ -171,32 +156,27 @@ static int crypto_kw_decrypt(struct blkcipher_desc *desc, ldst = dst; for (i = 0; i < 6; i++) { - u8 tbe_buffer[SEMIBSIZE + alignmask]; - /* alignment for the crypto_xor and the _to_be64 operation */ - u8 *tbe = PTR_ALIGN(tbe_buffer + 0, alignmask + 1); - unsigned int tmp_nbytes = nbytes; struct scatter_walk src_walk, dst_walk; + unsigned int tmp_nbytes = nbytes; while (tmp_nbytes) { /* move pointer by tmp_nbytes in the SGL */ crypto_kw_scatterlist_ff(&src_walk, lsrc, tmp_nbytes); /* get the source block */ - scatterwalk_copychunks(block->R, &src_walk, SEMIBSIZE, + scatterwalk_copychunks(&block.R, &src_walk, SEMIBSIZE, false); - /* perform KW operation: get counter as byte string */ - crypto_kw_cpu_to_be64(t, tbe); /* perform KW operation: modify IV with counter */ - crypto_xor(block->A, tbe, SEMIBSIZE); + block.A ^= cpu_to_be64(t); t--; /* perform KW operation: decrypt block */ - crypto_cipher_decrypt_one(child, (u8*)block, - (u8*)block); + crypto_cipher_decrypt_one(child, (u8*)&block, + (u8*)&block); /* move pointer by tmp_nbytes in the SGL */ crypto_kw_scatterlist_ff(&dst_walk, ldst, tmp_nbytes); /* Copy block->R into place */ - scatterwalk_copychunks(block->R, &dst_walk, SEMIBSIZE, + scatterwalk_copychunks(&block.R, &dst_walk, SEMIBSIZE, true); tmp_nbytes -= SEMIBSIZE; @@ -208,11 +188,10 @@ static int crypto_kw_decrypt(struct blkcipher_desc *desc, } /* Perform authentication check */ - if (crypto_memneq("\xA6\xA6\xA6\xA6\xA6\xA6\xA6\xA6", block->A, - SEMIBSIZE)) + if (block.A != cpu_to_be64(0xa6a6a6a6a6a6a6a6)) ret = -EBADMSG; - memzero_explicit(block, sizeof(struct crypto_kw_block)); + memzero_explicit(&block, sizeof(struct crypto_kw_block)); return ret; } @@ -224,17 +203,10 @@ static int crypto_kw_encrypt(struct blkcipher_desc *desc, struct crypto_blkcipher *tfm = desc->tfm; struct crypto_kw_ctx *ctx = crypto_blkcipher_ctx(tfm); struct crypto_cipher *child = ctx->child; - - unsigned long alignmask = max_t(unsigned long, SEMIBSIZE, - crypto_cipher_alignmask(child)); - unsigned int i; - - u8 blockbuf[sizeof(struct crypto_kw_block) + alignmask]; - struct crypto_kw_block *block = (struct crypto_kw_block *) - PTR_ALIGN(blockbuf + 0, alignmask + 1); - - u64 t = 1; + struct crypto_kw_block block; struct scatterlist *lsrc, *ldst; + u64 t = 1; + unsigned int i; /* * Require at least 2 semiblocks (note, the 3rd semiblock that is @@ -249,7 +221,7 @@ static int crypto_kw_encrypt(struct blkcipher_desc *desc, * Place the predefined IV into block A -- for encrypt, the caller * does not need to provide an IV, but he needs to fetch the final IV. */ - memcpy(block->A, "\xA6\xA6\xA6\xA6\xA6\xA6\xA6\xA6", SEMIBSIZE); + block.A = cpu_to_be64(0xa6a6a6a6a6a6a6a6); /* * src scatterlist is read-only. dst scatterlist is r/w. During the @@ -260,30 +232,26 @@ static int crypto_kw_encrypt(struct blkcipher_desc *desc, ldst = dst; for (i = 0; i < 6; i++) { - u8 tbe_buffer[SEMIBSIZE + alignmask]; - u8 *tbe = PTR_ALIGN(tbe_buffer + 0, alignmask + 1); - unsigned int tmp_nbytes = nbytes; struct scatter_walk src_walk, dst_walk; + unsigned int tmp_nbytes = nbytes; scatterwalk_start(&src_walk, lsrc); scatterwalk_start(&dst_walk, ldst); while (tmp_nbytes) { /* get the source block */ - scatterwalk_copychunks(block->R, &src_walk, SEMIBSIZE, + scatterwalk_copychunks(&block.R, &src_walk, SEMIBSIZE, false); /* perform KW operation: encrypt block */ - crypto_cipher_encrypt_one(child, (u8 *)block, - (u8 *)block); - /* perform KW operation: get counter as byte string */ - crypto_kw_cpu_to_be64(t, tbe); + crypto_cipher_encrypt_one(child, (u8 *)&block, + (u8 *)&block); /* perform KW operation: modify IV with counter */ - crypto_xor(block->A, tbe, SEMIBSIZE); + block.A ^= cpu_to_be64(t); t++; /* Copy block->R into place */ - scatterwalk_copychunks(block->R, &dst_walk, SEMIBSIZE, + scatterwalk_copychunks(&block.R, &dst_walk, SEMIBSIZE, true); tmp_nbytes -= SEMIBSIZE; @@ -295,9 +263,9 @@ static int crypto_kw_encrypt(struct blkcipher_desc *desc, } /* establish the IV for the caller to pick up */ - memcpy(desc->info, block->A, SEMIBSIZE); + memcpy(desc->info, &block.A, SEMIBSIZE); - memzero_explicit(block, sizeof(struct crypto_kw_block)); + memzero_explicit(&block, sizeof(struct crypto_kw_block)); return 0; } -- cgit From acfc587810bea08fdd62c9d5ed7cefe8be874a4f Mon Sep 17 00:00:00 2001 From: Harsh Jain Date: Sun, 8 Oct 2017 13:37:20 +0530 Subject: crypto: gf128mul - The x8_ble multiplication functions It multiply GF(2^128) elements in the ble format. It will be used by chelsio driver to speed up gf multiplication. Signed-off-by: Harsh Jain Signed-off-by: Herbert Xu --- crypto/gf128mul.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'crypto') diff --git a/crypto/gf128mul.c b/crypto/gf128mul.c index dc012129c063..24e601954c7a 100644 --- a/crypto/gf128mul.c +++ b/crypto/gf128mul.c @@ -156,6 +156,19 @@ static void gf128mul_x8_bbe(be128 *x) x->b = cpu_to_be64((b << 8) ^ _tt); } +void gf128mul_x8_ble(le128 *r, const le128 *x) +{ + u64 a = le64_to_cpu(x->a); + u64 b = le64_to_cpu(x->b); + + /* equivalent to gf128mul_table_be[b >> 63] (see crypto/gf128mul.c): */ + u64 _tt = gf128mul_table_be[a >> 56]; + + r->a = cpu_to_le64((a << 8) | (b >> 56)); + r->b = cpu_to_le64((b << 8) ^ _tt); +} +EXPORT_SYMBOL(gf128mul_x8_ble); + void gf128mul_lle(be128 *r, const be128 *b) { be128 p[8]; -- cgit From 59517226a35a4041e41d114d085846ac94ebfbf2 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 9 Oct 2017 14:43:21 -0500 Subject: crypto: tcrypt - mark expected switch fall-throughs in do_test() In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Cc: Herbert Xu Cc: "David S. Miller" Cc: linux-crypto@vger.kernel.org Signed-off-by: Gustavo A. R. Silva Signed-off-by: Herbert Xu --- crypto/tcrypt.c | 108 ++++++++++++++++++++++++++------------------------------ 1 file changed, 51 insertions(+), 57 deletions(-) (limited to 'crypto') diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index a371c072b62f..28bffa6f0292 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c @@ -1606,119 +1606,116 @@ static int do_test(const char *alg, u32 type, u32 mask, int m) speed_template_32); break; - case 300: if (alg) { test_hash_speed(alg, sec, generic_hash_speed_template); break; } - /* fall through */ - case 301: test_hash_speed("md4", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - + /* fall through */ case 302: test_hash_speed("md5", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - + /* fall through */ case 303: test_hash_speed("sha1", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - + /* fall through */ case 304: test_hash_speed("sha256", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - + /* fall through */ case 305: test_hash_speed("sha384", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - + /* fall through */ case 306: test_hash_speed("sha512", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - + /* fall through */ case 307: test_hash_speed("wp256", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - + /* fall through */ case 308: test_hash_speed("wp384", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - + /* fall through */ case 309: test_hash_speed("wp512", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - + /* fall through */ case 310: test_hash_speed("tgr128", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - + /* fall through */ case 311: test_hash_speed("tgr160", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - + /* fall through */ case 312: test_hash_speed("tgr192", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - + /* fall through */ case 313: test_hash_speed("sha224", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - + /* fall through */ case 314: test_hash_speed("rmd128", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - + /* fall through */ case 315: test_hash_speed("rmd160", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - + /* fall through */ case 316: test_hash_speed("rmd256", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - + /* fall through */ case 317: test_hash_speed("rmd320", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - + /* fall through */ case 318: test_hash_speed("ghash-generic", sec, hash_speed_template_16); if (mode > 300 && mode < 400) break; - + /* fall through */ case 319: test_hash_speed("crc32c", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - + /* fall through */ case 320: test_hash_speed("crct10dif", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - + /* fall through */ case 321: test_hash_speed("poly1305", sec, poly1305_speed_template); if (mode > 300 && mode < 400) break; - + /* fall through */ case 322: test_hash_speed("sha3-224", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - + /* fall through */ case 323: test_hash_speed("sha3-256", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - + /* fall through */ case 324: test_hash_speed("sha3-384", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - + /* fall through */ case 325: test_hash_speed("sha3-512", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - + /* fall through */ case 326: test_hash_speed("sm3", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - + /* fall through */ case 399: break; @@ -1727,110 +1724,107 @@ static int do_test(const char *alg, u32 type, u32 mask, int m) test_ahash_speed(alg, sec, generic_hash_speed_template); break; } - /* fall through */ - case 401: test_ahash_speed("md4", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - + /* fall through */ case 402: test_ahash_speed("md5", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - + /* fall through */ case 403: test_ahash_speed("sha1", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - + /* fall through */ case 404: test_ahash_speed("sha256", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - + /* fall through */ case 405: test_ahash_speed("sha384", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - + /* fall through */ case 406: test_ahash_speed("sha512", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - + /* fall through */ case 407: test_ahash_speed("wp256", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - + /* fall through */ case 408: test_ahash_speed("wp384", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - + /* fall through */ case 409: test_ahash_speed("wp512", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - + /* fall through */ case 410: test_ahash_speed("tgr128", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - + /* fall through */ case 411: test_ahash_speed("tgr160", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - + /* fall through */ case 412: test_ahash_speed("tgr192", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - + /* fall through */ case 413: test_ahash_speed("sha224", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - + /* fall through */ case 414: test_ahash_speed("rmd128", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - + /* fall through */ case 415: test_ahash_speed("rmd160", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - + /* fall through */ case 416: test_ahash_speed("rmd256", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - + /* fall through */ case 417: test_ahash_speed("rmd320", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - + /* fall through */ case 418: test_ahash_speed("sha3-224", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - + /* fall through */ case 419: test_ahash_speed("sha3-256", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - + /* fall through */ case 420: test_ahash_speed("sha3-384", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - - + /* fall through */ case 421: test_ahash_speed("sha3-512", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - + /* fall through */ case 422: test_mb_ahash_speed("sha1", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - + /* fall through */ case 423: test_mb_ahash_speed("sha256", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - + /* fall through */ case 424: test_mb_ahash_speed("sha512", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - + /* fall through */ case 425: test_mb_ahash_speed("sm3", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - + /* fall through */ case 499: break; -- cgit From 7aacbfcb331ceff3ac43096d563a1f93ed46e35e Mon Sep 17 00:00:00 2001 From: Robert Baronescu Date: Tue, 10 Oct 2017 13:22:00 +0300 Subject: crypto: tcrypt - fix buffer lengths in test_aead_speed() Fix the way the length of the buffers used for encryption / decryption are computed. For e.g. in case of encryption, input buffer does not contain an authentication tag. Signed-off-by: Robert Baronescu Signed-off-by: Herbert Xu --- crypto/tcrypt.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'crypto') diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index 28bffa6f0292..65d191b27ecc 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c @@ -340,7 +340,7 @@ static void test_aead_speed(const char *algo, int enc, unsigned int secs, } sg_init_aead(sg, xbuf, - *b_size + (enc ? authsize : 0)); + *b_size + (enc ? 0 : authsize)); sg_init_aead(sgout, xoutbuf, *b_size + (enc ? authsize : 0)); @@ -348,7 +348,9 @@ static void test_aead_speed(const char *algo, int enc, unsigned int secs, sg_set_buf(&sg[0], assoc, aad_size); sg_set_buf(&sgout[0], assoc, aad_size); - aead_request_set_crypt(req, sg, sgout, *b_size, iv); + aead_request_set_crypt(req, sg, sgout, + *b_size + (enc ? 0 : authsize), + iv); aead_request_set_ad(req, aad_size); if (secs) -- cgit From 6b80ea389a0bceee6a0a801474b78ad0a8cd034d Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Wed, 18 Oct 2017 08:00:33 +0100 Subject: crypto: change transient busy return code to -ENOSPC The crypto API was using the -EBUSY return value to indicate both a hard failure to submit a crypto operation into a transformation provider when the latter was busy and the backlog mechanism was not enabled as well as a notification that the operation was queued into the backlog when the backlog mechanism was enabled. Having the same return code indicate two very different conditions depending on a flag is both error prone and requires extra runtime check like the following to discern between the cases: if (err == -EINPROGRESS || (err == -EBUSY && (ahash_request_flags(req) & CRYPTO_TFM_REQ_MAY_BACKLOG))) This patch changes the return code used to indicate a crypto op failed due to the transformation provider being transiently busy to -ENOSPC. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Herbert Xu --- crypto/algapi.c | 6 ++++-- crypto/cryptd.c | 4 +--- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'crypto') diff --git a/crypto/algapi.c b/crypto/algapi.c index aa699ff6c876..60d7366ed343 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -897,9 +897,11 @@ int crypto_enqueue_request(struct crypto_queue *queue, int err = -EINPROGRESS; if (unlikely(queue->qlen >= queue->max_qlen)) { - err = -EBUSY; - if (!(request->flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) + if (!(request->flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) { + err = -ENOSPC; goto out; + } + err = -EBUSY; if (queue->backlog == &queue->list) queue->backlog = &request->list; } diff --git a/crypto/cryptd.c b/crypto/cryptd.c index 0508c48a45c4..bd43cf5be14c 100644 --- a/crypto/cryptd.c +++ b/crypto/cryptd.c @@ -137,16 +137,14 @@ static int cryptd_enqueue_request(struct cryptd_queue *queue, int cpu, err; struct cryptd_cpu_queue *cpu_queue; atomic_t *refcnt; - bool may_backlog; cpu = get_cpu(); cpu_queue = this_cpu_ptr(queue->cpu_queue); err = crypto_enqueue_request(&cpu_queue->queue, request); refcnt = crypto_tfm_ctx(request->tfm); - may_backlog = request->flags & CRYPTO_TFM_REQ_MAY_BACKLOG; - if (err == -EBUSY && !may_backlog) + if (err == -ENOSPC) goto out_put_cpu; queue_work_on(cpu, kcrypto_wq, &cpu_queue->work); -- cgit From 4e5b0ad5827163bd8e57ea595be2681cad12e5c2 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Wed, 18 Oct 2017 08:00:36 +0100 Subject: crypto: remove redundant backlog checks on EBUSY Now that -EBUSY return code only indicates backlog queueing we can safely remove the now redundant check for the CRYPTO_TFM_REQ_MAY_BACKLOG flag when -EBUSY is returned. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Herbert Xu --- crypto/ahash.c | 12 +++--------- crypto/cts.c | 6 ++---- crypto/lrw.c | 8 ++------ crypto/rsa-pkcs1pad.c | 16 ++++------------ crypto/xts.c | 8 ++------ 5 files changed, 13 insertions(+), 37 deletions(-) (limited to 'crypto') diff --git a/crypto/ahash.c b/crypto/ahash.c index 5e8666e6ccae..3a35d67de7d9 100644 --- a/crypto/ahash.c +++ b/crypto/ahash.c @@ -334,9 +334,7 @@ static int ahash_op_unaligned(struct ahash_request *req, return err; err = op(req); - if (err == -EINPROGRESS || - (err == -EBUSY && (ahash_request_flags(req) & - CRYPTO_TFM_REQ_MAY_BACKLOG))) + if (err == -EINPROGRESS || err == -EBUSY) return err; ahash_restore_req(req, err); @@ -394,9 +392,7 @@ static int ahash_def_finup_finish1(struct ahash_request *req, int err) req->base.complete = ahash_def_finup_done2; err = crypto_ahash_reqtfm(req)->final(req); - if (err == -EINPROGRESS || - (err == -EBUSY && (ahash_request_flags(req) & - CRYPTO_TFM_REQ_MAY_BACKLOG))) + if (err == -EINPROGRESS || err == -EBUSY) return err; out: @@ -432,9 +428,7 @@ static int ahash_def_finup(struct ahash_request *req) return err; err = tfm->update(req); - if (err == -EINPROGRESS || - (err == -EBUSY && (ahash_request_flags(req) & - CRYPTO_TFM_REQ_MAY_BACKLOG))) + if (err == -EINPROGRESS || err == -EBUSY) return err; return ahash_def_finup_finish1(req, err); diff --git a/crypto/cts.c b/crypto/cts.c index 243f591dc409..4773c188e6d9 100644 --- a/crypto/cts.c +++ b/crypto/cts.c @@ -136,8 +136,7 @@ static void crypto_cts_encrypt_done(struct crypto_async_request *areq, int err) goto out; err = cts_cbc_encrypt(req); - if (err == -EINPROGRESS || - (err == -EBUSY && req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) + if (err == -EINPROGRESS || err == -EBUSY) return; out: @@ -229,8 +228,7 @@ static void crypto_cts_decrypt_done(struct crypto_async_request *areq, int err) goto out; err = cts_cbc_decrypt(req); - if (err == -EINPROGRESS || - (err == -EBUSY && req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) + if (err == -EINPROGRESS || err == -EBUSY) return; out: diff --git a/crypto/lrw.c b/crypto/lrw.c index 92df312b8c6e..cbbd7c50ad19 100644 --- a/crypto/lrw.c +++ b/crypto/lrw.c @@ -328,9 +328,7 @@ static int do_encrypt(struct skcipher_request *req, int err) crypto_skcipher_encrypt(subreq) ?: post_crypt(req); - if (err == -EINPROGRESS || - (err == -EBUSY && - req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) + if (err == -EINPROGRESS || err == -EBUSY) return err; } @@ -380,9 +378,7 @@ static int do_decrypt(struct skcipher_request *req, int err) crypto_skcipher_decrypt(subreq) ?: post_crypt(req); - if (err == -EINPROGRESS || - (err == -EBUSY && - req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) + if (err == -EINPROGRESS || err == -EBUSY) return err; } diff --git a/crypto/rsa-pkcs1pad.c b/crypto/rsa-pkcs1pad.c index 407c64bdcdd9..2908f93c3e55 100644 --- a/crypto/rsa-pkcs1pad.c +++ b/crypto/rsa-pkcs1pad.c @@ -279,9 +279,7 @@ static int pkcs1pad_encrypt(struct akcipher_request *req) req->dst, ctx->key_size - 1, req->dst_len); err = crypto_akcipher_encrypt(&req_ctx->child_req); - if (err != -EINPROGRESS && - (err != -EBUSY || - !(req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG))) + if (err != -EINPROGRESS && err != -EBUSY) return pkcs1pad_encrypt_sign_complete(req, err); return err; @@ -383,9 +381,7 @@ static int pkcs1pad_decrypt(struct akcipher_request *req) ctx->key_size); err = crypto_akcipher_decrypt(&req_ctx->child_req); - if (err != -EINPROGRESS && - (err != -EBUSY || - !(req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG))) + if (err != -EINPROGRESS && err != -EBUSY) return pkcs1pad_decrypt_complete(req, err); return err; @@ -440,9 +436,7 @@ static int pkcs1pad_sign(struct akcipher_request *req) req->dst, ctx->key_size - 1, req->dst_len); err = crypto_akcipher_sign(&req_ctx->child_req); - if (err != -EINPROGRESS && - (err != -EBUSY || - !(req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG))) + if (err != -EINPROGRESS && err != -EBUSY) return pkcs1pad_encrypt_sign_complete(req, err); return err; @@ -561,9 +555,7 @@ static int pkcs1pad_verify(struct akcipher_request *req) ctx->key_size); err = crypto_akcipher_verify(&req_ctx->child_req); - if (err != -EINPROGRESS && - (err != -EBUSY || - !(req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG))) + if (err != -EINPROGRESS && err != -EBUSY) return pkcs1pad_verify_complete(req, err); return err; diff --git a/crypto/xts.c b/crypto/xts.c index d86c11a8c882..af68012dfab3 100644 --- a/crypto/xts.c +++ b/crypto/xts.c @@ -269,9 +269,7 @@ static int do_encrypt(struct skcipher_request *req, int err) crypto_skcipher_encrypt(subreq) ?: post_crypt(req); - if (err == -EINPROGRESS || - (err == -EBUSY && - req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) + if (err == -EINPROGRESS || err == -EBUSY) return err; } @@ -321,9 +319,7 @@ static int do_decrypt(struct skcipher_request *req, int err) crypto_skcipher_decrypt(subreq) ?: post_crypt(req); - if (err == -EINPROGRESS || - (err == -EBUSY && - req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) + if (err == -EINPROGRESS || err == -EBUSY) return err; } -- cgit From ada69a1639eca54ff74d839a6513c43db8d57d70 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Wed, 18 Oct 2017 08:00:38 +0100 Subject: crypto: introduce crypto wait for async op Invoking a possibly async. crypto op and waiting for completion while correctly handling backlog processing is a common task in the crypto API implementation and outside users of it. This patch adds a generic implementation for doing so in preparation for using it across the board instead of hand rolled versions. Signed-off-by: Gilad Ben-Yossef CC: Eric Biggers CC: Jonathan Cameron Signed-off-by: Herbert Xu --- crypto/api.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'crypto') diff --git a/crypto/api.c b/crypto/api.c index 941cd4c6c7ec..2a2479d168aa 100644 --- a/crypto/api.c +++ b/crypto/api.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "internal.h" LIST_HEAD(crypto_alg_list); @@ -595,5 +596,17 @@ int crypto_has_alg(const char *name, u32 type, u32 mask) } EXPORT_SYMBOL_GPL(crypto_has_alg); +void crypto_req_done(struct crypto_async_request *req, int err) +{ + struct crypto_wait *wait = req->data; + + if (err == -EINPROGRESS) + return; + + wait->err = err; + complete(&wait->completion); +} +EXPORT_SYMBOL_GPL(crypto_req_done); + MODULE_DESCRIPTION("Cryptographic core API"); MODULE_LICENSE("GPL"); -- cgit From 2c3f8b162106a7d12097d02eb22459f57fab8247 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Wed, 18 Oct 2017 08:00:39 +0100 Subject: crypto: algif - move to generic async completion algif starts several async crypto ops and waits for their completion. Move it over to generic code doing the same. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Herbert Xu --- crypto/af_alg.c | 27 --------------------------- crypto/algif_aead.c | 8 ++++---- crypto/algif_hash.c | 30 ++++++++++++++---------------- crypto/algif_skcipher.c | 9 ++++----- 4 files changed, 22 insertions(+), 52 deletions(-) (limited to 'crypto') diff --git a/crypto/af_alg.c b/crypto/af_alg.c index 337cf382718e..85cea9de324a 100644 --- a/crypto/af_alg.c +++ b/crypto/af_alg.c @@ -481,33 +481,6 @@ int af_alg_cmsg_send(struct msghdr *msg, struct af_alg_control *con) } EXPORT_SYMBOL_GPL(af_alg_cmsg_send); -int af_alg_wait_for_completion(int err, struct af_alg_completion *completion) -{ - switch (err) { - case -EINPROGRESS: - case -EBUSY: - wait_for_completion(&completion->completion); - reinit_completion(&completion->completion); - err = completion->err; - break; - }; - - return err; -} -EXPORT_SYMBOL_GPL(af_alg_wait_for_completion); - -void af_alg_complete(struct crypto_async_request *req, int err) -{ - struct af_alg_completion *completion = req->data; - - if (err == -EINPROGRESS) - return; - - completion->err = err; - complete(&completion->completion); -} -EXPORT_SYMBOL_GPL(af_alg_complete); - /** * af_alg_alloc_tsgl - allocate the TX SGL * diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c index 516b38c3a169..aacae0837aff 100644 --- a/crypto/algif_aead.c +++ b/crypto/algif_aead.c @@ -278,11 +278,11 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg, /* Synchronous operation */ aead_request_set_callback(&areq->cra_u.aead_req, CRYPTO_TFM_REQ_MAY_BACKLOG, - af_alg_complete, &ctx->completion); - err = af_alg_wait_for_completion(ctx->enc ? + crypto_req_done, &ctx->wait); + err = crypto_wait_req(ctx->enc ? crypto_aead_encrypt(&areq->cra_u.aead_req) : crypto_aead_decrypt(&areq->cra_u.aead_req), - &ctx->completion); + &ctx->wait); } /* AIO operation in progress */ @@ -554,7 +554,7 @@ static int aead_accept_parent_nokey(void *private, struct sock *sk) ctx->merge = 0; ctx->enc = 0; ctx->aead_assoclen = 0; - af_alg_init_completion(&ctx->completion); + crypto_init_wait(&ctx->wait); ask->private = ctx; diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c index 5e92bd275ef3..76d2e716c792 100644 --- a/crypto/algif_hash.c +++ b/crypto/algif_hash.c @@ -26,7 +26,7 @@ struct hash_ctx { u8 *result; - struct af_alg_completion completion; + struct crypto_wait wait; unsigned int len; bool more; @@ -88,8 +88,7 @@ static int hash_sendmsg(struct socket *sock, struct msghdr *msg, if ((msg->msg_flags & MSG_MORE)) hash_free_result(sk, ctx); - err = af_alg_wait_for_completion(crypto_ahash_init(&ctx->req), - &ctx->completion); + err = crypto_wait_req(crypto_ahash_init(&ctx->req), &ctx->wait); if (err) goto unlock; } @@ -110,8 +109,8 @@ static int hash_sendmsg(struct socket *sock, struct msghdr *msg, ahash_request_set_crypt(&ctx->req, ctx->sgl.sg, NULL, len); - err = af_alg_wait_for_completion(crypto_ahash_update(&ctx->req), - &ctx->completion); + err = crypto_wait_req(crypto_ahash_update(&ctx->req), + &ctx->wait); af_alg_free_sg(&ctx->sgl); if (err) goto unlock; @@ -129,8 +128,8 @@ static int hash_sendmsg(struct socket *sock, struct msghdr *msg, goto unlock; ahash_request_set_crypt(&ctx->req, NULL, ctx->result, 0); - err = af_alg_wait_for_completion(crypto_ahash_final(&ctx->req), - &ctx->completion); + err = crypto_wait_req(crypto_ahash_final(&ctx->req), + &ctx->wait); } unlock: @@ -171,7 +170,7 @@ static ssize_t hash_sendpage(struct socket *sock, struct page *page, } else { if (!ctx->more) { err = crypto_ahash_init(&ctx->req); - err = af_alg_wait_for_completion(err, &ctx->completion); + err = crypto_wait_req(err, &ctx->wait); if (err) goto unlock; } @@ -179,7 +178,7 @@ static ssize_t hash_sendpage(struct socket *sock, struct page *page, err = crypto_ahash_update(&ctx->req); } - err = af_alg_wait_for_completion(err, &ctx->completion); + err = crypto_wait_req(err, &ctx->wait); if (err) goto unlock; @@ -215,17 +214,16 @@ static int hash_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, ahash_request_set_crypt(&ctx->req, NULL, ctx->result, 0); if (!result && !ctx->more) { - err = af_alg_wait_for_completion( - crypto_ahash_init(&ctx->req), - &ctx->completion); + err = crypto_wait_req(crypto_ahash_init(&ctx->req), + &ctx->wait); if (err) goto unlock; } if (!result || ctx->more) { ctx->more = 0; - err = af_alg_wait_for_completion(crypto_ahash_final(&ctx->req), - &ctx->completion); + err = crypto_wait_req(crypto_ahash_final(&ctx->req), + &ctx->wait); if (err) goto unlock; } @@ -476,13 +474,13 @@ static int hash_accept_parent_nokey(void *private, struct sock *sk) ctx->result = NULL; ctx->len = len; ctx->more = 0; - af_alg_init_completion(&ctx->completion); + crypto_init_wait(&ctx->wait); ask->private = ctx; ahash_request_set_tfm(&ctx->req, hash); ahash_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG, - af_alg_complete, &ctx->completion); + crypto_req_done, &ctx->wait); sk->sk_destruct = hash_sock_destruct; diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c index 8ae4170aaeb4..9954b078f0b9 100644 --- a/crypto/algif_skcipher.c +++ b/crypto/algif_skcipher.c @@ -129,12 +129,11 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg, skcipher_request_set_callback(&areq->cra_u.skcipher_req, CRYPTO_TFM_REQ_MAY_SLEEP | CRYPTO_TFM_REQ_MAY_BACKLOG, - af_alg_complete, - &ctx->completion); - err = af_alg_wait_for_completion(ctx->enc ? + crypto_req_done, &ctx->wait); + err = crypto_wait_req(ctx->enc ? crypto_skcipher_encrypt(&areq->cra_u.skcipher_req) : crypto_skcipher_decrypt(&areq->cra_u.skcipher_req), - &ctx->completion); + &ctx->wait); } /* AIO operation in progress */ @@ -388,7 +387,7 @@ static int skcipher_accept_parent_nokey(void *private, struct sock *sk) ctx->more = 0; ctx->merge = 0; ctx->enc = 0; - af_alg_init_completion(&ctx->completion); + crypto_init_wait(&ctx->wait); ask->private = ctx; -- cgit From 0ca2a04ac398a71e49b0b093f365d1188cc13e01 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Wed, 18 Oct 2017 08:00:40 +0100 Subject: crypto: move pub key to generic async completion public_key_verify_signature() is starting an async crypto op and waiting for it to complete. Move it over to generic code doing the same. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Herbert Xu --- crypto/asymmetric_keys/public_key.c | 28 ++++------------------------ 1 file changed, 4 insertions(+), 24 deletions(-) (limited to 'crypto') diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c index 3cd6e12cfc46..d916235d6cf5 100644 --- a/crypto/asymmetric_keys/public_key.c +++ b/crypto/asymmetric_keys/public_key.c @@ -57,29 +57,13 @@ static void public_key_destroy(void *payload0, void *payload3) public_key_signature_free(payload3); } -struct public_key_completion { - struct completion completion; - int err; -}; - -static void public_key_verify_done(struct crypto_async_request *req, int err) -{ - struct public_key_completion *compl = req->data; - - if (err == -EINPROGRESS) - return; - - compl->err = err; - complete(&compl->completion); -} - /* * Verify a signature using a public key. */ int public_key_verify_signature(const struct public_key *pkey, const struct public_key_signature *sig) { - struct public_key_completion compl; + struct crypto_wait cwait; struct crypto_akcipher *tfm; struct akcipher_request *req; struct scatterlist sig_sg, digest_sg; @@ -131,20 +115,16 @@ int public_key_verify_signature(const struct public_key *pkey, sg_init_one(&digest_sg, output, outlen); akcipher_request_set_crypt(req, &sig_sg, &digest_sg, sig->s_size, outlen); - init_completion(&compl.completion); + crypto_init_wait(&cwait); akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, - public_key_verify_done, &compl); + crypto_req_done, &cwait); /* Perform the verification calculation. This doesn't actually do the * verification, but rather calculates the hash expected by the * signature and returns that to us. */ - ret = crypto_akcipher_verify(req); - if ((ret == -EINPROGRESS) || (ret == -EBUSY)) { - wait_for_completion(&compl.completion); - ret = compl.err; - } + ret = crypto_wait_req(crypto_akcipher_verify(req), &cwait); if (ret < 0) goto out_free_output; -- cgit From 85a2dea4bdbfa7565818ca094d08e838cf62da77 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Wed, 18 Oct 2017 08:00:41 +0100 Subject: crypto: drbg - move to generic async completion DRBG is starting an async. crypto op and waiting for it complete. Move it over to generic code doing the same. The code now also passes CRYPTO_TFM_REQ_MAY_SLEEP flag indicating crypto request memory allocation may use GFP_KERNEL which should be perfectly fine as the code is obviously sleeping for the completion of the request any way. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Herbert Xu --- crypto/drbg.c | 36 +++++++++--------------------------- 1 file changed, 9 insertions(+), 27 deletions(-) (limited to 'crypto') diff --git a/crypto/drbg.c b/crypto/drbg.c index 70018397e59a..4faa2781c964 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -1651,16 +1651,6 @@ static int drbg_fini_sym_kernel(struct drbg_state *drbg) return 0; } -static void drbg_skcipher_cb(struct crypto_async_request *req, int error) -{ - struct drbg_state *drbg = req->data; - - if (error == -EINPROGRESS) - return; - drbg->ctr_async_err = error; - complete(&drbg->ctr_completion); -} - static int drbg_init_sym_kernel(struct drbg_state *drbg) { struct crypto_cipher *tfm; @@ -1691,7 +1681,7 @@ static int drbg_init_sym_kernel(struct drbg_state *drbg) return PTR_ERR(sk_tfm); } drbg->ctr_handle = sk_tfm; - init_completion(&drbg->ctr_completion); + crypto_init_wait(&drbg->ctr_wait); req = skcipher_request_alloc(sk_tfm, GFP_KERNEL); if (!req) { @@ -1700,8 +1690,9 @@ static int drbg_init_sym_kernel(struct drbg_state *drbg) return -ENOMEM; } drbg->ctr_req = req; - skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, - drbg_skcipher_cb, drbg); + skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | + CRYPTO_TFM_REQ_MAY_SLEEP, + crypto_req_done, &drbg->ctr_wait); alignmask = crypto_skcipher_alignmask(sk_tfm); drbg->ctr_null_value_buf = kzalloc(DRBG_CTR_NULL_LEN + alignmask, @@ -1762,21 +1753,12 @@ static int drbg_kcapi_sym_ctr(struct drbg_state *drbg, /* Output buffer may not be valid for SGL, use scratchpad */ skcipher_request_set_crypt(drbg->ctr_req, &sg_in, &sg_out, cryptlen, drbg->V); - ret = crypto_skcipher_encrypt(drbg->ctr_req); - switch (ret) { - case 0: - break; - case -EINPROGRESS: - case -EBUSY: - wait_for_completion(&drbg->ctr_completion); - if (!drbg->ctr_async_err) { - reinit_completion(&drbg->ctr_completion); - break; - } - default: + ret = crypto_wait_req(crypto_skcipher_encrypt(drbg->ctr_req), + &drbg->ctr_wait); + if (ret) goto out; - } - init_completion(&drbg->ctr_completion); + + crypto_init_wait(&drbg->ctr_wait); memcpy(outbuf, drbg->outscratchpad, cryptlen); -- cgit From 76c6739477fa9e16a75633d1f57c62a8a57388ad Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Wed, 18 Oct 2017 08:00:42 +0100 Subject: crypto: gcm - move to generic async completion gcm is starting an async. crypto op and waiting for it complete. Move it over to generic code doing the same. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Herbert Xu --- crypto/gcm.c | 32 ++++++-------------------------- 1 file changed, 6 insertions(+), 26 deletions(-) (limited to 'crypto') diff --git a/crypto/gcm.c b/crypto/gcm.c index 80cf6cfe082b..8589681fb9f6 100644 --- a/crypto/gcm.c +++ b/crypto/gcm.c @@ -17,7 +17,6 @@ #include #include #include "internal.h" -#include #include #include #include @@ -79,11 +78,6 @@ struct crypto_gcm_req_priv_ctx { } u; }; -struct crypto_gcm_setkey_result { - int err; - struct completion completion; -}; - static struct { u8 buf[16]; struct scatterlist sg; @@ -99,17 +93,6 @@ static inline struct crypto_gcm_req_priv_ctx *crypto_gcm_reqctx( return (void *)PTR_ALIGN((u8 *)aead_request_ctx(req), align + 1); } -static void crypto_gcm_setkey_done(struct crypto_async_request *req, int err) -{ - struct crypto_gcm_setkey_result *result = req->data; - - if (err == -EINPROGRESS) - return; - - result->err = err; - complete(&result->completion); -} - static int crypto_gcm_setkey(struct crypto_aead *aead, const u8 *key, unsigned int keylen) { @@ -120,7 +103,7 @@ static int crypto_gcm_setkey(struct crypto_aead *aead, const u8 *key, be128 hash; u8 iv[16]; - struct crypto_gcm_setkey_result result; + struct crypto_wait wait; struct scatterlist sg[1]; struct skcipher_request req; @@ -141,21 +124,18 @@ static int crypto_gcm_setkey(struct crypto_aead *aead, const u8 *key, if (!data) return -ENOMEM; - init_completion(&data->result.completion); + crypto_init_wait(&data->wait); sg_init_one(data->sg, &data->hash, sizeof(data->hash)); skcipher_request_set_tfm(&data->req, ctr); skcipher_request_set_callback(&data->req, CRYPTO_TFM_REQ_MAY_SLEEP | CRYPTO_TFM_REQ_MAY_BACKLOG, - crypto_gcm_setkey_done, - &data->result); + crypto_req_done, + &data->wait); skcipher_request_set_crypt(&data->req, data->sg, data->sg, sizeof(data->hash), data->iv); - err = crypto_skcipher_encrypt(&data->req); - if (err == -EINPROGRESS || err == -EBUSY) { - wait_for_completion(&data->result.completion); - err = data->result.err; - } + err = crypto_wait_req(crypto_skcipher_encrypt(&data->req), + &data->wait); if (err) goto out; -- cgit From 7f39713684acb2745506be195d31f73ce410fb24 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Wed, 18 Oct 2017 08:00:43 +0100 Subject: crypto: testmgr - move to generic async completion testmgr is starting async. crypto ops and waiting for them to complete. Move it over to generic code doing the same. This also provides a test of the generic crypto async. wait code. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Herbert Xu --- crypto/testmgr.c | 204 ++++++++++++++++++------------------------------------- 1 file changed, 66 insertions(+), 138 deletions(-) (limited to 'crypto') diff --git a/crypto/testmgr.c b/crypto/testmgr.c index baf96cecaf49..29d7020b8826 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -76,11 +76,6 @@ int alg_test(const char *driver, const char *alg, u32 type, u32 mask) #define ENCRYPT 1 #define DECRYPT 0 -struct tcrypt_result { - struct completion completion; - int err; -}; - struct aead_test_suite { struct { const struct aead_testvec *vecs; @@ -155,17 +150,6 @@ static void hexdump(unsigned char *buf, unsigned int len) buf, len, false); } -static void tcrypt_complete(struct crypto_async_request *req, int err) -{ - struct tcrypt_result *res = req->data; - - if (err == -EINPROGRESS) - return; - - res->err = err; - complete(&res->completion); -} - static int testmgr_alloc_buf(char *buf[XBUFSIZE]) { int i; @@ -193,20 +177,10 @@ static void testmgr_free_buf(char *buf[XBUFSIZE]) free_page((unsigned long)buf[i]); } -static int wait_async_op(struct tcrypt_result *tr, int ret) -{ - if (ret == -EINPROGRESS || ret == -EBUSY) { - wait_for_completion(&tr->completion); - reinit_completion(&tr->completion); - ret = tr->err; - } - return ret; -} - static int ahash_partial_update(struct ahash_request **preq, struct crypto_ahash *tfm, const struct hash_testvec *template, void *hash_buff, int k, int temp, struct scatterlist *sg, - const char *algo, char *result, struct tcrypt_result *tresult) + const char *algo, char *result, struct crypto_wait *wait) { char *state; struct ahash_request *req; @@ -236,7 +210,7 @@ static int ahash_partial_update(struct ahash_request **preq, } ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, - tcrypt_complete, tresult); + crypto_req_done, wait); memcpy(hash_buff, template->plaintext + temp, template->tap[k]); @@ -247,7 +221,7 @@ static int ahash_partial_update(struct ahash_request **preq, pr_err("alg: hash: Failed to import() for %s\n", algo); goto out; } - ret = wait_async_op(tresult, crypto_ahash_update(req)); + ret = crypto_wait_req(crypto_ahash_update(req), wait); if (ret) goto out; *preq = req; @@ -272,7 +246,7 @@ static int __test_hash(struct crypto_ahash *tfm, char *result; char *key; struct ahash_request *req; - struct tcrypt_result tresult; + struct crypto_wait wait; void *hash_buff; char *xbuf[XBUFSIZE]; int ret = -ENOMEM; @@ -286,7 +260,7 @@ static int __test_hash(struct crypto_ahash *tfm, if (testmgr_alloc_buf(xbuf)) goto out_nobuf; - init_completion(&tresult.completion); + crypto_init_wait(&wait); req = ahash_request_alloc(tfm, GFP_KERNEL); if (!req) { @@ -295,7 +269,7 @@ static int __test_hash(struct crypto_ahash *tfm, goto out_noreq; } ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, - tcrypt_complete, &tresult); + crypto_req_done, &wait); j = 0; for (i = 0; i < tcount; i++) { @@ -335,26 +309,26 @@ static int __test_hash(struct crypto_ahash *tfm, ahash_request_set_crypt(req, sg, result, template[i].psize); if (use_digest) { - ret = wait_async_op(&tresult, crypto_ahash_digest(req)); + ret = crypto_wait_req(crypto_ahash_digest(req), &wait); if (ret) { pr_err("alg: hash: digest failed on test %d " "for %s: ret=%d\n", j, algo, -ret); goto out; } } else { - ret = wait_async_op(&tresult, crypto_ahash_init(req)); + ret = crypto_wait_req(crypto_ahash_init(req), &wait); if (ret) { pr_err("alg: hash: init failed on test %d " "for %s: ret=%d\n", j, algo, -ret); goto out; } - ret = wait_async_op(&tresult, crypto_ahash_update(req)); + ret = crypto_wait_req(crypto_ahash_update(req), &wait); if (ret) { pr_err("alg: hash: update failed on test %d " "for %s: ret=%d\n", j, algo, -ret); goto out; } - ret = wait_async_op(&tresult, crypto_ahash_final(req)); + ret = crypto_wait_req(crypto_ahash_final(req), &wait); if (ret) { pr_err("alg: hash: final failed on test %d " "for %s: ret=%d\n", j, algo, -ret); @@ -420,22 +394,10 @@ static int __test_hash(struct crypto_ahash *tfm, } ahash_request_set_crypt(req, sg, result, template[i].psize); - ret = crypto_ahash_digest(req); - switch (ret) { - case 0: - break; - case -EINPROGRESS: - case -EBUSY: - wait_for_completion(&tresult.completion); - reinit_completion(&tresult.completion); - ret = tresult.err; - if (!ret) - break; - /* fall through */ - default: - printk(KERN_ERR "alg: hash: digest failed " - "on chunking test %d for %s: " - "ret=%d\n", j, algo, -ret); + ret = crypto_wait_req(crypto_ahash_digest(req), &wait); + if (ret) { + pr_err("alg: hash: digest failed on chunking test %d for %s: ret=%d\n", + j, algo, -ret); goto out; } @@ -486,13 +448,13 @@ static int __test_hash(struct crypto_ahash *tfm, } ahash_request_set_crypt(req, sg, result, template[i].tap[0]); - ret = wait_async_op(&tresult, crypto_ahash_init(req)); + ret = crypto_wait_req(crypto_ahash_init(req), &wait); if (ret) { pr_err("alg: hash: init failed on test %d for %s: ret=%d\n", j, algo, -ret); goto out; } - ret = wait_async_op(&tresult, crypto_ahash_update(req)); + ret = crypto_wait_req(crypto_ahash_update(req), &wait); if (ret) { pr_err("alg: hash: update failed on test %d for %s: ret=%d\n", j, algo, -ret); @@ -503,7 +465,7 @@ static int __test_hash(struct crypto_ahash *tfm, for (k = 1; k < template[i].np; k++) { ret = ahash_partial_update(&req, tfm, &template[i], hash_buff, k, temp, &sg[0], algo, result, - &tresult); + &wait); if (ret) { pr_err("alg: hash: partial update failed on test %d for %s: ret=%d\n", j, algo, -ret); @@ -511,7 +473,7 @@ static int __test_hash(struct crypto_ahash *tfm, } temp += template[i].tap[k]; } - ret = wait_async_op(&tresult, crypto_ahash_final(req)); + ret = crypto_wait_req(crypto_ahash_final(req), &wait); if (ret) { pr_err("alg: hash: final failed on test %d for %s: ret=%d\n", j, algo, -ret); @@ -580,7 +542,7 @@ static int __test_aead(struct crypto_aead *tfm, int enc, struct scatterlist *sg; struct scatterlist *sgout; const char *e, *d; - struct tcrypt_result result; + struct crypto_wait wait; unsigned int authsize, iv_len; void *input; void *output; @@ -619,7 +581,7 @@ static int __test_aead(struct crypto_aead *tfm, int enc, else e = "decryption"; - init_completion(&result.completion); + crypto_init_wait(&wait); req = aead_request_alloc(tfm, GFP_KERNEL); if (!req) { @@ -629,7 +591,7 @@ static int __test_aead(struct crypto_aead *tfm, int enc, } aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, - tcrypt_complete, &result); + crypto_req_done, &wait); iv_len = crypto_aead_ivsize(tfm); @@ -709,7 +671,8 @@ static int __test_aead(struct crypto_aead *tfm, int enc, aead_request_set_ad(req, template[i].alen); - ret = enc ? crypto_aead_encrypt(req) : crypto_aead_decrypt(req); + ret = crypto_wait_req(enc ? crypto_aead_encrypt(req) + : crypto_aead_decrypt(req), &wait); switch (ret) { case 0: @@ -722,13 +685,6 @@ static int __test_aead(struct crypto_aead *tfm, int enc, goto out; } break; - case -EINPROGRESS: - case -EBUSY: - wait_for_completion(&result.completion); - reinit_completion(&result.completion); - ret = result.err; - if (!ret) - break; case -EBADMSG: if (template[i].novrfy) /* verification failure was expected */ @@ -866,7 +822,8 @@ static int __test_aead(struct crypto_aead *tfm, int enc, aead_request_set_ad(req, template[i].alen); - ret = enc ? crypto_aead_encrypt(req) : crypto_aead_decrypt(req); + ret = crypto_wait_req(enc ? crypto_aead_encrypt(req) + : crypto_aead_decrypt(req), &wait); switch (ret) { case 0: @@ -879,13 +836,6 @@ static int __test_aead(struct crypto_aead *tfm, int enc, goto out; } break; - case -EINPROGRESS: - case -EBUSY: - wait_for_completion(&result.completion); - reinit_completion(&result.completion); - ret = result.err; - if (!ret) - break; case -EBADMSG: if (template[i].novrfy) /* verification failure was expected */ @@ -1083,7 +1033,7 @@ static int __test_skcipher(struct crypto_skcipher *tfm, int enc, struct scatterlist sg[8]; struct scatterlist sgout[8]; const char *e, *d; - struct tcrypt_result result; + struct crypto_wait wait; void *data; char iv[MAX_IVLEN]; char *xbuf[XBUFSIZE]; @@ -1107,7 +1057,7 @@ static int __test_skcipher(struct crypto_skcipher *tfm, int enc, else e = "decryption"; - init_completion(&result.completion); + crypto_init_wait(&wait); req = skcipher_request_alloc(tfm, GFP_KERNEL); if (!req) { @@ -1117,7 +1067,7 @@ static int __test_skcipher(struct crypto_skcipher *tfm, int enc, } skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, - tcrypt_complete, &result); + crypto_req_done, &wait); j = 0; for (i = 0; i < tcount; i++) { @@ -1164,21 +1114,10 @@ static int __test_skcipher(struct crypto_skcipher *tfm, int enc, skcipher_request_set_crypt(req, sg, (diff_dst) ? sgout : sg, template[i].ilen, iv); - ret = enc ? crypto_skcipher_encrypt(req) : - crypto_skcipher_decrypt(req); + ret = crypto_wait_req(enc ? crypto_skcipher_encrypt(req) : + crypto_skcipher_decrypt(req), &wait); - switch (ret) { - case 0: - break; - case -EINPROGRESS: - case -EBUSY: - wait_for_completion(&result.completion); - reinit_completion(&result.completion); - ret = result.err; - if (!ret) - break; - /* fall through */ - default: + if (ret) { pr_err("alg: skcipher%s: %s failed on test %d for %s: ret=%d\n", d, e, j, algo, -ret); goto out; @@ -1272,21 +1211,10 @@ static int __test_skcipher(struct crypto_skcipher *tfm, int enc, skcipher_request_set_crypt(req, sg, (diff_dst) ? sgout : sg, template[i].ilen, iv); - ret = enc ? crypto_skcipher_encrypt(req) : - crypto_skcipher_decrypt(req); + ret = crypto_wait_req(enc ? crypto_skcipher_encrypt(req) : + crypto_skcipher_decrypt(req), &wait); - switch (ret) { - case 0: - break; - case -EINPROGRESS: - case -EBUSY: - wait_for_completion(&result.completion); - reinit_completion(&result.completion); - ret = result.err; - if (!ret) - break; - /* fall through */ - default: + if (ret) { pr_err("alg: skcipher%s: %s failed on chunk test %d for %s: ret=%d\n", d, e, j, algo, -ret); goto out; @@ -1462,7 +1390,7 @@ static int test_acomp(struct crypto_acomp *tfm, int ret; struct scatterlist src, dst; struct acomp_req *req; - struct tcrypt_result result; + struct crypto_wait wait; output = kmalloc(COMP_BUF_SIZE, GFP_KERNEL); if (!output) @@ -1486,7 +1414,7 @@ static int test_acomp(struct crypto_acomp *tfm, } memset(output, 0, dlen); - init_completion(&result.completion); + crypto_init_wait(&wait); sg_init_one(&src, input_vec, ilen); sg_init_one(&dst, output, dlen); @@ -1501,9 +1429,9 @@ static int test_acomp(struct crypto_acomp *tfm, acomp_request_set_params(req, &src, &dst, ilen, dlen); acomp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, - tcrypt_complete, &result); + crypto_req_done, &wait); - ret = wait_async_op(&result, crypto_acomp_compress(req)); + ret = crypto_wait_req(crypto_acomp_compress(req), &wait); if (ret) { pr_err("alg: acomp: compression failed on test %d for %s: ret=%d\n", i + 1, algo, -ret); @@ -1516,10 +1444,10 @@ static int test_acomp(struct crypto_acomp *tfm, dlen = COMP_BUF_SIZE; sg_init_one(&src, output, ilen); sg_init_one(&dst, decomp_out, dlen); - init_completion(&result.completion); + crypto_init_wait(&wait); acomp_request_set_params(req, &src, &dst, ilen, dlen); - ret = wait_async_op(&result, crypto_acomp_decompress(req)); + ret = crypto_wait_req(crypto_acomp_decompress(req), &wait); if (ret) { pr_err("alg: acomp: compression failed on test %d for %s: ret=%d\n", i + 1, algo, -ret); @@ -1563,7 +1491,7 @@ static int test_acomp(struct crypto_acomp *tfm, } memset(output, 0, dlen); - init_completion(&result.completion); + crypto_init_wait(&wait); sg_init_one(&src, input_vec, ilen); sg_init_one(&dst, output, dlen); @@ -1578,9 +1506,9 @@ static int test_acomp(struct crypto_acomp *tfm, acomp_request_set_params(req, &src, &dst, ilen, dlen); acomp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, - tcrypt_complete, &result); + crypto_req_done, &wait); - ret = wait_async_op(&result, crypto_acomp_decompress(req)); + ret = crypto_wait_req(crypto_acomp_decompress(req), &wait); if (ret) { pr_err("alg: acomp: decompression failed on test %d for %s: ret=%d\n", i + 1, algo, -ret); @@ -2000,7 +1928,7 @@ static int do_test_kpp(struct crypto_kpp *tfm, const struct kpp_testvec *vec, void *a_public = NULL; void *a_ss = NULL; void *shared_secret = NULL; - struct tcrypt_result result; + struct crypto_wait wait; unsigned int out_len_max; int err = -ENOMEM; struct scatterlist src, dst; @@ -2009,7 +1937,7 @@ static int do_test_kpp(struct crypto_kpp *tfm, const struct kpp_testvec *vec, if (!req) return err; - init_completion(&result.completion); + crypto_init_wait(&wait); err = crypto_kpp_set_secret(tfm, vec->secret, vec->secret_size); if (err < 0) @@ -2027,10 +1955,10 @@ static int do_test_kpp(struct crypto_kpp *tfm, const struct kpp_testvec *vec, sg_init_one(&dst, output_buf, out_len_max); kpp_request_set_output(req, &dst, out_len_max); kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, - tcrypt_complete, &result); + crypto_req_done, &wait); /* Compute party A's public key */ - err = wait_async_op(&result, crypto_kpp_generate_public_key(req)); + err = crypto_wait_req(crypto_kpp_generate_public_key(req), &wait); if (err) { pr_err("alg: %s: Party A: generate public key test failed. err %d\n", alg, err); @@ -2069,8 +1997,8 @@ static int do_test_kpp(struct crypto_kpp *tfm, const struct kpp_testvec *vec, kpp_request_set_input(req, &src, vec->b_public_size); kpp_request_set_output(req, &dst, out_len_max); kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, - tcrypt_complete, &result); - err = wait_async_op(&result, crypto_kpp_compute_shared_secret(req)); + crypto_req_done, &wait); + err = crypto_wait_req(crypto_kpp_compute_shared_secret(req), &wait); if (err) { pr_err("alg: %s: Party A: compute shared secret test failed. err %d\n", alg, err); @@ -2100,9 +2028,9 @@ static int do_test_kpp(struct crypto_kpp *tfm, const struct kpp_testvec *vec, kpp_request_set_input(req, &src, vec->expected_a_public_size); kpp_request_set_output(req, &dst, out_len_max); kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, - tcrypt_complete, &result); - err = wait_async_op(&result, - crypto_kpp_compute_shared_secret(req)); + crypto_req_done, &wait); + err = crypto_wait_req(crypto_kpp_compute_shared_secret(req), + &wait); if (err) { pr_err("alg: %s: Party B: compute shared secret failed. err %d\n", alg, err); @@ -2179,7 +2107,7 @@ static int test_akcipher_one(struct crypto_akcipher *tfm, struct akcipher_request *req; void *outbuf_enc = NULL; void *outbuf_dec = NULL; - struct tcrypt_result result; + struct crypto_wait wait; unsigned int out_len_max, out_len = 0; int err = -ENOMEM; struct scatterlist src, dst, src_tab[2]; @@ -2191,7 +2119,7 @@ static int test_akcipher_one(struct crypto_akcipher *tfm, if (!req) goto free_xbuf; - init_completion(&result.completion); + crypto_init_wait(&wait); if (vecs->public_key_vec) err = crypto_akcipher_set_pub_key(tfm, vecs->key, @@ -2220,13 +2148,13 @@ static int test_akcipher_one(struct crypto_akcipher *tfm, akcipher_request_set_crypt(req, src_tab, &dst, vecs->m_size, out_len_max); akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, - tcrypt_complete, &result); + crypto_req_done, &wait); - err = wait_async_op(&result, vecs->siggen_sigver_test ? - /* Run asymmetric signature generation */ - crypto_akcipher_sign(req) : - /* Run asymmetric encrypt */ - crypto_akcipher_encrypt(req)); + err = crypto_wait_req(vecs->siggen_sigver_test ? + /* Run asymmetric signature generation */ + crypto_akcipher_sign(req) : + /* Run asymmetric encrypt */ + crypto_akcipher_encrypt(req), &wait); if (err) { pr_err("alg: akcipher: encrypt test failed. err %d\n", err); goto free_all; @@ -2261,14 +2189,14 @@ static int test_akcipher_one(struct crypto_akcipher *tfm, sg_init_one(&src, xbuf[0], vecs->c_size); sg_init_one(&dst, outbuf_dec, out_len_max); - init_completion(&result.completion); + crypto_init_wait(&wait); akcipher_request_set_crypt(req, &src, &dst, vecs->c_size, out_len_max); - err = wait_async_op(&result, vecs->siggen_sigver_test ? - /* Run asymmetric signature verification */ - crypto_akcipher_verify(req) : - /* Run asymmetric decrypt */ - crypto_akcipher_decrypt(req)); + err = crypto_wait_req(vecs->siggen_sigver_test ? + /* Run asymmetric signature verification */ + crypto_akcipher_verify(req) : + /* Run asymmetric decrypt */ + crypto_akcipher_decrypt(req), &wait); if (err) { pr_err("alg: akcipher: decrypt test failed. err %d\n", err); goto free_all; -- cgit From 646710419a978c6f82342a2ad5eb28adb5f47bc4 Mon Sep 17 00:00:00 2001 From: Gilad Ben-Yossef Date: Wed, 18 Oct 2017 08:00:48 +0100 Subject: crypto: tcrypt - move to generic async completion tcrypt starts several async crypto ops and waits for their completions. Move it over to generic code doing the same. Signed-off-by: Gilad Ben-Yossef Signed-off-by: Herbert Xu --- crypto/tcrypt.c | 84 +++++++++++++++++---------------------------------------- 1 file changed, 25 insertions(+), 59 deletions(-) (limited to 'crypto') diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index 65d191b27ecc..9267cbdb14d2 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c @@ -79,34 +79,11 @@ static char *check[] = { NULL }; -struct tcrypt_result { - struct completion completion; - int err; -}; - -static void tcrypt_complete(struct crypto_async_request *req, int err) -{ - struct tcrypt_result *res = req->data; - - if (err == -EINPROGRESS) - return; - - res->err = err; - complete(&res->completion); -} - static inline int do_one_aead_op(struct aead_request *req, int ret) { - if (ret == -EINPROGRESS || ret == -EBUSY) { - struct tcrypt_result *tr = req->base.data; + struct crypto_wait *wait = req->base.data; - ret = wait_for_completion_interruptible(&tr->completion); - if (!ret) - ret = tr->err; - reinit_completion(&tr->completion); - } - - return ret; + return crypto_wait_req(ret, wait); } static int test_aead_jiffies(struct aead_request *req, int enc, @@ -248,7 +225,7 @@ static void test_aead_speed(const char *algo, int enc, unsigned int secs, char *axbuf[XBUFSIZE]; unsigned int *b_size; unsigned int iv_len; - struct tcrypt_result result; + struct crypto_wait wait; iv = kzalloc(MAX_IVLEN, GFP_KERNEL); if (!iv) @@ -284,7 +261,7 @@ static void test_aead_speed(const char *algo, int enc, unsigned int secs, goto out_notfm; } - init_completion(&result.completion); + crypto_init_wait(&wait); printk(KERN_INFO "\ntesting speed of %s (%s) %s\n", algo, get_driver_name(crypto_aead, tfm), e); @@ -296,7 +273,7 @@ static void test_aead_speed(const char *algo, int enc, unsigned int secs, } aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, - tcrypt_complete, &result); + crypto_req_done, &wait); i = 0; do { @@ -398,21 +375,16 @@ static void test_hash_sg_init(struct scatterlist *sg) static inline int do_one_ahash_op(struct ahash_request *req, int ret) { - if (ret == -EINPROGRESS || ret == -EBUSY) { - struct tcrypt_result *tr = req->base.data; + struct crypto_wait *wait = req->base.data; - wait_for_completion(&tr->completion); - reinit_completion(&tr->completion); - ret = tr->err; - } - return ret; + return crypto_wait_req(ret, wait); } struct test_mb_ahash_data { struct scatterlist sg[TVMEMSIZE]; char result[64]; struct ahash_request *req; - struct tcrypt_result tresult; + struct crypto_wait wait; char *xbuf[XBUFSIZE]; }; @@ -441,7 +413,7 @@ static void test_mb_ahash_speed(const char *algo, unsigned int sec, if (testmgr_alloc_buf(data[i].xbuf)) goto out; - init_completion(&data[i].tresult.completion); + crypto_init_wait(&data[i].wait); data[i].req = ahash_request_alloc(tfm, GFP_KERNEL); if (!data[i].req) { @@ -450,8 +422,8 @@ static void test_mb_ahash_speed(const char *algo, unsigned int sec, goto out; } - ahash_request_set_callback(data[i].req, 0, - tcrypt_complete, &data[i].tresult); + ahash_request_set_callback(data[i].req, 0, crypto_req_done, + &data[i].wait); test_hash_sg_init(data[i].sg); } @@ -493,16 +465,16 @@ static void test_mb_ahash_speed(const char *algo, unsigned int sec, if (ret) break; - complete(&data[k].tresult.completion); - data[k].tresult.err = 0; + crypto_req_done(&data[k].req->base, 0); } for (j = 0; j < k; j++) { - struct tcrypt_result *tr = &data[j].tresult; + struct crypto_wait *wait = &data[j].wait; + int wait_ret; - wait_for_completion(&tr->completion); - if (tr->err) - ret = tr->err; + wait_ret = crypto_wait_req(-EINPROGRESS, wait); + if (wait_ret) + ret = wait_ret; } end = get_cycles(); @@ -680,7 +652,7 @@ static void test_ahash_speed_common(const char *algo, unsigned int secs, struct hash_speed *speed, unsigned mask) { struct scatterlist sg[TVMEMSIZE]; - struct tcrypt_result tresult; + struct crypto_wait wait; struct ahash_request *req; struct crypto_ahash *tfm; char *output; @@ -709,9 +681,9 @@ static void test_ahash_speed_common(const char *algo, unsigned int secs, goto out; } - init_completion(&tresult.completion); + crypto_init_wait(&wait); ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, - tcrypt_complete, &tresult); + crypto_req_done, &wait); output = kmalloc(MAX_DIGEST_SIZE, GFP_KERNEL); if (!output) @@ -766,15 +738,9 @@ static void test_hash_speed(const char *algo, unsigned int secs, static inline int do_one_acipher_op(struct skcipher_request *req, int ret) { - if (ret == -EINPROGRESS || ret == -EBUSY) { - struct tcrypt_result *tr = req->base.data; - - wait_for_completion(&tr->completion); - reinit_completion(&tr->completion); - ret = tr->err; - } + struct crypto_wait *wait = req->base.data; - return ret; + return crypto_wait_req(ret, wait); } static int test_acipher_jiffies(struct skcipher_request *req, int enc, @@ -854,7 +820,7 @@ static void test_skcipher_speed(const char *algo, int enc, unsigned int secs, unsigned int tcount, u8 *keysize, bool async) { unsigned int ret, i, j, k, iv_len; - struct tcrypt_result tresult; + struct crypto_wait wait; const char *key; char iv[128]; struct skcipher_request *req; @@ -867,7 +833,7 @@ static void test_skcipher_speed(const char *algo, int enc, unsigned int secs, else e = "decryption"; - init_completion(&tresult.completion); + crypto_init_wait(&wait); tfm = crypto_alloc_skcipher(algo, 0, async ? 0 : CRYPTO_ALG_ASYNC); @@ -888,7 +854,7 @@ static void test_skcipher_speed(const char *algo, int enc, unsigned int secs, } skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, - tcrypt_complete, &tresult); + crypto_req_done, &wait); i = 0; do { -- cgit From f560acc3bbb05a6e974ea245562c94eb5d344768 Mon Sep 17 00:00:00 2001 From: Tudor-Dan Ambarus Date: Thu, 2 Nov 2017 16:46:47 +0200 Subject: crypto: ecdh - remove empty exit() Pointer members of an object with static storage duration, if not explicitly initialized, will be initialized to a NULL pointer. The crypto API checks if this pointer is not NULL before using it, we are safe to remove the function. Signed-off-by: Tudor Ambarus Signed-off-by: Herbert Xu --- crypto/ecdh.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'crypto') diff --git a/crypto/ecdh.c b/crypto/ecdh.c index 4271fc77d261..3aca0933ec44 100644 --- a/crypto/ecdh.c +++ b/crypto/ecdh.c @@ -131,17 +131,11 @@ static unsigned int ecdh_max_size(struct crypto_kpp *tfm) return ctx->ndigits << (ECC_DIGITS_TO_BYTES_SHIFT + 1); } -static void no_exit_tfm(struct crypto_kpp *tfm) -{ - return; -} - static struct kpp_alg ecdh = { .set_secret = ecdh_set_secret, .generate_public_key = ecdh_compute_value, .compute_shared_secret = ecdh_compute_value, .max_size = ecdh_max_size, - .exit = no_exit_tfm, .base = { .cra_name = "ecdh", .cra_driver_name = "ecdh-generic", -- cgit From 12d41a023efb01b846457ccdbbcbe2b65a87d530 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 5 Nov 2017 18:30:44 -0800 Subject: crypto: dh - Fix double free of ctx->p When setting the secret with the software Diffie-Hellman implementation, if allocating 'g' failed (e.g. if it was longer than MAX_EXTERN_MPI_BITS), then 'p' was freed twice: once immediately, and once later when the crypto_kpp tfm was destroyed. Fix it by using dh_free_ctx() (renamed to dh_clear_ctx()) in the error paths, as that correctly sets the pointers to NULL. KASAN report: MPI: mpi too large (32760 bits) ================================================================== BUG: KASAN: use-after-free in mpi_free+0x131/0x170 Read of size 4 at addr ffff88006c7cdf90 by task reproduce_doubl/367 CPU: 1 PID: 367 Comm: reproduce_doubl Not tainted 4.14.0-rc7-00040-g05298abde6fe #7 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 Call Trace: dump_stack+0xb3/0x10b ? mpi_free+0x131/0x170 print_address_description+0x79/0x2a0 ? mpi_free+0x131/0x170 kasan_report+0x236/0x340 ? akcipher_register_instance+0x90/0x90 __asan_report_load4_noabort+0x14/0x20 mpi_free+0x131/0x170 ? akcipher_register_instance+0x90/0x90 dh_exit_tfm+0x3d/0x140 crypto_kpp_exit_tfm+0x52/0x70 crypto_destroy_tfm+0xb3/0x250 __keyctl_dh_compute+0x640/0xe90 ? kasan_slab_free+0x12f/0x180 ? dh_data_from_key+0x240/0x240 ? key_create_or_update+0x1ee/0xb20 ? key_instantiate_and_link+0x440/0x440 ? lock_contended+0xee0/0xee0 ? kfree+0xcf/0x210 ? SyS_add_key+0x268/0x340 keyctl_dh_compute+0xb3/0xf1 ? __keyctl_dh_compute+0xe90/0xe90 ? SyS_add_key+0x26d/0x340 ? entry_SYSCALL_64_fastpath+0x5/0xbe ? trace_hardirqs_on_caller+0x3f4/0x560 SyS_keyctl+0x72/0x2c0 entry_SYSCALL_64_fastpath+0x1f/0xbe RIP: 0033:0x43ccf9 RSP: 002b:00007ffeeec96158 EFLAGS: 00000246 ORIG_RAX: 00000000000000fa RAX: ffffffffffffffda RBX: 000000000248b9b9 RCX: 000000000043ccf9 RDX: 00007ffeeec96170 RSI: 00007ffeeec96160 RDI: 0000000000000017 RBP: 0000000000000046 R08: 0000000000000000 R09: 0248b9b9143dc936 R10: 0000000000001000 R11: 0000000000000246 R12: 0000000000000000 R13: 0000000000409670 R14: 0000000000409700 R15: 0000000000000000 Allocated by task 367: save_stack_trace+0x16/0x20 kasan_kmalloc+0xeb/0x180 kmem_cache_alloc_trace+0x114/0x300 mpi_alloc+0x4b/0x230 mpi_read_raw_data+0xbe/0x360 dh_set_secret+0x1dc/0x460 __keyctl_dh_compute+0x623/0xe90 keyctl_dh_compute+0xb3/0xf1 SyS_keyctl+0x72/0x2c0 entry_SYSCALL_64_fastpath+0x1f/0xbe Freed by task 367: save_stack_trace+0x16/0x20 kasan_slab_free+0xab/0x180 kfree+0xb5/0x210 mpi_free+0xcb/0x170 dh_set_secret+0x2d7/0x460 __keyctl_dh_compute+0x623/0xe90 keyctl_dh_compute+0xb3/0xf1 SyS_keyctl+0x72/0x2c0 entry_SYSCALL_64_fastpath+0x1f/0xbe Fixes: 802c7f1c84e4 ("crypto: dh - Add DH software implementation") Cc: # v4.8+ Signed-off-by: Eric Biggers Reviewed-by: Tudor Ambarus Signed-off-by: Herbert Xu --- crypto/dh.c | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) (limited to 'crypto') diff --git a/crypto/dh.c b/crypto/dh.c index b1032a5c1bfa..aadaf36fb56f 100644 --- a/crypto/dh.c +++ b/crypto/dh.c @@ -21,19 +21,12 @@ struct dh_ctx { MPI xa; }; -static inline void dh_clear_params(struct dh_ctx *ctx) +static void dh_clear_ctx(struct dh_ctx *ctx) { mpi_free(ctx->p); mpi_free(ctx->g); - ctx->p = NULL; - ctx->g = NULL; -} - -static void dh_free_ctx(struct dh_ctx *ctx) -{ - dh_clear_params(ctx); mpi_free(ctx->xa); - ctx->xa = NULL; + memset(ctx, 0, sizeof(*ctx)); } /* @@ -71,10 +64,8 @@ static int dh_set_params(struct dh_ctx *ctx, struct dh *params) return -EINVAL; ctx->g = mpi_read_raw_data(params->g, params->g_size); - if (!ctx->g) { - mpi_free(ctx->p); + if (!ctx->g) return -EINVAL; - } return 0; } @@ -86,21 +77,23 @@ static int dh_set_secret(struct crypto_kpp *tfm, const void *buf, struct dh params; /* Free the old MPI key if any */ - dh_free_ctx(ctx); + dh_clear_ctx(ctx); if (crypto_dh_decode_key(buf, len, ¶ms) < 0) - return -EINVAL; + goto err_clear_ctx; if (dh_set_params(ctx, ¶ms) < 0) - return -EINVAL; + goto err_clear_ctx; ctx->xa = mpi_read_raw_data(params.key, params.key_size); - if (!ctx->xa) { - dh_clear_params(ctx); - return -EINVAL; - } + if (!ctx->xa) + goto err_clear_ctx; return 0; + +err_clear_ctx: + dh_clear_ctx(ctx); + return -EINVAL; } static int dh_compute_value(struct kpp_request *req) @@ -158,7 +151,7 @@ static void dh_exit_tfm(struct crypto_kpp *tfm) { struct dh_ctx *ctx = dh_get_ctx(tfm); - dh_free_ctx(ctx); + dh_clear_ctx(ctx); } static struct kpp_alg dh = { -- cgit From 199512b1234f09e44d592153ec82b44212b2f0c4 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 5 Nov 2017 18:30:45 -0800 Subject: crypto: dh - Don't permit 'p' to be 0 If 'p' is 0 for the software Diffie-Hellman implementation, then dh_max_size() returns 0. In the case of KEYCTL_DH_COMPUTE, this causes ZERO_SIZE_PTR to be passed to sg_init_one(), which with CONFIG_DEBUG_SG=y triggers the 'BUG_ON(!virt_addr_valid(buf));' in sg_set_buf(). Fix this by making crypto_dh_decode_key() reject 0 for 'p'. p=0 makes no sense for any DH implementation because 'p' is supposed to be a prime number. Moreover, 'mod 0' is not mathematically defined. Bug report: kernel BUG at ./include/linux/scatterlist.h:140! invalid opcode: 0000 [#1] SMP KASAN CPU: 0 PID: 27112 Comm: syz-executor2 Not tainted 4.14.0-rc7-00010-gf5dbb5d0ce32-dirty #7 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.3-20171021_125229-anatol 04/01/2014 task: ffff88006caac0c0 task.stack: ffff88006c7c8000 RIP: 0010:sg_set_buf include/linux/scatterlist.h:140 [inline] RIP: 0010:sg_init_one+0x1b3/0x240 lib/scatterlist.c:156 RSP: 0018:ffff88006c7cfb08 EFLAGS: 00010216 RAX: 0000000000010000 RBX: ffff88006c7cfe30 RCX: 00000000000064ee RDX: ffffffff81cf64c3 RSI: ffffc90000d72000 RDI: ffffffff92e937e0 RBP: ffff88006c7cfb30 R08: ffffed000d8f9fab R09: ffff88006c7cfd30 R10: 0000000000000005 R11: ffffed000d8f9faa R12: ffff88006c7cfd30 R13: 0000000000000000 R14: 0000000000000010 R15: ffff88006c7cfc50 FS: 00007fce190fa700(0000) GS:ffff88003ea00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007fffc6b33db8 CR3: 000000003cf64000 CR4: 00000000000006f0 Call Trace: __keyctl_dh_compute+0xa95/0x19b0 security/keys/dh.c:360 keyctl_dh_compute+0xac/0x100 security/keys/dh.c:434 SYSC_keyctl security/keys/keyctl.c:1745 [inline] SyS_keyctl+0x72/0x2c0 security/keys/keyctl.c:1641 entry_SYSCALL_64_fastpath+0x1f/0xbe RIP: 0033:0x4585c9 RSP: 002b:00007fce190f9bd8 EFLAGS: 00000216 ORIG_RAX: 00000000000000fa RAX: ffffffffffffffda RBX: 0000000000738020 RCX: 00000000004585c9 RDX: 000000002000d000 RSI: 0000000020000ff4 RDI: 0000000000000017 RBP: 0000000000000046 R08: 0000000020008000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000216 R12: 00007fff6e610cde R13: 00007fff6e610cdf R14: 00007fce190fa700 R15: 0000000000000000 Code: 03 0f b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 04 84 d2 75 33 5b 45 89 6c 24 14 41 5c 41 5d 41 5e 41 5f 5d c3 e8 fd 8f 68 ff <0f> 0b e8 f6 8f 68 ff 0f 0b e8 ef 8f 68 ff 0f 0b e8 e8 8f 68 ff 20 RIP: sg_set_buf include/linux/scatterlist.h:140 [inline] RSP: ffff88006c7cfb08 RIP: sg_init_one+0x1b3/0x240 lib/scatterlist.c:156 RSP: ffff88006c7cfb08 Fixes: 802c7f1c84e4 ("crypto: dh - Add DH software implementation") Cc: # v4.8+ Reviewed-by: Tudor Ambarus Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/dh_helper.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'crypto') diff --git a/crypto/dh_helper.c b/crypto/dh_helper.c index a413b311e568..788a9e572918 100644 --- a/crypto/dh_helper.c +++ b/crypto/dh_helper.c @@ -90,6 +90,14 @@ int crypto_dh_decode_key(const char *buf, unsigned int len, struct dh *params) params->p = (void *)(ptr + params->key_size); params->g = (void *)(ptr + params->key_size + params->p_size); + /* + * Don't permit 'p' to be 0. It's not a prime number, and it's subject + * to corner cases such as 'mod 0' being undefined or + * crypto_kpp_maxsize() returning 0. + */ + if (memchr_inv(params->p, 0, params->p_size) == NULL) + return -EINVAL; + return 0; } EXPORT_SYMBOL_GPL(crypto_dh_decode_key); -- cgit From ccd9888f14a8019c0bbdeeae758aba1f58693712 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 5 Nov 2017 18:30:46 -0800 Subject: crypto: dh - Don't permit 'key' or 'g' size longer than 'p' The "qat-dh" DH implementation assumes that 'key' and 'g' can be copied into a buffer with size 'p_size'. However it was never checked that that was actually the case, which most likely allowed users to cause a buffer underflow via KEYCTL_DH_COMPUTE. Fix this by updating crypto_dh_decode_key() to verify this precondition for all DH implementations. Fixes: c9839143ebbf ("crypto: qat - Add DH support") Cc: # v4.8+ Signed-off-by: Eric Biggers Reviewed-by: Tudor Ambarus Signed-off-by: Herbert Xu --- crypto/dh_helper.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'crypto') diff --git a/crypto/dh_helper.c b/crypto/dh_helper.c index 788a9e572918..24fdb2ecaa85 100644 --- a/crypto/dh_helper.c +++ b/crypto/dh_helper.c @@ -83,6 +83,14 @@ int crypto_dh_decode_key(const char *buf, unsigned int len, struct dh *params) if (secret.len != crypto_dh_key_len(params)) return -EINVAL; + /* + * Don't permit the buffer for 'key' or 'g' to be larger than 'p', since + * some drivers assume otherwise. + */ + if (params->key_size > params->p_size || + params->g_size > params->p_size) + return -EINVAL; + /* Don't allocate memory. Set pointers to data within * the given buffer */ -- cgit From ced6a58638432c9f731184f908208d539725ba82 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 5 Nov 2017 18:30:48 -0800 Subject: crypto: dh - Remove pointless checks for NULL 'p' and 'g' Neither 'p' nor 'g' can be NULL, as they were unpacked using crypto_dh_decode_key(). And it makes no sense for them to be optional. So remove the NULL checks that were copy-and-pasted into both modules. Signed-off-by: Eric Biggers Reviewed-by: Tudor Ambarus Signed-off-by: Herbert Xu --- crypto/dh.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'crypto') diff --git a/crypto/dh.c b/crypto/dh.c index aadaf36fb56f..5659fe7f446d 100644 --- a/crypto/dh.c +++ b/crypto/dh.c @@ -53,9 +53,6 @@ static int dh_check_params_length(unsigned int p_len) static int dh_set_params(struct dh_ctx *ctx, struct dh *params) { - if (unlikely(!params->p || !params->g)) - return -EINVAL; - if (dh_check_params_length(params->p_size << 3)) return -EINVAL; -- cgit