crypto: arc4 - refactor arc4 core code into separate library

Refactor the core rc4 handling so we can move most users to a library
interface, permitting us to drop the cipher interface entirely in a
future patch. This is part of an effort to simplify the crypto API
and improve its robustness against incorrect use.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
Ard Biesheuvel 2019-06-12 18:19:53 +02:00 committed by Herbert Xu
parent 192125ed5c
commit dc51f25752
7 changed files with 95 additions and 60 deletions

View File

@ -4229,6 +4229,7 @@ F: crypto/
F: drivers/crypto/ F: drivers/crypto/
F: include/crypto/ F: include/crypto/
F: include/linux/crypto* F: include/linux/crypto*
F: lib/crypto/
CRYPTOGRAPHIC RANDOM NUMBER GENERATOR CRYPTOGRAPHIC RANDOM NUMBER GENERATOR
M: Neil Horman <nhorman@tuxdriver.com> M: Neil Horman <nhorman@tuxdriver.com>

View File

@ -1237,9 +1237,13 @@ config CRYPTO_ANUBIS
<https://www.cosic.esat.kuleuven.be/nessie/reports/> <https://www.cosic.esat.kuleuven.be/nessie/reports/>
<http://www.larc.usp.br/~pbarreto/AnubisPage.html> <http://www.larc.usp.br/~pbarreto/AnubisPage.html>
config CRYPTO_LIB_ARC4
tristate
config CRYPTO_ARC4 config CRYPTO_ARC4
tristate "ARC4 cipher algorithm" tristate "ARC4 cipher algorithm"
select CRYPTO_BLKCIPHER select CRYPTO_BLKCIPHER
select CRYPTO_LIB_ARC4
help help
ARC4 cipher algorithm. ARC4 cipher algorithm.

View File

