b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame] | 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
| 2 | From: Ard Biesheuvel <ardb@kernel.org> |
| 3 | Date: Fri, 8 Nov 2019 13:22:08 +0100 |
| 4 | Subject: [PATCH] crypto: chacha - move existing library code into lib/crypto |
| 5 | |
| 6 | commit 5fb8ef25803ef33e2eb60b626435828b937bed75 upstream. |
| 7 | |
| 8 | Currently, our generic ChaCha implementation consists of a permute |
| 9 | function in lib/chacha.c that operates on the 64-byte ChaCha state |
| 10 | directly [and which is always included into the core kernel since it |
| 11 | is used by the /dev/random driver], and the crypto API plumbing to |
| 12 | expose it as a skcipher. |
| 13 | |
| 14 | In order to support in-kernel users that need the ChaCha streamcipher |
| 15 | but have no need [or tolerance] for going through the abstractions of |
| 16 | the crypto API, let's expose the streamcipher bits via a library API |
| 17 | as well, in a way that permits the implementation to be superseded by |
| 18 | an architecture specific one if provided. |
| 19 | |
| 20 | So move the streamcipher code into a separate module in lib/crypto, |
| 21 | and expose the init() and crypt() routines to users of the library. |
| 22 | |
| 23 | Signed-off-by: Ard Biesheuvel <ardb@kernel.org> |
| 24 | Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> |
| 25 | Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com> |
| 26 | --- |
| 27 | arch/arm/crypto/chacha-neon-glue.c | 2 +- |
| 28 | arch/arm64/crypto/chacha-neon-glue.c | 2 +- |
| 29 | arch/x86/crypto/chacha_glue.c | 2 +- |
| 30 | crypto/Kconfig | 1 + |
| 31 | crypto/chacha_generic.c | 60 ++-------------------- |
| 32 | include/crypto/chacha.h | 77 ++++++++++++++++++++++------ |
| 33 | include/crypto/internal/chacha.h | 53 +++++++++++++++++++ |
| 34 | lib/Makefile | 3 +- |
| 35 | lib/crypto/Kconfig | 26 ++++++++++ |
| 36 | lib/crypto/Makefile | 4 ++ |
| 37 | lib/{ => crypto}/chacha.c | 20 ++++---- |
| 38 | lib/crypto/libchacha.c | 35 +++++++++++++ |
| 39 | 12 files changed, 199 insertions(+), 86 deletions(-) |
| 40 | create mode 100644 include/crypto/internal/chacha.h |
| 41 | rename lib/{ => crypto}/chacha.c (88%) |
| 42 | create mode 100644 lib/crypto/libchacha.c |
| 43 | |
| 44 | --- a/arch/arm/crypto/chacha-neon-glue.c |
| 45 | +++ b/arch/arm/crypto/chacha-neon-glue.c |
| 46 | @@ -20,7 +20,7 @@ |
| 47 | */ |
| 48 | |
| 49 | #include <crypto/algapi.h> |
| 50 | -#include <crypto/chacha.h> |
| 51 | +#include <crypto/internal/chacha.h> |
| 52 | #include <crypto/internal/simd.h> |
| 53 | #include <crypto/internal/skcipher.h> |
| 54 | #include <linux/kernel.h> |
| 55 | --- a/arch/arm64/crypto/chacha-neon-glue.c |
| 56 | +++ b/arch/arm64/crypto/chacha-neon-glue.c |
| 57 | @@ -20,7 +20,7 @@ |
| 58 | */ |
| 59 | |
| 60 | #include <crypto/algapi.h> |
| 61 | -#include <crypto/chacha.h> |
| 62 | +#include <crypto/internal/chacha.h> |
| 63 | #include <crypto/internal/simd.h> |
| 64 | #include <crypto/internal/skcipher.h> |
| 65 | #include <linux/kernel.h> |
| 66 | --- a/arch/x86/crypto/chacha_glue.c |
| 67 | +++ b/arch/x86/crypto/chacha_glue.c |
| 68 | @@ -7,7 +7,7 @@ |
| 69 | */ |
| 70 | |
| 71 | #include <crypto/algapi.h> |
| 72 | -#include <crypto/chacha.h> |
| 73 | +#include <crypto/internal/chacha.h> |
| 74 | #include <crypto/internal/simd.h> |
| 75 | #include <crypto/internal/skcipher.h> |
| 76 | #include <linux/kernel.h> |
| 77 | --- a/crypto/Kconfig |
| 78 | +++ b/crypto/Kconfig |
| 79 | @@ -1393,6 +1393,7 @@ config CRYPTO_SALSA20 |
| 80 | |
| 81 | config CRYPTO_CHACHA20 |
| 82 | tristate "ChaCha stream cipher algorithms" |
| 83 | + select CRYPTO_LIB_CHACHA_GENERIC |
| 84 | select CRYPTO_BLKCIPHER |
| 85 | help |
| 86 | The ChaCha20, XChaCha20, and XChaCha12 stream cipher algorithms. |
| 87 | --- a/crypto/chacha_generic.c |
| 88 | +++ b/crypto/chacha_generic.c |
| 89 | @@ -8,29 +8,10 @@ |
| 90 | |
| 91 | #include <asm/unaligned.h> |
| 92 | #include <crypto/algapi.h> |
| 93 | -#include <crypto/chacha.h> |
| 94 | +#include <crypto/internal/chacha.h> |
| 95 | #include <crypto/internal/skcipher.h> |
| 96 | #include <linux/module.h> |
| 97 | |
| 98 | -static void chacha_docrypt(u32 *state, u8 *dst, const u8 *src, |
| 99 | - unsigned int bytes, int nrounds) |
| 100 | -{ |
| 101 | - /* aligned to potentially speed up crypto_xor() */ |
| 102 | - u8 stream[CHACHA_BLOCK_SIZE] __aligned(sizeof(long)); |
| 103 | - |
| 104 | - while (bytes >= CHACHA_BLOCK_SIZE) { |
| 105 | - chacha_block(state, stream, nrounds); |
| 106 | - crypto_xor_cpy(dst, src, stream, CHACHA_BLOCK_SIZE); |
| 107 | - bytes -= CHACHA_BLOCK_SIZE; |
| 108 | - dst += CHACHA_BLOCK_SIZE; |
| 109 | - src += CHACHA_BLOCK_SIZE; |
| 110 | - } |
| 111 | - if (bytes) { |
| 112 | - chacha_block(state, stream, nrounds); |
| 113 | - crypto_xor_cpy(dst, src, stream, bytes); |
| 114 | - } |
| 115 | -} |
| 116 | - |
| 117 | static int chacha_stream_xor(struct skcipher_request *req, |
| 118 | const struct chacha_ctx *ctx, const u8 *iv) |
| 119 | { |
| 120 | @@ -48,8 +29,8 @@ static int chacha_stream_xor(struct skci |
| 121 | if (nbytes < walk.total) |
| 122 | nbytes = round_down(nbytes, CHACHA_BLOCK_SIZE); |
| 123 | |
| 124 | - chacha_docrypt(state, walk.dst.virt.addr, walk.src.virt.addr, |
| 125 | - nbytes, ctx->nrounds); |
| 126 | + chacha_crypt_generic(state, walk.dst.virt.addr, |
| 127 | + walk.src.virt.addr, nbytes, ctx->nrounds); |
| 128 | err = skcipher_walk_done(&walk, walk.nbytes - nbytes); |
| 129 | } |
| 130 | |
| 131 | @@ -58,41 +39,10 @@ static int chacha_stream_xor(struct skci |
| 132 | |
| 133 | void crypto_chacha_init(u32 *state, const struct chacha_ctx *ctx, const u8 *iv) |
| 134 | { |
| 135 | - state[0] = 0x61707865; /* "expa" */ |
| 136 | - state[1] = 0x3320646e; /* "nd 3" */ |
| 137 | - state[2] = 0x79622d32; /* "2-by" */ |
| 138 | - state[3] = 0x6b206574; /* "te k" */ |
| 139 | - state[4] = ctx->key[0]; |
| 140 | - state[5] = ctx->key[1]; |
| 141 | - state[6] = ctx->key[2]; |
| 142 | - state[7] = ctx->key[3]; |
| 143 | - state[8] = ctx->key[4]; |
| 144 | - state[9] = ctx->key[5]; |
| 145 | - state[10] = ctx->key[6]; |
| 146 | - state[11] = ctx->key[7]; |
| 147 | - state[12] = get_unaligned_le32(iv + 0); |
| 148 | - state[13] = get_unaligned_le32(iv + 4); |
| 149 | - state[14] = get_unaligned_le32(iv + 8); |
| 150 | - state[15] = get_unaligned_le32(iv + 12); |
| 151 | + chacha_init_generic(state, ctx->key, iv); |
| 152 | } |
| 153 | EXPORT_SYMBOL_GPL(crypto_chacha_init); |
| 154 | |
| 155 | -static int chacha_setkey(struct crypto_skcipher *tfm, const u8 *key, |
| 156 | - unsigned int keysize, int nrounds) |
| 157 | -{ |
| 158 | - struct chacha_ctx *ctx = crypto_skcipher_ctx(tfm); |
| 159 | - int i; |
| 160 | - |
| 161 | - if (keysize != CHACHA_KEY_SIZE) |
| 162 | - return -EINVAL; |
| 163 | - |
| 164 | - for (i = 0; i < ARRAY_SIZE(ctx->key); i++) |
| 165 | - ctx->key[i] = get_unaligned_le32(key + i * sizeof(u32)); |
| 166 | - |
| 167 | - ctx->nrounds = nrounds; |
| 168 | - return 0; |
| 169 | -} |
| 170 | - |
| 171 | int crypto_chacha20_setkey(struct crypto_skcipher *tfm, const u8 *key, |
| 172 | unsigned int keysize) |
| 173 | { |
| 174 | @@ -126,7 +76,7 @@ int crypto_xchacha_crypt(struct skcipher |
| 175 | |
| 176 | /* Compute the subkey given the original key and first 128 nonce bits */ |
| 177 | crypto_chacha_init(state, ctx, req->iv); |
| 178 | - hchacha_block(state, subctx.key, ctx->nrounds); |
| 179 | + hchacha_block_generic(state, subctx.key, ctx->nrounds); |
| 180 | subctx.nrounds = ctx->nrounds; |
| 181 | |
| 182 | /* Build the real IV */ |
| 183 | --- a/include/crypto/chacha.h |
| 184 | +++ b/include/crypto/chacha.h |
| 185 | @@ -15,9 +15,8 @@ |
| 186 | #ifndef _CRYPTO_CHACHA_H |
| 187 | #define _CRYPTO_CHACHA_H |
| 188 | |
| 189 | -#include <crypto/skcipher.h> |
| 190 | +#include <asm/unaligned.h> |
| 191 | #include <linux/types.h> |
| 192 | -#include <linux/crypto.h> |
| 193 | |
| 194 | /* 32-bit stream position, then 96-bit nonce (RFC7539 convention) */ |
| 195 | #define CHACHA_IV_SIZE 16 |
| 196 | @@ -29,27 +28,71 @@ |
| 197 | /* 192-bit nonce, then 64-bit stream position */ |
| 198 | #define XCHACHA_IV_SIZE 32 |
| 199 | |
| 200 | -struct chacha_ctx { |
| 201 | - u32 key[8]; |
| 202 | - int nrounds; |
| 203 | -}; |
| 204 | - |
| 205 | -void chacha_block(u32 *state, u8 *stream, int nrounds); |
| 206 | +void chacha_block_generic(u32 *state, u8 *stream, int nrounds); |
| 207 | static inline void chacha20_block(u32 *state, u8 *stream) |
| 208 | { |
| 209 | - chacha_block(state, stream, 20); |
| 210 | + chacha_block_generic(state, stream, 20); |
| 211 | } |
| 212 | -void hchacha_block(const u32 *in, u32 *out, int nrounds); |
| 213 | |
| 214 | -void crypto_chacha_init(u32 *state, const struct chacha_ctx *ctx, const u8 *iv); |
| 215 | +void hchacha_block_arch(const u32 *state, u32 *out, int nrounds); |
| 216 | +void hchacha_block_generic(const u32 *state, u32 *out, int nrounds); |
| 217 | + |
| 218 | +static inline void hchacha_block(const u32 *state, u32 *out, int nrounds) |
| 219 | +{ |
| 220 | + if (IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_CHACHA)) |
| 221 | + hchacha_block_arch(state, out, nrounds); |
| 222 | + else |
| 223 | + hchacha_block_generic(state, out, nrounds); |
| 224 | +} |
| 225 | |
| 226 | -int crypto_chacha20_setkey(struct crypto_skcipher *tfm, const u8 *key, |
| 227 | - unsigned int keysize); |
| 228 | -int crypto_chacha12_setkey(struct crypto_skcipher *tfm, const u8 *key, |
| 229 | - unsigned int keysize); |
| 230 | +void chacha_init_arch(u32 *state, const u32 *key, const u8 *iv); |
| 231 | +static inline void chacha_init_generic(u32 *state, const u32 *key, const u8 *iv) |
| 232 | +{ |
| 233 | + state[0] = 0x61707865; /* "expa" */ |
| 234 | + state[1] = 0x3320646e; /* "nd 3" */ |
| 235 | + state[2] = 0x79622d32; /* "2-by" */ |
| 236 | + state[3] = 0x6b206574; /* "te k" */ |
| 237 | + state[4] = key[0]; |
| 238 | + state[5] = key[1]; |
| 239 | + state[6] = key[2]; |
| 240 | + state[7] = key[3]; |
| 241 | + state[8] = key[4]; |
| 242 | + state[9] = key[5]; |
| 243 | + state[10] = key[6]; |
| 244 | + state[11] = key[7]; |
| 245 | + state[12] = get_unaligned_le32(iv + 0); |
| 246 | + state[13] = get_unaligned_le32(iv + 4); |
| 247 | + state[14] = get_unaligned_le32(iv + 8); |
| 248 | + state[15] = get_unaligned_le32(iv + 12); |
| 249 | +} |
| 250 | |
| 251 | -int crypto_chacha_crypt(struct skcipher_request *req); |
| 252 | -int crypto_xchacha_crypt(struct skcipher_request *req); |
| 253 | +static inline void chacha_init(u32 *state, const u32 *key, const u8 *iv) |
| 254 | +{ |
| 255 | + if (IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_CHACHA)) |
| 256 | + chacha_init_arch(state, key, iv); |
| 257 | + else |
| 258 | + chacha_init_generic(state, key, iv); |
| 259 | +} |
| 260 | + |
| 261 | +void chacha_crypt_arch(u32 *state, u8 *dst, const u8 *src, |
| 262 | + unsigned int bytes, int nrounds); |
| 263 | +void chacha_crypt_generic(u32 *state, u8 *dst, const u8 *src, |
| 264 | + unsigned int bytes, int nrounds); |
| 265 | + |
| 266 | +static inline void chacha_crypt(u32 *state, u8 *dst, const u8 *src, |
| 267 | + unsigned int bytes, int nrounds) |
| 268 | +{ |
| 269 | + if (IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_CHACHA)) |
| 270 | + chacha_crypt_arch(state, dst, src, bytes, nrounds); |
| 271 | + else |
| 272 | + chacha_crypt_generic(state, dst, src, bytes, nrounds); |
| 273 | +} |
| 274 | + |
| 275 | +static inline void chacha20_crypt(u32 *state, u8 *dst, const u8 *src, |
| 276 | + unsigned int bytes) |
| 277 | +{ |
| 278 | + chacha_crypt(state, dst, src, bytes, 20); |
| 279 | +} |
| 280 | |
| 281 | enum chacha_constants { /* expand 32-byte k */ |
| 282 | CHACHA_CONSTANT_EXPA = 0x61707865U, |
| 283 | --- /dev/null |
| 284 | +++ b/include/crypto/internal/chacha.h |
| 285 | @@ -0,0 +1,53 @@ |
| 286 | +/* SPDX-License-Identifier: GPL-2.0 */ |
| 287 | + |
| 288 | +#ifndef _CRYPTO_INTERNAL_CHACHA_H |
| 289 | +#define _CRYPTO_INTERNAL_CHACHA_H |
| 290 | + |
| 291 | +#include <crypto/chacha.h> |
| 292 | +#include <crypto/internal/skcipher.h> |
| 293 | +#include <linux/crypto.h> |
| 294 | + |
| 295 | +struct chacha_ctx { |
| 296 | + u32 key[8]; |
| 297 | + int nrounds; |
| 298 | +}; |
| 299 | + |
| 300 | +void crypto_chacha_init(u32 *state, const struct chacha_ctx *ctx, const u8 *iv); |
| 301 | + |
| 302 | +static inline int chacha_setkey(struct crypto_skcipher *tfm, const u8 *key, |
| 303 | + unsigned int keysize, int nrounds) |
| 304 | +{ |
| 305 | + struct chacha_ctx *ctx = crypto_skcipher_ctx(tfm); |
| 306 | + int i; |
| 307 | + |
| 308 | + if (keysize != CHACHA_KEY_SIZE) |
| 309 | + return -EINVAL; |
| 310 | + |
| 311 | + for (i = 0; i < ARRAY_SIZE(ctx->key); i++) |
| 312 | + ctx->key[i] = get_unaligned_le32(key + i * sizeof(u32)); |
| 313 | + |
| 314 | + ctx->nrounds = nrounds; |
| 315 | + return 0; |
| 316 | +} |
| 317 | + |
| 318 | +static inline int chacha20_setkey(struct crypto_skcipher *tfm, const u8 *key, |
| 319 | + unsigned int keysize) |
| 320 | +{ |
| 321 | + return chacha_setkey(tfm, key, keysize, 20); |
| 322 | +} |
| 323 | + |
| 324 | +static int inline chacha12_setkey(struct crypto_skcipher *tfm, const u8 *key, |
| 325 | + unsigned int keysize) |
| 326 | +{ |
| 327 | + return chacha_setkey(tfm, key, keysize, 12); |
| 328 | +} |
| 329 | + |
| 330 | +int crypto_chacha20_setkey(struct crypto_skcipher *tfm, const u8 *key, |
| 331 | + unsigned int keysize); |
| 332 | +int crypto_chacha12_setkey(struct crypto_skcipher *tfm, const u8 *key, |
| 333 | + unsigned int keysize); |
| 334 | + |
| 335 | +int crypto_chacha_crypt(struct skcipher_request *req); |
| 336 | +int crypto_xchacha_crypt(struct skcipher_request *req); |
| 337 | + |
| 338 | +#endif /* _CRYPTO_CHACHA_H */ |
| 339 | --- a/lib/Makefile |
| 340 | +++ b/lib/Makefile |
| 341 | @@ -26,8 +26,7 @@ endif |
| 342 | |
| 343 | lib-y := ctype.o string.o vsprintf.o cmdline.o \ |
| 344 | rbtree.o radix-tree.o timerqueue.o xarray.o \ |
| 345 | - idr.o extable.o \ |
| 346 | - sha1.o chacha.o irq_regs.o argv_split.o \ |
| 347 | + idr.o extable.o sha1.o irq_regs.o argv_split.o \ |
| 348 | flex_proportions.o ratelimit.o show_mem.o \ |
| 349 | is_single_threaded.o plist.o decompress.o kobject_uevent.o \ |
| 350 | earlycpio.o seq_buf.o siphash.o dec_and_lock.o \ |
| 351 | --- a/lib/crypto/Kconfig |
| 352 | +++ b/lib/crypto/Kconfig |
| 353 | @@ -8,6 +8,32 @@ config CRYPTO_LIB_AES |
| 354 | config CRYPTO_LIB_ARC4 |
| 355 | tristate |
| 356 | |
| 357 | +config CRYPTO_ARCH_HAVE_LIB_CHACHA |
| 358 | + tristate |
| 359 | + help |
| 360 | + Declares whether the architecture provides an arch-specific |
| 361 | + accelerated implementation of the ChaCha library interface, |
| 362 | + either builtin or as a module. |
| 363 | + |
| 364 | +config CRYPTO_LIB_CHACHA_GENERIC |
| 365 | + tristate |
| 366 | + select CRYPTO_ALGAPI |
| 367 | + help |
| 368 | + This symbol can be depended upon by arch implementations of the |
| 369 | + ChaCha library interface that require the generic code as a |
| 370 | + fallback, e.g., for SIMD implementations. If no arch specific |
| 371 | + implementation is enabled, this implementation serves the users |
| 372 | + of CRYPTO_LIB_CHACHA. |
| 373 | + |
| 374 | +config CRYPTO_LIB_CHACHA |
| 375 | + tristate "ChaCha library interface" |
| 376 | + depends on CRYPTO_ARCH_HAVE_LIB_CHACHA || !CRYPTO_ARCH_HAVE_LIB_CHACHA |
| 377 | + select CRYPTO_LIB_CHACHA_GENERIC if CRYPTO_ARCH_HAVE_LIB_CHACHA=n |
| 378 | + help |
| 379 | + Enable the ChaCha library interface. This interface may be fulfilled |
| 380 | + by either the generic implementation or an arch-specific one, if one |
| 381 | + is available and enabled. |
| 382 | + |
| 383 | config CRYPTO_LIB_DES |
| 384 | tristate |
| 385 | |
| 386 | --- a/lib/crypto/Makefile |
| 387 | +++ b/lib/crypto/Makefile |
| 388 | @@ -1,5 +1,9 @@ |
| 389 | # SPDX-License-Identifier: GPL-2.0 |
| 390 | |
| 391 | +# chacha is used by the /dev/random driver which is always builtin |
| 392 | +obj-y += chacha.o |
| 393 | +obj-$(CONFIG_CRYPTO_LIB_CHACHA_GENERIC) += libchacha.o |
| 394 | + |
| 395 | obj-$(CONFIG_CRYPTO_LIB_AES) += libaes.o |
| 396 | libaes-y := aes.o |
| 397 | |
| 398 | --- a/lib/chacha.c |
| 399 | +++ /dev/null |
| 400 | @@ -1,113 +0,0 @@ |
| 401 | -// SPDX-License-Identifier: GPL-2.0-or-later |
| 402 | -/* |
| 403 | - * The "hash function" used as the core of the ChaCha stream cipher (RFC7539) |
| 404 | - * |
| 405 | - * Copyright (C) 2015 Martin Willi |
| 406 | - */ |
| 407 | - |
| 408 | -#include <linux/kernel.h> |
| 409 | -#include <linux/export.h> |
| 410 | -#include <linux/bitops.h> |
| 411 | -#include <linux/cryptohash.h> |
| 412 | -#include <asm/unaligned.h> |
| 413 | -#include <crypto/chacha.h> |
| 414 | - |
| 415 | -static void chacha_permute(u32 *x, int nrounds) |
| 416 | -{ |
| 417 | - int i; |
| 418 | - |
| 419 | - /* whitelist the allowed round counts */ |
| 420 | - WARN_ON_ONCE(nrounds != 20 && nrounds != 12); |
| 421 | - |
| 422 | - for (i = 0; i < nrounds; i += 2) { |
| 423 | - x[0] += x[4]; x[12] = rol32(x[12] ^ x[0], 16); |
| 424 | - x[1] += x[5]; x[13] = rol32(x[13] ^ x[1], 16); |
| 425 | - x[2] += x[6]; x[14] = rol32(x[14] ^ x[2], 16); |
| 426 | - x[3] += x[7]; x[15] = rol32(x[15] ^ x[3], 16); |
| 427 | - |
| 428 | - x[8] += x[12]; x[4] = rol32(x[4] ^ x[8], 12); |
| 429 | - x[9] += x[13]; x[5] = rol32(x[5] ^ x[9], 12); |
| 430 | - x[10] += x[14]; x[6] = rol32(x[6] ^ x[10], 12); |
| 431 | - x[11] += x[15]; x[7] = rol32(x[7] ^ x[11], 12); |
| 432 | - |
| 433 | - x[0] += x[4]; x[12] = rol32(x[12] ^ x[0], 8); |
| 434 | - x[1] += x[5]; x[13] = rol32(x[13] ^ x[1], 8); |
| 435 | - x[2] += x[6]; x[14] = rol32(x[14] ^ x[2], 8); |
| 436 | - x[3] += x[7]; x[15] = rol32(x[15] ^ x[3], 8); |
| 437 | - |
| 438 | - x[8] += x[12]; x[4] = rol32(x[4] ^ x[8], 7); |
| 439 | - x[9] += x[13]; x[5] = rol32(x[5] ^ x[9], 7); |
| 440 | - x[10] += x[14]; x[6] = rol32(x[6] ^ x[10], 7); |
| 441 | - x[11] += x[15]; x[7] = rol32(x[7] ^ x[11], 7); |
| 442 | - |
| 443 | - x[0] += x[5]; x[15] = rol32(x[15] ^ x[0], 16); |
| 444 | - x[1] += x[6]; x[12] = rol32(x[12] ^ x[1], 16); |
| 445 | - x[2] += x[7]; x[13] = rol32(x[13] ^ x[2], 16); |
| 446 | - x[3] += x[4]; x[14] = rol32(x[14] ^ x[3], 16); |
| 447 | - |
| 448 | - x[10] += x[15]; x[5] = rol32(x[5] ^ x[10], 12); |
| 449 | - x[11] += x[12]; x[6] = rol32(x[6] ^ x[11], 12); |
| 450 | - x[8] += x[13]; x[7] = rol32(x[7] ^ x[8], 12); |
| 451 | - x[9] += x[14]; x[4] = rol32(x[4] ^ x[9], 12); |
| 452 | - |
| 453 | - x[0] += x[5]; x[15] = rol32(x[15] ^ x[0], 8); |
| 454 | - x[1] += x[6]; x[12] = rol32(x[12] ^ x[1], 8); |
| 455 | - x[2] += x[7]; x[13] = rol32(x[13] ^ x[2], 8); |
| 456 | - x[3] += x[4]; x[14] = rol32(x[14] ^ x[3], 8); |
| 457 | - |
| 458 | - x[10] += x[15]; x[5] = rol32(x[5] ^ x[10], 7); |
| 459 | - x[11] += x[12]; x[6] = rol32(x[6] ^ x[11], 7); |
| 460 | - x[8] += x[13]; x[7] = rol32(x[7] ^ x[8], 7); |
| 461 | - x[9] += x[14]; x[4] = rol32(x[4] ^ x[9], 7); |
| 462 | - } |
| 463 | -} |
| 464 | - |
| 465 | -/** |
| 466 | - * chacha_block - generate one keystream block and increment block counter |
| 467 | - * @state: input state matrix (16 32-bit words) |
| 468 | - * @stream: output keystream block (64 bytes) |
| 469 | - * @nrounds: number of rounds (20 or 12; 20 is recommended) |
| 470 | - * |
| 471 | - * This is the ChaCha core, a function from 64-byte strings to 64-byte strings. |
| 472 | - * The caller has already converted the endianness of the input. This function |
| 473 | - * also handles incrementing the block counter in the input matrix. |
| 474 | - */ |
| 475 | -void chacha_block(u32 *state, u8 *stream, int nrounds) |
| 476 | -{ |
| 477 | - u32 x[16]; |
| 478 | - int i; |
| 479 | - |
| 480 | - memcpy(x, state, 64); |
| 481 | - |
| 482 | - chacha_permute(x, nrounds); |
| 483 | - |
| 484 | - for (i = 0; i < ARRAY_SIZE(x); i++) |
| 485 | - put_unaligned_le32(x[i] + state[i], &stream[i * sizeof(u32)]); |
| 486 | - |
| 487 | - state[12]++; |
| 488 | -} |
| 489 | -EXPORT_SYMBOL(chacha_block); |
| 490 | - |
| 491 | -/** |
| 492 | - * hchacha_block - abbreviated ChaCha core, for XChaCha |
| 493 | - * @in: input state matrix (16 32-bit words) |
| 494 | - * @out: output (8 32-bit words) |
| 495 | - * @nrounds: number of rounds (20 or 12; 20 is recommended) |
| 496 | - * |
| 497 | - * HChaCha is the ChaCha equivalent of HSalsa and is an intermediate step |
| 498 | - * towards XChaCha (see https://cr.yp.to/snuffle/xsalsa-20081128.pdf). HChaCha |
| 499 | - * skips the final addition of the initial state, and outputs only certain words |
| 500 | - * of the state. It should not be used for streaming directly. |
| 501 | - */ |
| 502 | -void hchacha_block(const u32 *in, u32 *out, int nrounds) |
| 503 | -{ |
| 504 | - u32 x[16]; |
| 505 | - |
| 506 | - memcpy(x, in, 64); |
| 507 | - |
| 508 | - chacha_permute(x, nrounds); |
| 509 | - |
| 510 | - memcpy(&out[0], &x[0], 16); |
| 511 | - memcpy(&out[4], &x[12], 16); |
| 512 | -} |
| 513 | -EXPORT_SYMBOL(hchacha_block); |
| 514 | --- /dev/null |
| 515 | +++ b/lib/crypto/chacha.c |
| 516 | @@ -0,0 +1,115 @@ |
| 517 | +// SPDX-License-Identifier: GPL-2.0-or-later |
| 518 | +/* |
| 519 | + * The "hash function" used as the core of the ChaCha stream cipher (RFC7539) |
| 520 | + * |
| 521 | + * Copyright (C) 2015 Martin Willi |
| 522 | + */ |
| 523 | + |
| 524 | +#include <linux/bug.h> |
| 525 | +#include <linux/kernel.h> |
| 526 | +#include <linux/export.h> |
| 527 | +#include <linux/bitops.h> |
| 528 | +#include <linux/string.h> |
| 529 | +#include <linux/cryptohash.h> |
| 530 | +#include <asm/unaligned.h> |
| 531 | +#include <crypto/chacha.h> |
| 532 | + |
| 533 | +static void chacha_permute(u32 *x, int nrounds) |
| 534 | +{ |
| 535 | + int i; |
| 536 | + |
| 537 | + /* whitelist the allowed round counts */ |
| 538 | + WARN_ON_ONCE(nrounds != 20 && nrounds != 12); |
| 539 | + |
| 540 | + for (i = 0; i < nrounds; i += 2) { |
| 541 | + x[0] += x[4]; x[12] = rol32(x[12] ^ x[0], 16); |
| 542 | + x[1] += x[5]; x[13] = rol32(x[13] ^ x[1], 16); |
| 543 | + x[2] += x[6]; x[14] = rol32(x[14] ^ x[2], 16); |
| 544 | + x[3] += x[7]; x[15] = rol32(x[15] ^ x[3], 16); |
| 545 | + |
| 546 | + x[8] += x[12]; x[4] = rol32(x[4] ^ x[8], 12); |
| 547 | + x[9] += x[13]; x[5] = rol32(x[5] ^ x[9], 12); |
| 548 | + x[10] += x[14]; x[6] = rol32(x[6] ^ x[10], 12); |
| 549 | + x[11] += x[15]; x[7] = rol32(x[7] ^ x[11], 12); |
| 550 | + |
| 551 | + x[0] += x[4]; x[12] = rol32(x[12] ^ x[0], 8); |
| 552 | + x[1] += x[5]; x[13] = rol32(x[13] ^ x[1], 8); |
| 553 | + x[2] += x[6]; x[14] = rol32(x[14] ^ x[2], 8); |
| 554 | + x[3] += x[7]; x[15] = rol32(x[15] ^ x[3], 8); |
| 555 | + |
| 556 | + x[8] += x[12]; x[4] = rol32(x[4] ^ x[8], 7); |
| 557 | + x[9] += x[13]; x[5] = rol32(x[5] ^ x[9], 7); |
| 558 | + x[10] += x[14]; x[6] = rol32(x[6] ^ x[10], 7); |
| 559 | + x[11] += x[15]; x[7] = rol32(x[7] ^ x[11], 7); |
| 560 | + |
| 561 | + x[0] += x[5]; x[15] = rol32(x[15] ^ x[0], 16); |
| 562 | + x[1] += x[6]; x[12] = rol32(x[12] ^ x[1], 16); |
| 563 | + x[2] += x[7]; x[13] = rol32(x[13] ^ x[2], 16); |
| 564 | + x[3] += x[4]; x[14] = rol32(x[14] ^ x[3], 16); |
| 565 | + |
| 566 | + x[10] += x[15]; x[5] = rol32(x[5] ^ x[10], 12); |
| 567 | + x[11] += x[12]; x[6] = rol32(x[6] ^ x[11], 12); |
| 568 | + x[8] += x[13]; x[7] = rol32(x[7] ^ x[8], 12); |
| 569 | + x[9] += x[14]; x[4] = rol32(x[4] ^ x[9], 12); |
| 570 | + |
| 571 | + x[0] += x[5]; x[15] = rol32(x[15] ^ x[0], 8); |
| 572 | + x[1] += x[6]; x[12] = rol32(x[12] ^ x[1], 8); |
| 573 | + x[2] += x[7]; x[13] = rol32(x[13] ^ x[2], 8); |
| 574 | + x[3] += x[4]; x[14] = rol32(x[14] ^ x[3], 8); |
| 575 | + |
| 576 | + x[10] += x[15]; x[5] = rol32(x[5] ^ x[10], 7); |
| 577 | + x[11] += x[12]; x[6] = rol32(x[6] ^ x[11], 7); |
| 578 | + x[8] += x[13]; x[7] = rol32(x[7] ^ x[8], 7); |
| 579 | + x[9] += x[14]; x[4] = rol32(x[4] ^ x[9], 7); |
| 580 | + } |
| 581 | +} |
| 582 | + |
| 583 | +/** |
| 584 | + * chacha_block - generate one keystream block and increment block counter |
| 585 | + * @state: input state matrix (16 32-bit words) |
| 586 | + * @stream: output keystream block (64 bytes) |
| 587 | + * @nrounds: number of rounds (20 or 12; 20 is recommended) |
| 588 | + * |
| 589 | + * This is the ChaCha core, a function from 64-byte strings to 64-byte strings. |
| 590 | + * The caller has already converted the endianness of the input. This function |
| 591 | + * also handles incrementing the block counter in the input matrix. |
| 592 | + */ |
| 593 | +void chacha_block_generic(u32 *state, u8 *stream, int nrounds) |
| 594 | +{ |
| 595 | + u32 x[16]; |
| 596 | + int i; |
| 597 | + |
| 598 | + memcpy(x, state, 64); |
| 599 | + |
| 600 | + chacha_permute(x, nrounds); |
| 601 | + |
| 602 | + for (i = 0; i < ARRAY_SIZE(x); i++) |
| 603 | + put_unaligned_le32(x[i] + state[i], &stream[i * sizeof(u32)]); |
| 604 | + |
| 605 | + state[12]++; |
| 606 | +} |
| 607 | +EXPORT_SYMBOL(chacha_block_generic); |
| 608 | + |
| 609 | +/** |
| 610 | + * hchacha_block_generic - abbreviated ChaCha core, for XChaCha |
| 611 | + * @state: input state matrix (16 32-bit words) |
| 612 | + * @out: output (8 32-bit words) |
| 613 | + * @nrounds: number of rounds (20 or 12; 20 is recommended) |
| 614 | + * |
| 615 | + * HChaCha is the ChaCha equivalent of HSalsa and is an intermediate step |
| 616 | + * towards XChaCha (see https://cr.yp.to/snuffle/xsalsa-20081128.pdf). HChaCha |
| 617 | + * skips the final addition of the initial state, and outputs only certain words |
| 618 | + * of the state. It should not be used for streaming directly. |
| 619 | + */ |
| 620 | +void hchacha_block_generic(const u32 *state, u32 *stream, int nrounds) |
| 621 | +{ |
| 622 | + u32 x[16]; |
| 623 | + |
| 624 | + memcpy(x, state, 64); |
| 625 | + |
| 626 | + chacha_permute(x, nrounds); |
| 627 | + |
| 628 | + memcpy(&stream[0], &x[0], 16); |
| 629 | + memcpy(&stream[4], &x[12], 16); |
| 630 | +} |
| 631 | +EXPORT_SYMBOL(hchacha_block_generic); |
| 632 | --- /dev/null |
| 633 | +++ b/lib/crypto/libchacha.c |
| 634 | @@ -0,0 +1,35 @@ |
| 635 | +// SPDX-License-Identifier: GPL-2.0-or-later |
| 636 | +/* |
| 637 | + * The ChaCha stream cipher (RFC7539) |
| 638 | + * |
| 639 | + * Copyright (C) 2015 Martin Willi |
| 640 | + */ |
| 641 | + |
| 642 | +#include <linux/kernel.h> |
| 643 | +#include <linux/export.h> |
| 644 | +#include <linux/module.h> |
| 645 | + |
| 646 | +#include <crypto/algapi.h> // for crypto_xor_cpy |
| 647 | +#include <crypto/chacha.h> |
| 648 | + |
| 649 | +void chacha_crypt_generic(u32 *state, u8 *dst, const u8 *src, |
| 650 | + unsigned int bytes, int nrounds) |
| 651 | +{ |
| 652 | + /* aligned to potentially speed up crypto_xor() */ |
| 653 | + u8 stream[CHACHA_BLOCK_SIZE] __aligned(sizeof(long)); |
| 654 | + |
| 655 | + while (bytes >= CHACHA_BLOCK_SIZE) { |
| 656 | + chacha_block_generic(state, stream, nrounds); |
| 657 | + crypto_xor_cpy(dst, src, stream, CHACHA_BLOCK_SIZE); |
| 658 | + bytes -= CHACHA_BLOCK_SIZE; |
| 659 | + dst += CHACHA_BLOCK_SIZE; |
| 660 | + src += CHACHA_BLOCK_SIZE; |
| 661 | + } |
| 662 | + if (bytes) { |
| 663 | + chacha_block_generic(state, stream, nrounds); |
| 664 | + crypto_xor_cpy(dst, src, stream, bytes); |
| 665 | + } |
| 666 | +} |
| 667 | +EXPORT_SYMBOL(chacha_crypt_generic); |
| 668 | + |
| 669 | +MODULE_LICENSE("GPL"); |