diff options
Diffstat (limited to 'lib/crypto')
-rw-r--r-- | lib/crypto/Kconfig | 8 | ||||
-rw-r--r-- | lib/crypto/Makefile | 9 | ||||
-rw-r--r-- | lib/crypto/blake2s-selftest.c | 41 | ||||
-rw-r--r-- | lib/crypto/blake2s.c | 37 | ||||
-rw-r--r-- | lib/crypto/sha1.c | 140 | ||||
-rw-r--r-- | lib/crypto/sm3.c | 246 | ||||
-rw-r--r-- | lib/crypto/sm4.c | 176 |
7 files changed, 217 insertions, 440 deletions
diff --git a/lib/crypto/Kconfig b/lib/crypto/Kconfig index 379a66d7f504..9ff549f63540 100644 --- a/lib/crypto/Kconfig +++ b/lib/crypto/Kconfig @@ -71,6 +71,7 @@ config CRYPTO_LIB_CURVE25519 tristate "Curve25519 scalar multiplication library" depends on CRYPTO_ARCH_HAVE_LIB_CURVE25519 || !CRYPTO_ARCH_HAVE_LIB_CURVE25519 select CRYPTO_LIB_CURVE25519_GENERIC if CRYPTO_ARCH_HAVE_LIB_CURVE25519=n + select LIB_MEMNEQ help Enable the Curve25519 library interface. This interface may be fulfilled by either the generic implementation or an arch-specific @@ -120,13 +121,10 @@ config CRYPTO_LIB_CHACHA20POLY1305 select CRYPTO_LIB_POLY1305 select CRYPTO_ALGAPI -config CRYPTO_LIB_SHA256 - tristate - -config CRYPTO_LIB_SM3 +config CRYPTO_LIB_SHA1 tristate -config CRYPTO_LIB_SM4 +config CRYPTO_LIB_SHA256 tristate endmenu diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile index 6c872d05d1e6..919cbb2c220d 100644 --- a/lib/crypto/Makefile +++ b/lib/crypto/Makefile @@ -34,15 +34,12 @@ libpoly1305-y := poly1305-donna32.o libpoly1305-$(CONFIG_ARCH_SUPPORTS_INT128) := poly1305-donna64.o libpoly1305-y += poly1305.o +obj-$(CONFIG_CRYPTO_LIB_SHA1) += libsha1.o +libsha1-y := sha1.o + obj-$(CONFIG_CRYPTO_LIB_SHA256) += libsha256.o libsha256-y := sha256.o -obj-$(CONFIG_CRYPTO_LIB_SM3) += libsm3.o -libsm3-y := sm3.o - -obj-$(CONFIG_CRYPTO_LIB_SM4) += libsm4.o -libsm4-y := sm4.o - ifneq ($(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS),y) libblake2s-y += blake2s-selftest.o libchacha20poly1305-y += chacha20poly1305-selftest.o diff --git a/lib/crypto/blake2s-selftest.c b/lib/crypto/blake2s-selftest.c index 409e4b728770..7d77dea15587 100644 --- a/lib/crypto/blake2s-selftest.c +++ b/lib/crypto/blake2s-selftest.c @@ -4,6 +4,8 @@ */ #include <crypto/internal/blake2s.h> +#include <linux/kernel.h> +#include <linux/random.h> #include <linux/string.h> /* @@ -587,5 +589,44 @@ bool __init blake2s_selftest(void) } } + for (i = 0; i < 32; ++i) { + enum { TEST_ALIGNMENT = 16 }; + u8 unaligned_block[BLAKE2S_BLOCK_SIZE + TEST_ALIGNMENT - 1] + __aligned(TEST_ALIGNMENT); + u8 blocks[BLAKE2S_BLOCK_SIZE * 2]; + struct blake2s_state state1, state2; + + get_random_bytes(blocks, sizeof(blocks)); + get_random_bytes(&state, sizeof(state)); + +#if defined(CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC) && \ + defined(CONFIG_CRYPTO_ARCH_HAVE_LIB_BLAKE2S) + memcpy(&state1, &state, sizeof(state1)); + memcpy(&state2, &state, sizeof(state2)); + blake2s_compress(&state1, blocks, 2, BLAKE2S_BLOCK_SIZE); + blake2s_compress_generic(&state2, blocks, 2, BLAKE2S_BLOCK_SIZE); + if (memcmp(&state1, &state2, sizeof(state1))) { + pr_err("blake2s random compress self-test %d: FAIL\n", + i + 1); + success = false; + } +#endif + + memcpy(&state1, &state, sizeof(state1)); + blake2s_compress(&state1, blocks, 1, BLAKE2S_BLOCK_SIZE); + for (l = 1; l < TEST_ALIGNMENT; ++l) { + memcpy(unaligned_block + l, blocks, + BLAKE2S_BLOCK_SIZE); + memcpy(&state2, &state, sizeof(state2)); + blake2s_compress(&state2, unaligned_block + l, 1, + BLAKE2S_BLOCK_SIZE); + if (memcmp(&state1, &state2, sizeof(state1))) { + pr_err("blake2s random compress align %d self-test %d: FAIL\n", + l, i + 1); + success = false; + } + } + } + return success; } diff --git a/lib/crypto/blake2s.c b/lib/crypto/blake2s.c index c71c09621c09..98e688c6d891 100644 --- a/lib/crypto/blake2s.c +++ b/lib/crypto/blake2s.c @@ -16,16 +16,44 @@ #include <linux/init.h> #include <linux/bug.h> +static inline void blake2s_set_lastblock(struct blake2s_state *state) +{ + state->f[0] = -1; +} + void blake2s_update(struct blake2s_state *state, const u8 *in, size_t inlen) { - __blake2s_update(state, in, inlen, false); + const size_t fill = BLAKE2S_BLOCK_SIZE - state->buflen; + + if (unlikely(!inlen)) + return; + if (inlen > fill) { + memcpy(state->buf + state->buflen, in, fill); + blake2s_compress(state, state->buf, 1, BLAKE2S_BLOCK_SIZE); + state->buflen = 0; + in += fill; + inlen -= fill; + } + if (inlen > BLAKE2S_BLOCK_SIZE) { + const size_t nblocks = DIV_ROUND_UP(inlen, BLAKE2S_BLOCK_SIZE); + blake2s_compress(state, in, nblocks - 1, BLAKE2S_BLOCK_SIZE); + in += BLAKE2S_BLOCK_SIZE * (nblocks - 1); + inlen -= BLAKE2S_BLOCK_SIZE * (nblocks - 1); + } + memcpy(state->buf + state->buflen, in, inlen); + state->buflen += inlen; } EXPORT_SYMBOL(blake2s_update); void blake2s_final(struct blake2s_state *state, u8 *out) { WARN_ON(IS_ENABLED(DEBUG) && !out); - __blake2s_final(state, out, false); + blake2s_set_lastblock(state); + memset(state->buf + state->buflen, 0, + BLAKE2S_BLOCK_SIZE - state->buflen); /* Padding */ + blake2s_compress(state, state->buf, 1, state->buflen); + cpu_to_le32_array(state->h, ARRAY_SIZE(state->h)); + memcpy(out, state->h, state->outlen); memzero_explicit(state, sizeof(*state)); } EXPORT_SYMBOL(blake2s_final); @@ -38,12 +66,7 @@ static int __init blake2s_mod_init(void) return 0; } -static void __exit blake2s_mod_exit(void) -{ -} - module_init(blake2s_mod_init); -module_exit(blake2s_mod_exit); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("BLAKE2s hash function"); MODULE_AUTHOR("Jason A. Donenfeld <Jason@zx2c4.com>"); diff --git a/lib/crypto/sha1.c b/lib/crypto/sha1.c new file mode 100644 index 000000000000..1aebe7be9401 --- /dev/null +++ b/lib/crypto/sha1.c @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * SHA1 routine optimized to do word accesses rather than byte accesses, + * and to avoid unnecessary copies into the context array. + * + * This was based on the git SHA1 implementation. + */ + +#include <linux/kernel.h> +#include <linux/export.h> +#include <linux/module.h> +#include <linux/bitops.h> +#include <linux/string.h> +#include <crypto/sha1.h> +#include <asm/unaligned.h> + +/* + * If you have 32 registers or more, the compiler can (and should) + * try to change the array[] accesses into registers. However, on + * machines with less than ~25 registers, that won't really work, + * and at least gcc will make an unholy mess of it. + * + * So to avoid that mess which just slows things down, we force + * the stores to memory to actually happen (we might be better off + * with a 'W(t)=(val);asm("":"+m" (W(t))' there instead, as + * suggested by Artur Skawina - that will also make gcc unable to + * try to do the silly "optimize away loads" part because it won't + * see what the value will be). + * + * Ben Herrenschmidt reports that on PPC, the C version comes close + * to the optimized asm with this (ie on PPC you don't want that + * 'volatile', since there are lots of registers). + * + * On ARM we get the best code generation by forcing a full memory barrier + * between each SHA_ROUND, otherwise gcc happily get wild with spilling and + * the stack frame size simply explode and performance goes down the drain. + */ + +#ifdef CONFIG_X86 + #define setW(x, val) (*(volatile __u32 *)&W(x) = (val)) +#elif defined(CONFIG_ARM) + #define setW(x, val) do { W(x) = (val); __asm__("":::"memory"); } while (0) +#else + #define setW(x, val) (W(x) = (val)) +#endif + +/* This "rolls" over the 512-bit array */ +#define W(x) (array[(x)&15]) + +/* + * Where do we get the source from? The first 16 iterations get it from + * the input data, the next mix it from the 512-bit array. + */ +#define SHA_SRC(t) get_unaligned_be32((__u32 *)data + t) +#define SHA_MIX(t) rol32(W(t+13) ^ W(t+8) ^ W(t+2) ^ W(t), 1) + +#define SHA_ROUND(t, input, fn, constant, A, B, C, D, E) do { \ + __u32 TEMP = input(t); setW(t, TEMP); \ + E += TEMP + rol32(A,5) + (fn) + (constant); \ + B = ror32(B, 2); \ + TEMP = E; E = D; D = C; C = B; B = A; A = TEMP; } while (0) + +#define T_0_15(t, A, B, C, D, E) SHA_ROUND(t, SHA_SRC, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E ) +#define T_16_19(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (((C^D)&B)^D) , 0x5a827999, A, B, C, D, E ) +#define T_20_39(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (B^C^D) , 0x6ed9eba1, A, B, C, D, E ) +#define T_40_59(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, ((B&C)+(D&(B^C))) , 0x8f1bbcdc, A, B, C, D, E ) +#define T_60_79(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (B^C^D) , 0xca62c1d6, A, B, C, D, E ) + +/** + * sha1_transform - single block SHA1 transform (deprecated) + * + * @digest: 160 bit digest to update + * @data: 512 bits of data to hash + * @array: 16 words of workspace (see note) + * + * This function executes SHA-1's internal compression function. It updates the + * 160-bit internal state (@digest) with a single 512-bit data block (@data). + * + * Don't use this function. SHA-1 is no longer considered secure. And even if + * you do have to use SHA-1, this isn't the correct way to hash something with + * SHA-1 as this doesn't handle padding and finalization. + * + * Note: If the hash is security sensitive, the caller should be sure + * to clear the workspace. This is left to the caller to avoid + * unnecessary clears between chained hashing operations. + */ +void sha1_transform(__u32 *digest, const char *data, __u32 *array) +{ + __u32 A, B, C, D, E; + unsigned int i = 0; + + A = digest[0]; + B = digest[1]; + C = digest[2]; + D = digest[3]; + E = digest[4]; + + /* Round 1 - iterations 0-16 take their input from 'data' */ + for (; i < 16; ++i) + T_0_15(i, A, B, C, D, E); + + /* Round 1 - tail. Input from 512-bit mixing array */ + for (; i < 20; ++i) + T_16_19(i, A, B, C, D, E); + + /* Round 2 */ + for (; i < 40; ++i) + T_20_39(i, A, B, C, D, E); + + /* Round 3 */ + for (; i < 60; ++i) + T_40_59(i, A, B, C, D, E); + + /* Round 4 */ + for (; i < 80; ++i) + T_60_79(i, A, B, C, D, E); + + digest[0] += A; + digest[1] += B; + digest[2] += C; + digest[3] += D; + digest[4] += E; +} +EXPORT_SYMBOL(sha1_transform); + +/** + * sha1_init - initialize the vectors for a SHA1 digest + * @buf: vector to initialize + */ +void sha1_init(__u32 *buf) +{ + buf[0] = 0x67452301; + buf[1] = 0xefcdab89; + buf[2] = 0x98badcfe; + buf[3] = 0x10325476; + buf[4] = 0xc3d2e1f0; +} +EXPORT_SYMBOL(sha1_init); + +MODULE_LICENSE("GPL"); diff --git a/lib/crypto/sm3.c b/lib/crypto/sm3.c deleted file mode 100644 index d473e358a873..000000000000 --- a/lib/crypto/sm3.c +++ /dev/null @@ -1,246 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * SM3 secure hash, as specified by OSCCA GM/T 0004-2012 SM3 and described - * at https://datatracker.ietf.org/doc/html/draft-sca-cfrg-sm3-02 - * - * Copyright (C) 2017 ARM Limited or its affiliates. - * Copyright (C) 2017 Gilad Ben-Yossef <gilad@benyossef.com> - * Copyright (C) 2021 Tianjia Zhang <tianjia.zhang@linux.alibaba.com> - */ - -#include <linux/module.h> -#include <asm/unaligned.h> -#include <crypto/sm3.h> - -static const u32 ____cacheline_aligned K[64] = { - 0x79cc4519, 0xf3988a32, 0xe7311465, 0xce6228cb, - 0x9cc45197, 0x3988a32f, 0x7311465e, 0xe6228cbc, - 0xcc451979, 0x988a32f3, 0x311465e7, 0x6228cbce, - 0xc451979c, 0x88a32f39, 0x11465e73, 0x228cbce6, - 0x9d8a7a87, 0x3b14f50f, 0x7629ea1e, 0xec53d43c, - 0xd8a7a879, 0xb14f50f3, 0x629ea1e7, 0xc53d43ce, - 0x8a7a879d, 0x14f50f3b, 0x29ea1e76, 0x53d43cec, - 0xa7a879d8, 0x4f50f3b1, 0x9ea1e762, 0x3d43cec5, - 0x7a879d8a, 0xf50f3b14, 0xea1e7629, 0xd43cec53, - 0xa879d8a7, 0x50f3b14f, 0xa1e7629e, 0x43cec53d, - 0x879d8a7a, 0x0f3b14f5, 0x1e7629ea, 0x3cec53d4, - 0x79d8a7a8, 0xf3b14f50, 0xe7629ea1, 0xcec53d43, - 0x9d8a7a87, 0x3b14f50f, 0x7629ea1e, 0xec53d43c, - 0xd8a7a879, 0xb14f50f3, 0x629ea1e7, 0xc53d43ce, - 0x8a7a879d, 0x14f50f3b, 0x29ea1e76, 0x53d43cec, - 0xa7a879d8, 0x4f50f3b1, 0x9ea1e762, 0x3d43cec5 -}; - -/* - * Transform the message X which consists of 16 32-bit-words. See - * GM/T 004-2012 for details. - */ -#define R(i, a, b, c, d, e, f, g, h, t, w1, w2) \ - do { \ - ss1 = rol32((rol32((a), 12) + (e) + (t)), 7); \ - ss2 = ss1 ^ rol32((a), 12); \ - d += FF ## i(a, b, c) + ss2 + ((w1) ^ (w2)); \ - h += GG ## i(e, f, g) + ss1 + (w1); \ - b = rol32((b), 9); \ - f = rol32((f), 19); \ - h = P0((h)); \ - } while (0) - -#define R1(a, b, c, d, e, f, g, h, t, w1, w2) \ - R(1, a, b, c, d, e, f, g, h, t, w1, w2) -#define R2(a, b, c, d, e, f, g, h, t, w1, w2) \ - R(2, a, b, c, d, e, f, g, h, t, w1, w2) - -#define FF1(x, y, z) (x ^ y ^ z) -#define FF2(x, y, z) ((x & y) | (x & z) | (y & z)) - -#define GG1(x, y, z) FF1(x, y, z) -#define GG2(x, y, z) ((x & y) | (~x & z)) - -/* Message expansion */ -#define P0(x) ((x) ^ rol32((x), 9) ^ rol32((x), 17)) -#define P1(x) ((x) ^ rol32((x), 15) ^ rol32((x), 23)) -#define I(i) (W[i] = get_unaligned_be32(data + i * 4)) -#define W1(i) (W[i & 0x0f]) -#define W2(i) (W[i & 0x0f] = \ - P1(W[i & 0x0f] \ - ^ W[(i-9) & 0x0f] \ - ^ rol32(W[(i-3) & 0x0f], 15)) \ - ^ rol32(W[(i-13) & 0x0f], 7) \ - ^ W[(i-6) & 0x0f]) - -static void sm3_transform(struct sm3_state *sctx, u8 const *data, u32 W[16]) -{ - u32 a, b, c, d, e, f, g, h, ss1, ss2; - - a = sctx->state[0]; - b = sctx->state[1]; - c = sctx->state[2]; - d = sctx->state[3]; - e = sctx->state[4]; - f = sctx->state[5]; - g = sctx->state[6]; - h = sctx->state[7]; - - R1(a, b, c, d, e, f, g, h, K[0], I(0), I(4)); - R1(d, a, b, c, h, e, f, g, K[1], I(1), I(5)); - R1(c, d, a, b, g, h, e, f, K[2], I(2), I(6)); - R1(b, c, d, a, f, g, h, e, K[3], I(3), I(7)); - R1(a, b, c, d, e, f, g, h, K[4], W1(4), I(8)); - R1(d, a, b, c, h, e, f, g, K[5], W1(5), I(9)); - R1(c, d, a, b, g, h, e, f, K[6], W1(6), I(10)); - R1(b, c, d, a, f, g, h, e, K[7], W1(7), I(11)); - R1(a, b, c, d, e, f, g, h, K[8], W1(8), I(12)); - R1(d, a, b, c, h, e, f, g, K[9], W1(9), I(13)); - R1(c, d, a, b, g, h, e, f, K[10], W1(10), I(14)); - R1(b, c, d, a, f, g, h, e, K[11], W1(11), I(15)); - R1(a, b, c, d, e, f, g, h, K[12], W1(12), W2(16)); - R1(d, a, b, c, h, e, f, g, K[13], W1(13), W2(17)); - R1(c, d, a, b, g, h, e, f, K[14], W1(14), W2(18)); - R1(b, c, d, a, f, g, h, e, K[15], W1(15), W2(19)); - - R2(a, b, c, d, e, f, g, h, K[16], W1(16), W2(20)); - R2(d, a, b, c, h, e, f, g, K[17], W1(17), W2(21)); - R2(c, d, a, b, g, h, e, f, K[18], W1(18), W2(22)); - R2(b, c, d, a, f, g, h, e, K[19], W1(19), W2(23)); - R2(a, b, c, d, e, f, g, h, K[20], W1(20), W2(24)); - R2(d, a, b, c, h, e, f, g, K[21], W1(21), W2(25)); - R2(c, d, a, b, g, h, e, f, K[22], W1(22), W2(26)); - R2(b, c, d, a, f, g, h, e, K[23], W1(23), W2(27)); - R2(a, b, c, d, e, f, g, h, K[24], W1(24), W2(28)); - R2(d, a, b, c, h, e, f, g, K[25], W1(25), W2(29)); - R2(c, d, a, b, g, h, e, f, K[26], W1(26), W2(30)); - R2(b, c, d, a, f, g, h, e, K[27], W1(27), W2(31)); - R2(a, b, c, d, e, f, g, h, K[28], W1(28), W2(32)); - R2(d, a, b, c, h, e, f, g, K[29], W1(29), W2(33)); - R2(c, d, a, b, g, h, e, f, K[30], W1(30), W2(34)); - R2(b, c, d, a, f, g, h, e, K[31], W1(31), W2(35)); - - R2(a, b, c, d, e, f, g, h, K[32], W1(32), W2(36)); - R2(d, a, b, c, h, e, f, g, K[33], W1(33), W2(37)); - R2(c, d, a, b, g, h, e, f, K[34], W1(34), W2(38)); - R2(b, c, d, a, f, g, h, e, K[35], W1(35), W2(39)); - R2(a, b, c, d, e, f, g, h, K[36], W1(36), W2(40)); - R2(d, a, b, c, h, e, f, g, K[37], W1(37), W2(41)); - R2(c, d, a, b, g, h, e, f, K[38], W1(38), W2(42)); - R2(b, c, d, a, f, g, h, e, K[39], W1(39), W2(43)); - R2(a, b, c, d, e, f, g, h, K[40], W1(40), W2(44)); - R2(d, a, b, c, h, e, f, g, K[41], W1(41), W2(45)); - R2(c, d, a, b, g, h, e, f, K[42], W1(42), W2(46)); - R2(b, c, d, a, f, g, h, e, K[43], W1(43), W2(47)); - R2(a, b, c, d, e, f, g, h, K[44], W1(44), W2(48)); - R2(d, a, b, c, h, e, f, g, K[45], W1(45), W2(49)); - R2(c, d, a, b, g, h, e, f, K[46], W1(46), W2(50)); - R2(b, c, d, a, f, g, h, e, K[47], W1(47), W2(51)); - - R2(a, b, c, d, e, f, g, h, K[48], W1(48), W2(52)); - R2(d, a, b, c, h, e, f, g, K[49], W1(49), W2(53)); - R2(c, d, a, b, g, h, e, f, K[50], W1(50), W2(54)); - R2(b, c, d, a, f, g, h, e, K[51], W1(51), W2(55)); - R2(a, b, c, d, e, f, g, h, K[52], W1(52), W2(56)); - R2(d, a, b, c, h, e, f, g, K[53], W1(53), W2(57)); - R2(c, d, a, b, g, h, e, f, K[54], W1(54), W2(58)); - R2(b, c, d, a, f, g, h, e, K[55], W1(55), W2(59)); - R2(a, b, c, d, e, f, g, h, K[56], W1(56), W2(60)); - R2(d, a, b, c, h, e, f, g, K[57], W1(57), W2(61)); - R2(c, d, a, b, g, h, e, f, K[58], W1(58), W2(62)); - R2(b, c, d, a, f, g, h, e, K[59], W1(59), W2(63)); - R2(a, b, c, d, e, f, g, h, K[60], W1(60), W2(64)); - R2(d, a, b, c, h, e, f, g, K[61], W1(61), W2(65)); - R2(c, d, a, b, g, h, e, f, K[62], W1(62), W2(66)); - R2(b, c, d, a, f, g, h, e, K[63], W1(63), W2(67)); - - sctx->state[0] ^= a; - sctx->state[1] ^= b; - sctx->state[2] ^= c; - sctx->state[3] ^= d; - sctx->state[4] ^= e; - sctx->state[5] ^= f; - sctx->state[6] ^= g; - sctx->state[7] ^= h; -} -#undef R -#undef R1 -#undef R2 -#undef I -#undef W1 -#undef W2 - -static inline void sm3_block(struct sm3_state *sctx, - u8 const *data, int blocks, u32 W[16]) -{ - while (blocks--) { - sm3_transform(sctx, data, W); - data += SM3_BLOCK_SIZE; - } -} - -void sm3_update(struct sm3_state *sctx, const u8 *data, unsigned int len) -{ - unsigned int partial = sctx->count % SM3_BLOCK_SIZE; - u32 W[16]; - - sctx->count += len; - - if ((partial + len) >= SM3_BLOCK_SIZE) { - int blocks; - - if (partial) { - int p = SM3_BLOCK_SIZE - partial; - - memcpy(sctx->buffer + partial, data, p); - data += p; - len -= p; - - sm3_block(sctx, sctx->buffer, 1, W); - } - - blocks = len / SM3_BLOCK_SIZE; - len %= SM3_BLOCK_SIZE; - - if (blocks) { - sm3_block(sctx, data, blocks, W); - data += blocks * SM3_BLOCK_SIZE; - } - - memzero_explicit(W, sizeof(W)); - - partial = 0; - } - if (len) - memcpy(sctx->buffer + partial, data, len); -} -EXPORT_SYMBOL_GPL(sm3_update); - -void sm3_final(struct sm3_state *sctx, u8 *out) -{ - const int bit_offset = SM3_BLOCK_SIZE - sizeof(u64); - __be64 *bits = (__be64 *)(sctx->buffer + bit_offset); - __be32 *digest = (__be32 *)out; - unsigned int partial = sctx->count % SM3_BLOCK_SIZE; - u32 W[16]; - int i; - - sctx->buffer[partial++] = 0x80; - if (partial > bit_offset) { - memset(sctx->buffer + partial, 0, SM3_BLOCK_SIZE - partial); - partial = 0; - - sm3_block(sctx, sctx->buffer, 1, W); - } - - memset(sctx->buffer + partial, 0, bit_offset - partial); - *bits = cpu_to_be64(sctx->count << 3); - sm3_block(sctx, sctx->buffer, 1, W); - - for (i = 0; i < 8; i++) - put_unaligned_be32(sctx->state[i], digest++); - - /* Zeroize sensitive information. */ - memzero_explicit(W, sizeof(W)); - memzero_explicit(sctx, sizeof(*sctx)); -} -EXPORT_SYMBOL_GPL(sm3_final); - -MODULE_DESCRIPTION("Generic SM3 library"); -MODULE_LICENSE("GPL v2"); diff --git a/lib/crypto/sm4.c b/lib/crypto/sm4.c deleted file mode 100644 index 284e62576d0c..000000000000 --- a/lib/crypto/sm4.c +++ /dev/null @@ -1,176 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * SM4, as specified in - * https://tools.ietf.org/id/draft-ribose-cfrg-sm4-10.html - * - * Copyright (C) 2018 ARM Limited or its affiliates. - * Copyright (c) 2021 Tianjia Zhang <tianjia.zhang@linux.alibaba.com> - */ - -#include <linux/module.h> -#include <asm/unaligned.h> -#include <crypto/sm4.h> - -static const u32 fk[4] = { - 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc -}; - -static const u32 ____cacheline_aligned ck[32] = { - 0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269, - 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9, - 0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249, - 0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9, - 0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229, - 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299, - 0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209, - 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279 -}; - -static const u8 ____cacheline_aligned sbox[256] = { - 0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, - 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05, - 0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3, - 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99, - 0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a, - 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62, - 0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, - 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6, - 0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, - 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8, - 0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, - 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35, - 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, - 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87, - 0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, - 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e, - 0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5, - 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1, - 0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55, - 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3, - 0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, - 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f, - 0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f, - 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51, - 0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, - 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8, - 0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, - 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0, - 0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e, - 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84, - 0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20, - 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48 -}; - -static inline u32 sm4_t_non_lin_sub(u32 x) -{ - u32 out; - - out = (u32)sbox[x & 0xff]; - out |= (u32)sbox[(x >> 8) & 0xff] << 8; - out |= (u32)sbox[(x >> 16) & 0xff] << 16; - out |= (u32)sbox[(x >> 24) & 0xff] << 24; - - return out; -} - -static inline u32 sm4_key_lin_sub(u32 x) -{ - return x ^ rol32(x, 13) ^ rol32(x, 23); -} - -static inline u32 sm4_enc_lin_sub(u32 x) -{ - return x ^ rol32(x, 2) ^ rol32(x, 10) ^ rol32(x, 18) ^ rol32(x, 24); -} - -static inline u32 sm4_key_sub(u32 x) -{ - return sm4_key_lin_sub(sm4_t_non_lin_sub(x)); -} - -static inline u32 sm4_enc_sub(u32 x) -{ - return sm4_enc_lin_sub(sm4_t_non_lin_sub(x)); -} - -static inline u32 sm4_round(u32 x0, u32 x1, u32 x2, u32 x3, u32 rk) -{ - return x0 ^ sm4_enc_sub(x1 ^ x2 ^ x3 ^ rk); -} - - -/** - * sm4_expandkey - Expands the SM4 key as described in GB/T 32907-2016 - * @ctx: The location where the computed key will be stored. - * @in_key: The supplied key. - * @key_len: The length of the supplied key. - * - * Returns 0 on success. The function fails only if an invalid key size (or - * pointer) is supplied. - */ -int sm4_expandkey(struct sm4_ctx *ctx, const u8 *in_key, - unsigned int key_len) -{ - u32 rk[4]; - const u32 *key = (u32 *)in_key; - int i; - - if (key_len != SM4_KEY_SIZE) - return -EINVAL; - - rk[0] = get_unaligned_be32(&key[0]) ^ fk[0]; - rk[1] = get_unaligned_be32(&key[1]) ^ fk[1]; - rk[2] = get_unaligned_be32(&key[2]) ^ fk[2]; - rk[3] = get_unaligned_be32(&key[3]) ^ fk[3]; - - for (i = 0; i < 32; i += 4) { - rk[0] ^= sm4_key_sub(rk[1] ^ rk[2] ^ rk[3] ^ ck[i + 0]); - rk[1] ^= sm4_key_sub(rk[2] ^ rk[3] ^ rk[0] ^ ck[i + 1]); - rk[2] ^= sm4_key_sub(rk[3] ^ rk[0] ^ rk[1] ^ ck[i + 2]); - rk[3] ^= sm4_key_sub(rk[0] ^ rk[1] ^ rk[2] ^ ck[i + 3]); - - ctx->rkey_enc[i + 0] = rk[0]; - ctx->rkey_enc[i + 1] = rk[1]; - ctx->rkey_enc[i + 2] = rk[2]; - ctx->rkey_enc[i + 3] = rk[3]; - ctx->rkey_dec[31 - 0 - i] = rk[0]; - ctx->rkey_dec[31 - 1 - i] = rk[1]; - ctx->rkey_dec[31 - 2 - i] = rk[2]; - ctx->rkey_dec[31 - 3 - i] = rk[3]; - } - - return 0; -} -EXPORT_SYMBOL_GPL(sm4_expandkey); - -/** - * sm4_crypt_block - Encrypt or decrypt a single SM4 block - * @rk: The rkey_enc for encrypt or rkey_dec for decrypt - * @out: Buffer to store output data - * @in: Buffer containing the input data - */ -void sm4_crypt_block(const u32 *rk, u8 *out, const u8 *in) -{ - u32 x[4], i; - - x[0] = get_unaligned_be32(in + 0 * 4); - x[1] = get_unaligned_be32(in + 1 * 4); - x[2] = get_unaligned_be32(in + 2 * 4); - x[3] = get_unaligned_be32(in + 3 * 4); - - for (i = 0; i < 32; i += 4) { - x[0] = sm4_round(x[0], x[1], x[2], x[3], rk[i + 0]); - x[1] = sm4_round(x[1], x[2], x[3], x[0], rk[i + 1]); - x[2] = sm4_round(x[2], x[3], x[0], x[1], rk[i + 2]); - x[3] = sm4_round(x[3], x[0], x[1], x[2], rk[i + 3]); - } - - put_unaligned_be32(x[3 - 0], out + 0 * 4); - put_unaligned_be32(x[3 - 1], out + 1 * 4); - put_unaligned_be32(x[3 - 2], out + 2 * 4); - put_unaligned_be32(x[3 - 3], out + 3 * 4); -} -EXPORT_SYMBOL_GPL(sm4_crypt_block); - -MODULE_DESCRIPTION("Generic SM4 library"); -MODULE_LICENSE("GPL v2"); |