@ -18,33 +18,12 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
struct arc4_ctx {
u32 S[256];
u32 x, y;
};
static int arc4_set_key(struct crypto_tfm *tfm, const u8 *in_key, static int arc4_set_key(struct crypto_tfm *tfm, const u8 *in_key,
unsigned int key_len) unsigned int key_len)
{ {
struct arc4_ctx *ctx = crypto_tfm_ctx(tfm); struct arc4_ctx *ctx = crypto_tfm_ctx(tfm);
int i, j = 0, k = 0;
ctx->x = 1; return arc4_setkey(ctx, in_key, key_len);
ctx->y = 0;
for (i = 0; i < 256; i++)
ctx->S[i] = i;
for (i = 0; i < 256; i++) {
u32 a = ctx->S[i];
j = (j + in_key[k] + a) & 0xff;
ctx->S[i] = ctx->S[j];
ctx->S[j] = a;
if (++k >= key_len)
k = 0;
}
return 0;
} }
static int arc4_set_key_skcipher(struct crypto_skcipher *tfm, const u8 *in_key, static int arc4_set_key_skcipher(struct crypto_skcipher *tfm, const u8 *in_key,
@ -53,43 +32,6 @@ static int arc4_set_key_skcipher(struct crypto_skcipher *tfm, const u8 *in_key,
return arc4_set_key(&tfm->base, in_key, key_len); return arc4_set_key(&tfm->base, in_key, key_len);
} }
static void arc4_crypt(struct arc4_ctx *ctx, u8 *out, const u8 *in,
unsigned int len)
{
u32 *const S = ctx->S;
u32 x, y, a, b;
u32 ty, ta, tb;
if (len == 0)
return;
x = ctx->x;
y = ctx->y;
a = S[x];
y = (y + a) & 0xff;
b = S[y];
do {
S[y] = a;
a = (a + b) & 0xff;
S[x] = b;
x = (x + 1) & 0xff;
ta = S[x];
ty = (y + ta) & 0xff;
tb = S[ty];
*out++ = *in++ ^ S[a];
if (--len == 0)
break;
y = ty;
a = ta;
b = tb;
} while (true);
ctx->x = x;
ctx->y = y;
}
static void arc4_crypt_one(struct crypto_tfm *tfm, u8 *out, const u8 *in) static void arc4_crypt_one(struct crypto_tfm *tfm, u8 *out, const u8 *in)
{ {
arc4_crypt(crypto_tfm_ctx(tfm), out, in, 1); arc4_crypt(crypto_tfm_ctx(tfm), out, in, 1);

View File

@ -6,8 +6,18 @@
#ifndef _CRYPTO_ARC4_H #ifndef _CRYPTO_ARC4_H
#define _CRYPTO_ARC4_H #define _CRYPTO_ARC4_H
#include <linux/types.h>
#define ARC4_MIN_KEY_SIZE 1 #define ARC4_MIN_KEY_SIZE 1
#define ARC4_MAX_KEY_SIZE 256 #define ARC4_MAX_KEY_SIZE 256
#define ARC4_BLOCK_SIZE 1 #define ARC4_BLOCK_SIZE 1
struct arc4_ctx {
u32 S[256];
u32 x, y;
};
int arc4_setkey(struct arc4_ctx *ctx, const u8 *in_key, unsigned int key_len);
void arc4_crypt(struct arc4_ctx *ctx, u8 *out, const u8 *in, unsigned int len);
#endif /* _CRYPTO_ARC4_H */ #endif /* _CRYPTO_ARC4_H */

View File

@ -102,7 +102,7 @@ endif
obj-$(CONFIG_DEBUG_INFO_REDUCED) += debug_info.o obj-$(CONFIG_DEBUG_INFO_REDUCED) += debug_info.o
CFLAGS_debug_info.o += $(call cc-option, -femit-struct-debug-detailed=any) CFLAGS_debug_info.o += $(call cc-option, -femit-struct-debug-detailed=any)
obj-y += math/ obj-y += math/ crypto/
obj-$(CONFIG_GENERIC_IOMAP) += iomap.o obj-$(CONFIG_GENERIC_IOMAP) += iomap.o
obj-$(CONFIG_GENERIC_PCI_IOMAP) += pci_iomap.o obj-$(CONFIG_GENERIC_PCI_IOMAP) += pci_iomap.o

4
lib/crypto/Makefile Normal file
View File

@ -0,0 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_CRYPTO_LIB_ARC4) += libarc4.o
libarc4-y := arc4.o

74
lib/crypto/arc4.c Normal file
View File

@ -0,0 +1,74 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Cryptographic API
*
* ARC4 Cipher Algorithm
*
* Jon Oberheide <jon@oberheide.org>
*/
#include <crypto/arc4.h>
#include <linux/module.h>
int arc4_setkey(struct arc4_ctx *ctx, const u8 *in_key, unsigned int key_len)
{
int i, j = 0, k = 0;
ctx->x = 1;
ctx->y = 0;
for (i = 0; i < 256; i++)
ctx->S[i] = i;
for (i = 0; i < 256; i++) {
u32 a = ctx->S[i];
j = (j + in_key[k] + a) & 0xff;
ctx->S[i] = ctx->S[j];
ctx->S[j] = a;
if (++k >= key_len)
k = 0;
}
return 0;
}
EXPORT_SYMBOL(arc4_setkey);
void arc4_crypt(struct arc4_ctx *ctx, u8 *out, const u8 *in, unsigned int len)
{
u32 *const S = ctx->S;
u32 x, y, a, b;
u32 ty, ta, tb;
if (len == 0)
return;
x = ctx->x;
y = ctx->y;
a = S[x];
y = (y + a) & 0xff;
b = S[y];
do {
S[y] = a;
a = (a + b) & 0xff;
S[x] = b;
x = (x + 1) & 0xff;
ta = S[x];
ty = (y + ta) & 0xff;
tb = S[ty];
*out++ = *in++ ^ S[a];
if (--len == 0)
break;
y = ty;
a = ta;
b = tb;
} while (true);
ctx->x = x;
ctx->y = y;
}
EXPORT_SYMBOL(arc4_crypt);
MODULE_LICENSE("GPL");