Merge git://github.com/herbertx/crypto
* git://github.com/herbertx/crypto: (48 commits) crypto: user - Depend on NET instead of selecting it crypto: user - Add dependency on NET crypto: talitos - handle descriptor not found in error path crypto: user - Initialise match in crypto_alg_match crypto: testmgr - add twofish tests crypto: testmgr - add blowfish test-vectors crypto: Make hifn_795x build depend on !ARCH_DMA_ADDR_T_64BIT crypto: twofish-x86_64-3way - fix ctr blocksize to 1 crypto: blowfish-x86_64 - fix ctr blocksize to 1 crypto: whirlpool - count rounds from 0 crypto: Add userspace report for compress type algorithms crypto: Add userspace report for cipher type algorithms crypto: Add userspace report for rng type algorithms crypto: Add userspace report for pcompress type algorithms crypto: Add userspace report for nivaead type algorithms crypto: Add userspace report for aead type algorithms crypto: Add userspace report for givcipher type algorithms crypto: Add userspace report for ablkcipher type algorithms crypto: Add userspace report for blkcipher type algorithms crypto: Add userspace report for ahash type algorithms ...
This commit is contained in:
commit
dc47d3810c
23
Documentation/devicetree/bindings/crypto/picochip-spacc.txt
Normal file
23
Documentation/devicetree/bindings/crypto/picochip-spacc.txt
Normal file
@ -0,0 +1,23 @@
|
||||
Picochip picoXcell SPAcc (Security Protocol Accelerator) bindings
|
||||
|
||||
Picochip picoXcell devices contain crypto offload engines that may be used for
|
||||
IPSEC and femtocell layer 2 ciphering.
|
||||
|
||||
Required properties:
|
||||
- compatible : "picochip,spacc-ipsec" for the IPSEC offload engine
|
||||
"picochip,spacc-l2" for the femtocell layer 2 ciphering engine.
|
||||
- reg : Offset and length of the register set for this device
|
||||
- interrupt-parent : The interrupt controller that controls the SPAcc
|
||||
interrupt.
|
||||
- interrupts : The interrupt line from the SPAcc.
|
||||
- ref-clock : The input clock that drives the SPAcc.
|
||||
|
||||
Example SPAcc node:
|
||||
|
||||
spacc@10000 {
|
||||
compatible = "picochip,spacc-ipsec";
|
||||
reg = <0x100000 0x10000>;
|
||||
interrupt-parent = <&vic0>;
|
||||
interrupts = <24>;
|
||||
ref-clock = <&ipsec_clk>, "ref";
|
||||
};
|
@ -7,21 +7,33 @@ obj-$(CONFIG_CRYPTO_TWOFISH_586) += twofish-i586.o
|
||||
obj-$(CONFIG_CRYPTO_SALSA20_586) += salsa20-i586.o
|
||||
|
||||
obj-$(CONFIG_CRYPTO_AES_X86_64) += aes-x86_64.o
|
||||
obj-$(CONFIG_CRYPTO_BLOWFISH_X86_64) += blowfish-x86_64.o
|
||||
obj-$(CONFIG_CRYPTO_TWOFISH_X86_64) += twofish-x86_64.o
|
||||
obj-$(CONFIG_CRYPTO_TWOFISH_X86_64_3WAY) += twofish-x86_64-3way.o
|
||||
obj-$(CONFIG_CRYPTO_SALSA20_X86_64) += salsa20-x86_64.o
|
||||
obj-$(CONFIG_CRYPTO_AES_NI_INTEL) += aesni-intel.o
|
||||
obj-$(CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL) += ghash-clmulni-intel.o
|
||||
|
||||
obj-$(CONFIG_CRYPTO_CRC32C_INTEL) += crc32c-intel.o
|
||||
obj-$(CONFIG_CRYPTO_SHA1_SSSE3) += sha1-ssse3.o
|
||||
|
||||
aes-i586-y := aes-i586-asm_32.o aes_glue.o
|
||||
twofish-i586-y := twofish-i586-asm_32.o twofish_glue.o
|
||||
salsa20-i586-y := salsa20-i586-asm_32.o salsa20_glue.o
|
||||
|
||||
aes-x86_64-y := aes-x86_64-asm_64.o aes_glue.o
|
||||
blowfish-x86_64-y := blowfish-x86_64-asm_64.o blowfish_glue.o
|
||||
twofish-x86_64-y := twofish-x86_64-asm_64.o twofish_glue.o
|
||||
twofish-x86_64-3way-y := twofish-x86_64-asm_64-3way.o twofish_glue_3way.o
|
||||
salsa20-x86_64-y := salsa20-x86_64-asm_64.o salsa20_glue.o
|
||||
|
||||
aesni-intel-y := aesni-intel_asm.o aesni-intel_glue.o fpu.o
|
||||
|
||||
ghash-clmulni-intel-y := ghash-clmulni-intel_asm.o ghash-clmulni-intel_glue.o
|
||||
|
||||
# enable AVX support only when $(AS) can actually assemble the instructions
|
||||
ifeq ($(call as-instr,vpxor %xmm0$(comma)%xmm1$(comma)%xmm2,yes,no),yes)
|
||||
AFLAGS_sha1_ssse3_asm.o += -DSHA1_ENABLE_AVX_SUPPORT
|
||||
CFLAGS_sha1_ssse3_glue.o += -DSHA1_ENABLE_AVX_SUPPORT
|
||||
endif
|
||||
sha1-ssse3-y := sha1_ssse3_asm.o sha1_ssse3_glue.o
|
||||
|
@ -4,6 +4,7 @@
|
||||
*/
|
||||
|
||||
#include <crypto/aes.h>
|
||||
#include <asm/aes.h>
|
||||
|
||||
asmlinkage void aes_enc_blk(struct crypto_aes_ctx *ctx, u8 *out, const u8 *in);
|
||||
asmlinkage void aes_dec_blk(struct crypto_aes_ctx *ctx, u8 *out, const u8 *in);
|
||||
|
390
arch/x86/crypto/blowfish-x86_64-asm_64.S
Normal file
390
arch/x86/crypto/blowfish-x86_64-asm_64.S
Normal file
@ -0,0 +1,390 @@
|
||||
/*
|
||||
* Blowfish Cipher Algorithm (x86_64)
|
||||
*
|
||||
* Copyright (C) 2011 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA
|
||||
*
|
||||
*/
|
||||
|
||||
.file "blowfish-x86_64-asm.S"
|
||||
.text
|
||||
|
||||
/* structure of crypto context */
|
||||
#define p 0
|
||||
#define s0 ((16 + 2) * 4)
|
||||
#define s1 ((16 + 2 + (1 * 256)) * 4)
|
||||
#define s2 ((16 + 2 + (2 * 256)) * 4)
|
||||
#define s3 ((16 + 2 + (3 * 256)) * 4)
|
||||
|
||||
/* register macros */
|
||||
#define CTX %rdi
|
||||
#define RIO %rsi
|
||||
|
||||
#define RX0 %rax
|
||||
#define RX1 %rbx
|
||||
#define RX2 %rcx
|
||||
#define RX3 %rdx
|
||||
|
||||
#define RX0d %eax
|
||||
#define RX1d %ebx
|
||||
#define RX2d %ecx
|
||||
#define RX3d %edx
|
||||
|
||||
#define RX0bl %al
|
||||
#define RX1bl %bl
|
||||
#define RX2bl %cl
|
||||
#define RX3bl %dl
|
||||
|
||||
#define RX0bh %ah
|
||||
#define RX1bh %bh
|
||||
#define RX2bh %ch
|
||||
#define RX3bh %dh
|
||||
|
||||
#define RT0 %rbp
|
||||
#define RT1 %rsi
|
||||
#define RT2 %r8
|
||||
#define RT3 %r9
|
||||
|
||||
#define RT0d %ebp
|
||||
#define RT1d %esi
|
||||
#define RT2d %r8d
|
||||
#define RT3d %r9d
|
||||
|
||||
#define RKEY %r10
|
||||
|
||||
/***********************************************************************
|
||||
* 1-way blowfish
|
||||
***********************************************************************/
|
||||
#define F() \
|
||||
rorq $16, RX0; \
|
||||
movzbl RX0bh, RT0d; \
|
||||
movzbl RX0bl, RT1d; \
|
||||
rolq $16, RX0; \
|
||||
movl s0(CTX,RT0,4), RT0d; \
|
||||
addl s1(CTX,RT1,4), RT0d; \
|
||||
movzbl RX0bh, RT1d; \
|
||||
movzbl RX0bl, RT2d; \
|
||||
rolq $32, RX0; \
|
||||
xorl s2(CTX,RT1,4), RT0d; \
|
||||
addl s3(CTX,RT2,4), RT0d; \
|
||||
xorq RT0, RX0;
|
||||
|
||||
#define add_roundkey_enc(n) \
|
||||
xorq p+4*(n)(CTX), RX0;
|
||||
|
||||
#define round_enc(n) \
|
||||
add_roundkey_enc(n); \
|
||||
\
|
||||
F(); \
|
||||
F();
|
||||
|
||||
#define add_roundkey_dec(n) \
|
||||
movq p+4*(n-1)(CTX), RT0; \
|
||||
rorq $32, RT0; \
|
||||
xorq RT0, RX0;
|
||||
|
||||
#define round_dec(n) \
|
||||
add_roundkey_dec(n); \
|
||||
\
|
||||
F(); \
|
||||
F(); \
|
||||
|
||||
#define read_block() \
|
||||
movq (RIO), RX0; \
|
||||
rorq $32, RX0; \
|
||||
bswapq RX0;
|
||||
|
||||
#define write_block() \
|
||||
bswapq RX0; \
|
||||
movq RX0, (RIO);
|
||||
|
||||
#define xor_block() \
|
||||
bswapq RX0; \
|
||||
xorq RX0, (RIO);
|
||||
|
||||
.align 8
|
||||
.global __blowfish_enc_blk
|
||||
.type __blowfish_enc_blk,@function;
|
||||
|
||||
__blowfish_enc_blk:
|
||||
/* input:
|
||||
* %rdi: ctx, CTX
|
||||
* %rsi: dst
|
||||
* %rdx: src
|
||||
* %rcx: bool, if true: xor output
|
||||
*/
|
||||
movq %rbp, %r11;
|
||||
|
||||
movq %rsi, %r10;
|
||||
movq %rdx, RIO;
|
||||
|
||||
read_block();
|
||||
|
||||
round_enc(0);
|
||||
round_enc(2);
|
||||
round_enc(4);
|
||||
round_enc(6);
|
||||
round_enc(8);
|
||||
round_enc(10);
|
||||
round_enc(12);
|
||||
round_enc(14);
|
||||
add_roundkey_enc(16);
|
||||
|
||||
movq %r11, %rbp;
|
||||
|
||||
movq %r10, RIO;
|
||||
test %cl, %cl;
|
||||
jnz __enc_xor;
|
||||
|
||||
write_block();
|
||||
ret;
|
||||
__enc_xor:
|
||||
xor_block();
|
||||
ret;
|
||||
|
||||
.align 8
|
||||
.global blowfish_dec_blk
|
||||
.type blowfish_dec_blk,@function;
|
||||
|
||||
blowfish_dec_blk:
|
||||
/* input:
|
||||
* %rdi: ctx, CTX
|
||||
* %rsi: dst
|
||||
* %rdx: src
|
||||
*/
|
||||
movq %rbp, %r11;
|
||||
|
||||
movq %rsi, %r10;
|
||||
movq %rdx, RIO;
|
||||
|
||||
read_block();
|
||||
|
||||
round_dec(17);
|
||||
round_dec(15);
|
||||
round_dec(13);
|
||||
round_dec(11);
|
||||
round_dec(9);
|
||||
round_dec(7);
|
||||
round_dec(5);
|
||||
round_dec(3);
|
||||
add_roundkey_dec(1);
|
||||
|
||||
movq %r10, RIO;
|
||||
write_block();
|
||||
|
||||
movq %r11, %rbp;
|
||||
|
||||
ret;
|
||||
|
||||
/**********************************************************************
|
||||
4-way blowfish, four blocks parallel
|
||||
**********************************************************************/
|
||||
|
||||
/* F() for 4-way. Slower when used alone/1-way, but faster when used
|
||||
* parallel/4-way (tested on AMD Phenom II & Intel Xeon E7330).
|
||||
*/
|
||||
#define F4(x) \
|
||||
movzbl x ## bh, RT1d; \
|
||||
movzbl x ## bl, RT3d; \
|
||||
rorq $16, x; \
|
||||
movzbl x ## bh, RT0d; \
|
||||
movzbl x ## bl, RT2d; \
|
||||
rorq $16, x; \
|
||||
movl s0(CTX,RT0,4), RT0d; \
|
||||
addl s1(CTX,RT2,4), RT0d; \
|
||||
xorl s2(CTX,RT1,4), RT0d; \
|
||||
addl s3(CTX,RT3,4), RT0d; \
|
||||
xorq RT0, x;
|
||||
|
||||
#define add_preloaded_roundkey4() \
|
||||
xorq RKEY, RX0; \
|
||||
xorq RKEY, RX1; \
|
||||
xorq RKEY, RX2; \
|
||||
xorq RKEY, RX3;
|
||||
|
||||
#define preload_roundkey_enc(n) \
|
||||
movq p+4*(n)(CTX), RKEY;
|
||||
|
||||
#define add_roundkey_enc4(n) \
|
||||
add_preloaded_roundkey4(); \
|
||||
preload_roundkey_enc(n + 2);
|
||||
|
||||
#define round_enc4(n) \
|
||||
add_roundkey_enc4(n); \
|
||||
\
|
||||
F4(RX0); \
|
||||
F4(RX1); \
|
||||
F4(RX2); \
|
||||
F4(RX3); \
|
||||
\
|
||||
F4(RX0); \
|
||||
F4(RX1); \
|
||||
F4(RX2); \
|
||||
F4(RX3);
|
||||
|
||||
#define preload_roundkey_dec(n) \
|
||||
movq p+4*((n)-1)(CTX), RKEY; \
|
||||
rorq $32, RKEY;
|
||||
|
||||
#define add_roundkey_dec4(n) \
|
||||
add_preloaded_roundkey4(); \
|
||||
preload_roundkey_dec(n - 2);
|
||||
|
||||
#define round_dec4(n) \
|
||||
add_roundkey_dec4(n); \
|
||||
\
|
||||
F4(RX0); \
|
||||
F4(RX1); \
|
||||
F4(RX2); \
|
||||
F4(RX3); \
|
||||
\
|
||||
F4(RX0); \
|
||||
F4(RX1); \
|
||||
F4(RX2); \
|
||||
F4(RX3);
|
||||
|
||||
#define read_block4() \
|
||||
movq (RIO), RX0; \
|
||||
rorq $32, RX0; \
|
||||
bswapq RX0; \
|
||||
\
|
||||
movq 8(RIO), RX1; \
|
||||
rorq $32, RX1; \
|
||||
bswapq RX1; \
|
||||
\
|
||||
movq 16(RIO), RX2; \
|
||||
rorq $32, RX2; \
|
||||
bswapq RX2; \
|
||||
\
|
||||
movq 24(RIO), RX3; \
|
||||
rorq $32, RX3; \
|
||||
bswapq RX3;
|
||||
|
||||
#define write_block4() \
|
||||
bswapq RX0; \
|
||||
movq RX0, (RIO); \
|
||||
\
|
||||
bswapq RX1; \
|
||||
movq RX1, 8(RIO); \
|
||||
\
|
||||
bswapq RX2; \
|
||||
movq RX2, 16(RIO); \
|
||||
\
|
||||
bswapq RX3; \
|
||||
movq RX3, 24(RIO);
|
||||
|
||||
#define xor_block4() \
|
||||
bswapq RX0; \
|
||||
xorq RX0, (RIO); \
|
||||
\
|
||||
bswapq RX1; \
|
||||
xorq RX1, 8(RIO); \
|
||||
\
|
||||
bswapq RX2; \
|
||||
xorq RX2, 16(RIO); \
|
||||
\
|
||||
bswapq RX3; \
|
||||
xorq RX3, 24(RIO);
|
||||
|
||||
.align 8
|
||||
.global __blowfish_enc_blk_4way
|
||||
.type __blowfish_enc_blk_4way,@function;
|
||||
|
||||
__blowfish_enc_blk_4way:
|
||||
/* input:
|
||||
* %rdi: ctx, CTX
|
||||
* %rsi: dst
|
||||
* %rdx: src
|
||||
* %rcx: bool, if true: xor output
|
||||
*/
|
||||
pushq %rbp;
|
||||
pushq %rbx;
|
||||
pushq %rcx;
|
||||
|
||||
preload_roundkey_enc(0);
|
||||
|
||||
movq %rsi, %r11;
|
||||
movq %rdx, RIO;
|
||||
|
||||
read_block4();
|
||||
|
||||
round_enc4(0);
|
||||
round_enc4(2);
|
||||
round_enc4(4);
|
||||
round_enc4(6);
|
||||
round_enc4(8);
|
||||
round_enc4(10);
|
||||
round_enc4(12);
|
||||
round_enc4(14);
|
||||
add_preloaded_roundkey4();
|
||||
|
||||
popq %rbp;
|
||||
movq %r11, RIO;
|
||||
|
||||
test %bpl, %bpl;
|
||||
jnz __enc_xor4;
|
||||
|
||||
write_block4();
|
||||
|
||||
popq %rbx;
|
||||
popq %rbp;
|
||||
ret;
|
||||
|
||||
__enc_xor4:
|
||||
xor_block4();
|
||||
|
||||
popq %rbx;
|
||||
popq %rbp;
|
||||
ret;
|
||||
|
||||
.align 8
|
||||
.global blowfish_dec_blk_4way
|
||||
.type blowfish_dec_blk_4way,@function;
|
||||
|
||||
blowfish_dec_blk_4way:
|
||||
/* input:
|
||||
* %rdi: ctx, CTX
|
||||
* %rsi: dst
|
||||
* %rdx: src
|
||||
*/
|
||||
pushq %rbp;
|
||||
pushq %rbx;
|
||||
preload_roundkey_dec(17);
|
||||
|
||||
movq %rsi, %r11;
|
||||
movq %rdx, RIO;
|
||||
|
||||
read_block4();
|
||||
|
||||
round_dec4(17);
|
||||
round_dec4(15);
|
||||
round_dec4(13);
|
||||
round_dec4(11);
|
||||
round_dec4(9);
|
||||
round_dec4(7);
|
||||
round_dec4(5);
|
||||
round_dec4(3);
|
||||
add_preloaded_roundkey4();
|
||||
|
||||
movq %r11, RIO;
|
||||
write_block4();
|
||||
|
||||
popq %rbx;
|
||||
popq %rbp;
|
||||
|
||||
ret;
|
||||
|
492
arch/x86/crypto/blowfish_glue.c
Normal file
492
arch/x86/crypto/blowfish_glue.c
Normal file
@ -0,0 +1,492 @@
|
||||
/*
|
||||
* Glue Code for assembler optimized version of Blowfish
|
||||
*
|
||||
* Copyright (c) 2011 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
|
||||
*
|
||||
* CBC & ECB parts based on code (crypto/cbc.c,ecb.c) by:
|
||||
* Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
|
||||
* CTR part based on code (crypto/ctr.c) by:
|
||||
* (C) Copyright IBM Corp. 2007 - Joy Latten <latten@us.ibm.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <crypto/blowfish.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <crypto/algapi.h>
|
||||
|
||||
/* regular block cipher functions */
|
||||
asmlinkage void __blowfish_enc_blk(struct bf_ctx *ctx, u8 *dst, const u8 *src,
|
||||
bool xor);
|
||||
asmlinkage void blowfish_dec_blk(struct bf_ctx *ctx, u8 *dst, const u8 *src);
|
||||
|
||||
/* 4-way parallel cipher functions */
|
||||
asmlinkage void __blowfish_enc_blk_4way(struct bf_ctx *ctx, u8 *dst,
|
||||
const u8 *src, bool xor);
|
||||
asmlinkage void blowfish_dec_blk_4way(struct bf_ctx *ctx, u8 *dst,
|
||||
const u8 *src);
|
||||
|
||||
static inline void blowfish_enc_blk(struct bf_ctx *ctx, u8 *dst, const u8 *src)
|
||||
{
|
||||
__blowfish_enc_blk(ctx, dst, src, false);
|
||||
}
|
||||
|
||||
static inline void blowfish_enc_blk_xor(struct bf_ctx *ctx, u8 *dst,
|
||||
const u8 *src)
|
||||
{
|
||||
__blowfish_enc_blk(ctx, dst, src, true);
|
||||
}
|
||||
|
||||
static inline void blowfish_enc_blk_4way(struct bf_ctx *ctx, u8 *dst,
|
||||
const u8 *src)
|
||||
{
|
||||
__blowfish_enc_blk_4way(ctx, dst, src, false);
|
||||
}
|
||||
|
||||
static inline void blowfish_enc_blk_xor_4way(struct bf_ctx *ctx, u8 *dst,
|
||||
const u8 *src)
|
||||
{
|
||||
__blowfish_enc_blk_4way(ctx, dst, src, true);
|
||||
}
|
||||
|
||||
static void blowfish_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
|
||||
{
|
||||
blowfish_enc_blk(crypto_tfm_ctx(tfm), dst, src);
|
||||
}
|
||||
|
||||
static void blowfish_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
|
||||
{
|
||||
blowfish_dec_blk(crypto_tfm_ctx(tfm), dst, src);
|
||||
}
|
||||
|
||||
static struct crypto_alg bf_alg = {
|
||||
.cra_name = "blowfish",
|
||||
.cra_driver_name = "blowfish-asm",
|
||||
.cra_priority = 200,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
|
||||
.cra_blocksize = BF_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct bf_ctx),
|
||||
.cra_alignmask = 3,
|
||||
.cra_module = THIS_MODULE,
|
||||
.cra_list = LIST_HEAD_INIT(bf_alg.cra_list),
|
||||
.cra_u = {
|
||||
.cipher = {
|
||||
.cia_min_keysize = BF_MIN_KEY_SIZE,
|
||||
.cia_max_keysize = BF_MAX_KEY_SIZE,
|
||||
.cia_setkey = blowfish_setkey,
|
||||
.cia_encrypt = blowfish_encrypt,
|
||||
.cia_decrypt = blowfish_decrypt,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk,
|
||||
void (*fn)(struct bf_ctx *, u8 *, const u8 *),
|
||||
void (*fn_4way)(struct bf_ctx *, u8 *, const u8 *))
|
||||
{
|
||||
struct bf_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
|
||||
unsigned int bsize = BF_BLOCK_SIZE;
|
||||
unsigned int nbytes;
|
||||
int err;
|
||||
|
||||
err = blkcipher_walk_virt(desc, walk);
|
||||
|
||||
while ((nbytes = walk->nbytes)) {
|
||||
u8 *wsrc = walk->src.virt.addr;
|
||||
u8 *wdst = walk->dst.virt.addr;
|
||||
|
||||
/* Process four block batch */
|
||||
if (nbytes >= bsize * 4) {
|
||||
do {
|
||||
fn_4way(ctx, wdst, wsrc);
|
||||
|
||||
wsrc += bsize * 4;
|
||||
wdst += bsize * 4;
|
||||
nbytes -= bsize * 4;
|
||||
} while (nbytes >= bsize * 4);
|
||||
|
||||
if (nbytes < bsize)
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Handle leftovers */
|
||||
do {
|
||||
fn(ctx, wdst, wsrc);
|
||||
|
||||
wsrc += bsize;
|
||||
wdst += bsize;
|
||||
nbytes -= bsize;
|
||||
} while (nbytes >= bsize);
|
||||
|
||||
done:
|
||||
err = blkcipher_walk_done(desc, walk, nbytes);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
|
||||
struct scatterlist *src, unsigned int nbytes)
|
||||
{
|
||||
struct blkcipher_walk walk;
|
||||
|
||||
blkcipher_walk_init(&walk, dst, src, nbytes);
|
||||
return ecb_crypt(desc, &walk, blowfish_enc_blk, blowfish_enc_blk_4way);
|
||||
}
|
||||
|
||||
static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
|
||||
struct scatterlist *src, unsigned int nbytes)
|
||||
{
|
||||
struct blkcipher_walk walk;
|
||||
|
||||
blkcipher_walk_init(&walk, dst, src, nbytes);
|
||||
return ecb_crypt(desc, &walk, blowfish_dec_blk, blowfish_dec_blk_4way);
|
||||
}
|
||||
|
||||
static struct crypto_alg blk_ecb_alg = {
|
||||
.cra_name = "ecb(blowfish)",
|
||||
.cra_driver_name = "ecb-blowfish-asm",
|
||||
.cra_priority = 300,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
|
||||
.cra_blocksize = BF_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct bf_ctx),
|
||||
.cra_alignmask = 0,
|
||||
.cra_type = &crypto_blkcipher_type,
|
||||
.cra_module = THIS_MODULE,
|
||||
.cra_list = LIST_HEAD_INIT(blk_ecb_alg.cra_list),
|
||||
.cra_u = {
|
||||
.blkcipher = {
|
||||
.min_keysize = BF_MIN_KEY_SIZE,
|
||||
.max_keysize = BF_MAX_KEY_SIZE,
|
||||
.setkey = blowfish_setkey,
|
||||
.encrypt = ecb_encrypt,
|
||||
.decrypt = ecb_decrypt,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static unsigned int __cbc_encrypt(struct blkcipher_desc *desc,
|
||||
struct blkcipher_walk *walk)
|
||||
{
|
||||
struct bf_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
|
||||
unsigned int bsize = BF_BLOCK_SIZE;
|
||||
unsigned int nbytes = walk->nbytes;
|
||||
u64 *src = (u64 *)walk->src.virt.addr;
|
||||
u64 *dst = (u64 *)walk->dst.virt.addr;
|
||||
u64 *iv = (u64 *)walk->iv;
|
||||
|
||||
do {
|
||||
*dst = *src ^ *iv;
|
||||
blowfish_enc_blk(ctx, (u8 *)dst, (u8 *)dst);
|
||||
iv = dst;
|
||||
|
||||
src += 1;
|
||||
dst += 1;
|
||||
nbytes -= bsize;
|
||||
} while (nbytes >= bsize);
|
||||
|
||||
*(u64 *)walk->iv = *iv;
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
|
||||
struct scatterlist *src, unsigned int nbytes)
|
||||
{
|
||||
struct blkcipher_walk walk;
|
||||
int err;
|
||||
|
||||
blkcipher_walk_init(&walk, dst, src, nbytes);
|
||||
err = blkcipher_walk_virt(desc, &walk);
|
||||
|
||||
while ((nbytes = walk.nbytes)) {
|
||||
nbytes = __cbc_encrypt(desc, &walk);
|
||||
err = blkcipher_walk_done(desc, &walk, nbytes);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static unsigned int __cbc_decrypt(struct blkcipher_desc *desc,
|
||||
struct blkcipher_walk *walk)
|
||||
{
|
||||
struct bf_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
|
||||
unsigned int bsize = BF_BLOCK_SIZE;
|
||||
unsigned int nbytes = walk->nbytes;
|
||||
u64 *src = (u64 *)walk->src.virt.addr;
|
||||
u64 *dst = (u64 *)walk->dst.virt.addr;
|
||||
u64 ivs[4 - 1];
|
||||
u64 last_iv;
|
||||
|
||||
/* Start of the last block. */
|
||||
src += nbytes / bsize - 1;
|
||||
dst += nbytes / bsize - 1;
|
||||
|
||||
last_iv = *src;
|
||||
|
||||
/* Process four block batch */
|
||||
if (nbytes >= bsize * 4) {
|
||||
do {
|
||||
nbytes -= bsize * 4 - bsize;
|
||||
src -= 4 - 1;
|
||||
dst -= 4 - 1;
|
||||
|
||||
ivs[0] = src[0];
|
||||
ivs[1] = src[1];
|
||||
ivs[2] = src[2];
|
||||
|
||||
blowfish_dec_blk_4way(ctx, (u8 *)dst, (u8 *)src);
|
||||
|
||||
dst[1] ^= ivs[0];
|
||||
dst[2] ^= ivs[1];
|
||||
dst[3] ^= ivs[2];
|
||||
|
||||
nbytes -= bsize;
|
||||
if (nbytes < bsize)
|
||||
goto done;
|
||||
|
||||
*dst ^= *(src - 1);
|
||||
src -= 1;
|
||||
dst -= 1;
|
||||
} while (nbytes >= bsize * 4);
|
||||
|
||||
if (nbytes < bsize)
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Handle leftovers */
|
||||
for (;;) {
|
||||
blowfish_dec_blk(ctx, (u8 *)dst, (u8 *)src);
|
||||
|
||||
nbytes -= bsize;
|
||||
if (nbytes < bsize)
|
||||
break;
|
||||
|
||||
*dst ^= *(src - 1);
|
||||
src -= 1;
|
||||
dst -= 1;
|
||||
}
|
||||
|
||||
done:
|
||||
*dst ^= *(u64 *)walk->iv;
|
||||
*(u64 *)walk->iv = last_iv;
|
||||
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
|
||||
struct scatterlist *src, unsigned int nbytes)
|
||||
{
|
||||
struct blkcipher_walk walk;
|
||||
int err;
|
||||
|
||||
blkcipher_walk_init(&walk, dst, src, nbytes);
|
||||
err = blkcipher_walk_virt(desc, &walk);
|
||||
|
||||
while ((nbytes = walk.nbytes)) {
|
||||
nbytes = __cbc_decrypt(desc, &walk);
|
||||
err = blkcipher_walk_done(desc, &walk, nbytes);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct crypto_alg blk_cbc_alg = {
|
||||
.cra_name = "cbc(blowfish)",
|
||||
.cra_driver_name = "cbc-blowfish-asm",
|
||||
.cra_priority = 300,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
|
||||
.cra_blocksize = BF_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct bf_ctx),
|
||||
.cra_alignmask = 0,
|
||||
.cra_type = &crypto_blkcipher_type,
|
||||
.cra_module = THIS_MODULE,
|
||||
.cra_list = LIST_HEAD_INIT(blk_cbc_alg.cra_list),
|
||||
.cra_u = {
|
||||
.blkcipher = {
|
||||
.min_keysize = BF_MIN_KEY_SIZE,
|
||||
.max_keysize = BF_MAX_KEY_SIZE,
|
||||
.ivsize = BF_BLOCK_SIZE,
|
||||
.setkey = blowfish_setkey,
|
||||
.encrypt = cbc_encrypt,
|
||||
.decrypt = cbc_decrypt,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static void ctr_crypt_final(struct bf_ctx *ctx, struct blkcipher_walk *walk)
|
||||
{
|
||||
u8 *ctrblk = walk->iv;
|
||||
u8 keystream[BF_BLOCK_SIZE];
|
||||
u8 *src = walk->src.virt.addr;
|
||||
u8 *dst = walk->dst.virt.addr;
|
||||
unsigned int nbytes = walk->nbytes;
|
||||
|
||||
blowfish_enc_blk(ctx, keystream, ctrblk);
|
||||
crypto_xor(keystream, src, nbytes);
|
||||
memcpy(dst, keystream, nbytes);
|
||||
|
||||
crypto_inc(ctrblk, BF_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
static unsigned int __ctr_crypt(struct blkcipher_desc *desc,
|
||||
struct blkcipher_walk *walk)
|
||||
{
|
||||
struct bf_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
|
||||
unsigned int bsize = BF_BLOCK_SIZE;
|
||||
unsigned int nbytes = walk->nbytes;
|
||||
u64 *src = (u64 *)walk->src.virt.addr;
|
||||
u64 *dst = (u64 *)walk->dst.virt.addr;
|
||||
u64 ctrblk = be64_to_cpu(*(__be64 *)walk->iv);
|
||||
__be64 ctrblocks[4];
|
||||
|
||||
/* Process four block batch */
|
||||
if (nbytes >= bsize * 4) {
|
||||
do {
|
||||
if (dst != src) {
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[1];
|
||||
dst[2] = src[2];
|
||||
dst[3] = src[3];
|
||||
}
|
||||
|
||||
/* create ctrblks for parallel encrypt */
|
||||
ctrblocks[0] = cpu_to_be64(ctrblk++);
|
||||
ctrblocks[1] = cpu_to_be64(ctrblk++);
|
||||
ctrblocks[2] = cpu_to_be64(ctrblk++);
|
||||
ctrblocks[3] = cpu_to_be64(ctrblk++);
|
||||
|
||||
blowfish_enc_blk_xor_4way(ctx, (u8 *)dst,
|
||||
(u8 *)ctrblocks);
|
||||
|
||||
src += 4;
|
||||
dst += 4;
|
||||
} while ((nbytes -= bsize * 4) >= bsize * 4);
|
||||
|
||||
if (nbytes < bsize)
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Handle leftovers */
|
||||
do {
|
||||
if (dst != src)
|
||||
*dst = *src;
|
||||
|
||||
ctrblocks[0] = cpu_to_be64(ctrblk++);
|
||||
|
||||
blowfish_enc_blk_xor(ctx, (u8 *)dst, (u8 *)ctrblocks);
|
||||
|
||||
src += 1;
|
||||
dst += 1;
|
||||
} while ((nbytes -= bsize) >= bsize);
|
||||
|
||||
done:
|
||||
*(__be64 *)walk->iv = cpu_to_be64(ctrblk);
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
static int ctr_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
|
||||
struct scatterlist *src, unsigned int nbytes)
|
||||
{
|
||||
struct blkcipher_walk walk;
|
||||
int err;
|
||||
|
||||
blkcipher_walk_init(&walk, dst, src, nbytes);
|
||||
err = blkcipher_walk_virt_block(desc, &walk, BF_BLOCK_SIZE);
|
||||
|
||||
while ((nbytes = walk.nbytes) >= BF_BLOCK_SIZE) {
|
||||
nbytes = __ctr_crypt(desc, &walk);
|
||||
err = blkcipher_walk_done(desc, &walk, nbytes);
|
||||
}
|
||||
|
||||
if (walk.nbytes) {
|
||||
ctr_crypt_final(crypto_blkcipher_ctx(desc->tfm), &walk);
|
||||
err = blkcipher_walk_done(desc, &walk, 0);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct crypto_alg blk_ctr_alg = {
|
||||
.cra_name = "ctr(blowfish)",
|
||||
.cra_driver_name = "ctr-blowfish-asm",
|
||||
.cra_priority = 300,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
|
||||
.cra_blocksize = 1,
|
||||
.cra_ctxsize = sizeof(struct bf_ctx),
|
||||
.cra_alignmask = 0,
|
||||
.cra_type = &crypto_blkcipher_type,
|
||||
.cra_module = THIS_MODULE,
|
||||
.cra_list = LIST_HEAD_INIT(blk_ctr_alg.cra_list),
|
||||
.cra_u = {
|
||||
.blkcipher = {
|
||||
.min_keysize = BF_MIN_KEY_SIZE,
|
||||
.max_keysize = BF_MAX_KEY_SIZE,
|
||||
.ivsize = BF_BLOCK_SIZE,
|
||||
.setkey = blowfish_setkey,
|
||||
.encrypt = ctr_crypt,
|
||||
.decrypt = ctr_crypt,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static int __init init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = crypto_register_alg(&bf_alg);
|
||||
if (err)
|
||||
goto bf_err;
|
||||
err = crypto_register_alg(&blk_ecb_alg);
|
||||
if (err)
|
||||
goto ecb_err;
|
||||
err = crypto_register_alg(&blk_cbc_alg);
|
||||
if (err)
|
||||
goto cbc_err;
|
||||
err = crypto_register_alg(&blk_ctr_alg);
|
||||
if (err)
|
||||
goto ctr_err;
|
||||
|
||||
return 0;
|
||||
|
||||
ctr_err:
|
||||
crypto_unregister_alg(&blk_cbc_alg);
|
||||
cbc_err:
|
||||
crypto_unregister_alg(&blk_ecb_alg);
|
||||
ecb_err:
|
||||
crypto_unregister_alg(&bf_alg);
|
||||
bf_err:
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __exit fini(void)
|
||||
{
|
||||
crypto_unregister_alg(&blk_ctr_alg);
|
||||
crypto_unregister_alg(&blk_cbc_alg);
|
||||
crypto_unregister_alg(&blk_ecb_alg);
|
||||
crypto_unregister_alg(&bf_alg);
|
||||
}
|
||||
|
||||
module_init(init);
|
||||
module_exit(fini);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Blowfish Cipher Algorithm, asm optimized");
|
||||
MODULE_ALIAS("blowfish");
|
||||
MODULE_ALIAS("blowfish-asm");
|
558
arch/x86/crypto/sha1_ssse3_asm.S
Normal file
558
arch/x86/crypto/sha1_ssse3_asm.S
Normal file
@ -0,0 +1,558 @@
|
||||
/*
|
||||
* This is a SIMD SHA-1 implementation. It requires the Intel(R) Supplemental
|
||||
* SSE3 instruction set extensions introduced in Intel Core Microarchitecture
|
||||
* processors. CPUs supporting Intel(R) AVX extensions will get an additional
|
||||
* boost.
|
||||
*
|
||||
* This work was inspired by the vectorized implementation of Dean Gaudet.
|
||||
* Additional information on it can be found at:
|
||||
* http://www.arctic.org/~dean/crypto/sha1.html
|
||||
*
|
||||
* It was improved upon with more efficient vectorization of the message
|
||||
* scheduling. This implementation has also been optimized for all current and
|
||||
* several future generations of Intel CPUs.
|
||||
*
|
||||
* See this article for more information about the implementation details:
|
||||
* http://software.intel.com/en-us/articles/improving-the-performance-of-the-secure-hash-algorithm-1/
|
||||
*
|
||||
* Copyright (C) 2010, Intel Corp.
|
||||
* Authors: Maxim Locktyukhin <maxim.locktyukhin@intel.com>
|
||||
* Ronen Zohar <ronen.zohar@intel.com>
|
||||
*
|
||||
* Converted to AT&T syntax and adapted for inclusion in the Linux kernel:
|
||||
* Author: Mathias Krause <minipli@googlemail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#define CTX %rdi // arg1
|
||||
#define BUF %rsi // arg2
|
||||
#define CNT %rdx // arg3
|
||||
|
||||
#define REG_A %ecx
|
||||
#define REG_B %esi
|
||||
#define REG_C %edi
|
||||
#define REG_D %ebp
|
||||
#define REG_E %edx
|
||||
|
||||
#define REG_T1 %eax
|
||||
#define REG_T2 %ebx
|
||||
|
||||
#define K_BASE %r8
|
||||
#define HASH_PTR %r9
|
||||
#define BUFFER_PTR %r10
|
||||
#define BUFFER_END %r11
|
||||
|
||||
#define W_TMP1 %xmm0
|
||||
#define W_TMP2 %xmm9
|
||||
|
||||
#define W0 %xmm1
|
||||
#define W4 %xmm2
|
||||
#define W8 %xmm3
|
||||
#define W12 %xmm4
|
||||
#define W16 %xmm5
|
||||
#define W20 %xmm6
|
||||
#define W24 %xmm7
|
||||
#define W28 %xmm8
|
||||
|
||||
#define XMM_SHUFB_BSWAP %xmm10
|
||||
|
||||
/* we keep window of 64 w[i]+K pre-calculated values in a circular buffer */
|
||||
#define WK(t) (((t) & 15) * 4)(%rsp)
|
||||
#define W_PRECALC_AHEAD 16
|
||||
|
||||
/*
|
||||
* This macro implements the SHA-1 function's body for single 64-byte block
|
||||
* param: function's name
|
||||
*/
|
||||
.macro SHA1_VECTOR_ASM name
|
||||
.global \name
|
||||
.type \name, @function
|
||||
.align 32
|
||||
\name:
|
||||
push %rbx
|
||||
push %rbp
|
||||
push %r12
|
||||
|
||||
mov %rsp, %r12
|
||||
sub $64, %rsp # allocate workspace
|
||||
and $~15, %rsp # align stack
|
||||
|
||||
mov CTX, HASH_PTR
|
||||
mov BUF, BUFFER_PTR
|
||||
|
||||
shl $6, CNT # multiply by 64
|
||||
add BUF, CNT
|
||||
mov CNT, BUFFER_END
|
||||
|
||||
lea K_XMM_AR(%rip), K_BASE
|
||||
xmm_mov BSWAP_SHUFB_CTL(%rip), XMM_SHUFB_BSWAP
|
||||
|
||||
SHA1_PIPELINED_MAIN_BODY
|
||||
|
||||
# cleanup workspace
|
||||
mov $8, %ecx
|
||||
mov %rsp, %rdi
|
||||
xor %rax, %rax
|
||||
rep stosq
|
||||
|
||||
mov %r12, %rsp # deallocate workspace
|
||||
|
||||
pop %r12
|
||||
pop %rbp
|
||||
pop %rbx
|
||||
ret
|
||||
|
||||
.size \name, .-\name
|
||||
.endm
|
||||
|
||||
/*
|
||||
* This macro implements 80 rounds of SHA-1 for one 64-byte block
|
||||
*/
|
||||
.macro SHA1_PIPELINED_MAIN_BODY
|
||||
INIT_REGALLOC
|
||||
|
||||
mov (HASH_PTR), A
|
||||
mov 4(HASH_PTR), B
|
||||
mov 8(HASH_PTR), C
|
||||
mov 12(HASH_PTR), D
|
||||
mov 16(HASH_PTR), E
|
||||
|
||||
.set i, 0
|
||||
.rept W_PRECALC_AHEAD
|
||||
W_PRECALC i
|
||||
.set i, (i+1)
|
||||
.endr
|
||||
|
||||
.align 4
|
||||
1:
|
||||
RR F1,A,B,C,D,E,0
|
||||
RR F1,D,E,A,B,C,2
|
||||
RR F1,B,C,D,E,A,4
|
||||
RR F1,E,A,B,C,D,6
|
||||
RR F1,C,D,E,A,B,8
|
||||
|
||||
RR F1,A,B,C,D,E,10
|
||||
RR F1,D,E,A,B,C,12
|
||||
RR F1,B,C,D,E,A,14
|
||||
RR F1,E,A,B,C,D,16
|
||||
RR F1,C,D,E,A,B,18
|
||||
|
||||
RR F2,A,B,C,D,E,20
|
||||
RR F2,D,E,A,B,C,22
|
||||
RR F2,B,C,D,E,A,24
|
||||
RR F2,E,A,B,C,D,26
|
||||
RR F2,C,D,E,A,B,28
|
||||
|
||||
RR F2,A,B,C,D,E,30
|
||||
RR F2,D,E,A,B,C,32
|
||||
RR F2,B,C,D,E,A,34
|
||||
RR F2,E,A,B,C,D,36
|
||||
RR F2,C,D,E,A,B,38
|
||||
|
||||
RR F3,A,B,C,D,E,40
|
||||
RR F3,D,E,A,B,C,42
|
||||
RR F3,B,C,D,E,A,44
|
||||
RR F3,E,A,B,C,D,46
|
||||
RR F3,C,D,E,A,B,48
|
||||
|
||||
RR F3,A,B,C,D,E,50
|
||||
RR F3,D,E,A,B,C,52
|
||||
RR F3,B,C,D,E,A,54
|
||||
RR F3,E,A,B,C,D,56
|
||||
RR F3,C,D,E,A,B,58
|
||||
|
||||
add $64, BUFFER_PTR # move to the next 64-byte block
|
||||
cmp BUFFER_END, BUFFER_PTR # if the current is the last one use
|
||||
cmovae K_BASE, BUFFER_PTR # dummy source to avoid buffer overrun
|
||||
|
||||
RR F4,A,B,C,D,E,60
|
||||
RR F4,D,E,A,B,C,62
|
||||
RR F4,B,C,D,E,A,64
|
||||
RR F4,E,A,B,C,D,66
|
||||
RR F4,C,D,E,A,B,68
|
||||
|
||||
RR F4,A,B,C,D,E,70
|
||||
RR F4,D,E,A,B,C,72
|
||||
RR F4,B,C,D,E,A,74
|
||||
RR F4,E,A,B,C,D,76
|
||||
RR F4,C,D,E,A,B,78
|
||||
|
||||
UPDATE_HASH (HASH_PTR), A
|
||||
UPDATE_HASH 4(HASH_PTR), B
|
||||
UPDATE_HASH 8(HASH_PTR), C
|
||||
UPDATE_HASH 12(HASH_PTR), D
|
||||
UPDATE_HASH 16(HASH_PTR), E
|
||||
|
||||
RESTORE_RENAMED_REGS
|
||||
cmp K_BASE, BUFFER_PTR # K_BASE means, we reached the end
|
||||
jne 1b
|
||||
.endm
|
||||
|
||||
.macro INIT_REGALLOC
|
||||
.set A, REG_A
|
||||
.set B, REG_B
|
||||
.set C, REG_C
|
||||
.set D, REG_D
|
||||
.set E, REG_E
|
||||
.set T1, REG_T1
|
||||
.set T2, REG_T2
|
||||
.endm
|
||||
|
||||
.macro RESTORE_RENAMED_REGS
|
||||
# order is important (REG_C is where it should be)
|
||||
mov B, REG_B
|
||||
mov D, REG_D
|
||||
mov A, REG_A
|
||||
mov E, REG_E
|
||||
.endm
|
||||
|
||||
.macro SWAP_REG_NAMES a, b
|
||||
.set _T, \a
|
||||
.set \a, \b
|
||||
.set \b, _T
|
||||
.endm
|
||||
|
||||
.macro F1 b, c, d
|
||||
mov \c, T1
|
||||
SWAP_REG_NAMES \c, T1
|
||||
xor \d, T1
|
||||
and \b, T1
|
||||
xor \d, T1
|
||||
.endm
|
||||
|
||||
.macro F2 b, c, d
|
||||
mov \d, T1
|
||||
SWAP_REG_NAMES \d, T1
|
||||
xor \c, T1
|
||||
xor \b, T1
|
||||
.endm
|
||||
|
||||
.macro F3 b, c ,d
|
||||
mov \c, T1
|
||||
SWAP_REG_NAMES \c, T1
|
||||
mov \b, T2
|
||||
or \b, T1
|
||||
and \c, T2
|
||||
and \d, T1
|
||||
or T2, T1
|
||||
.endm
|
||||
|
||||
.macro F4 b, c, d
|
||||
F2 \b, \c, \d
|
||||
.endm
|
||||
|
||||
.macro UPDATE_HASH hash, val
|
||||
add \hash, \val
|
||||
mov \val, \hash
|
||||
.endm
|
||||
|
||||
/*
|
||||
* RR does two rounds of SHA-1 back to back with W[] pre-calc
|
||||
* t1 = F(b, c, d); e += w(i)
|
||||
* e += t1; b <<= 30; d += w(i+1);
|
||||
* t1 = F(a, b, c);
|
||||
* d += t1; a <<= 5;
|
||||
* e += a;
|
||||
* t1 = e; a >>= 7;
|
||||
* t1 <<= 5;
|
||||
* d += t1;
|
||||
*/
|
||||
.macro RR F, a, b, c, d, e, round
|
||||
add WK(\round), \e
|
||||
\F \b, \c, \d # t1 = F(b, c, d);
|
||||
W_PRECALC (\round + W_PRECALC_AHEAD)
|
||||
rol $30, \b
|
||||
add T1, \e
|
||||
add WK(\round + 1), \d
|
||||
|
||||
\F \a, \b, \c
|
||||
W_PRECALC (\round + W_PRECALC_AHEAD + 1)
|
||||
rol $5, \a
|
||||
add \a, \e
|
||||
add T1, \d
|
||||
ror $7, \a # (a <<r 5) >>r 7) => a <<r 30)
|
||||
|
||||
mov \e, T1
|
||||
SWAP_REG_NAMES \e, T1
|
||||
|
||||
rol $5, T1
|
||||
add T1, \d
|
||||
|
||||
# write: \a, \b
|
||||
# rotate: \a<=\d, \b<=\e, \c<=\a, \d<=\b, \e<=\c
|
||||
.endm
|
||||
|
||||
.macro W_PRECALC r
|
||||
.set i, \r
|
||||
|
||||
.if (i < 20)
|
||||
.set K_XMM, 0
|
||||
.elseif (i < 40)
|
||||
.set K_XMM, 16
|
||||
.elseif (i < 60)
|
||||
.set K_XMM, 32
|
||||
.elseif (i < 80)
|
||||
.set K_XMM, 48
|
||||
.endif
|
||||
|
||||
.if ((i < 16) || ((i >= 80) && (i < (80 + W_PRECALC_AHEAD))))
|
||||
.set i, ((\r) % 80) # pre-compute for the next iteration
|
||||
.if (i == 0)
|
||||
W_PRECALC_RESET
|
||||
.endif
|
||||
W_PRECALC_00_15
|
||||
.elseif (i<32)
|
||||
W_PRECALC_16_31
|
||||
.elseif (i < 80) // rounds 32-79
|
||||
W_PRECALC_32_79
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro W_PRECALC_RESET
|
||||
.set W, W0
|
||||
.set W_minus_04, W4
|
||||
.set W_minus_08, W8
|
||||
.set W_minus_12, W12
|
||||
.set W_minus_16, W16
|
||||
.set W_minus_20, W20
|
||||
.set W_minus_24, W24
|
||||
.set W_minus_28, W28
|
||||
.set W_minus_32, W
|
||||
.endm
|
||||
|
||||
.macro W_PRECALC_ROTATE
|
||||
.set W_minus_32, W_minus_28
|
||||
.set W_minus_28, W_minus_24
|
||||
.set W_minus_24, W_minus_20
|
||||
.set W_minus_20, W_minus_16
|
||||
.set W_minus_16, W_minus_12
|
||||
.set W_minus_12, W_minus_08
|
||||
.set W_minus_08, W_minus_04
|
||||
.set W_minus_04, W
|
||||
.set W, W_minus_32
|
||||
.endm
|
||||
|
||||
.macro W_PRECALC_SSSE3
|
||||
|
||||
.macro W_PRECALC_00_15
|
||||
W_PRECALC_00_15_SSSE3
|
||||
.endm
|
||||
.macro W_PRECALC_16_31
|
||||
W_PRECALC_16_31_SSSE3
|
||||
.endm
|
||||
.macro W_PRECALC_32_79
|
||||
W_PRECALC_32_79_SSSE3
|
||||
.endm
|
||||
|
||||
/* message scheduling pre-compute for rounds 0-15 */
|
||||
.macro W_PRECALC_00_15_SSSE3
|
||||
.if ((i & 3) == 0)
|
||||
movdqu (i*4)(BUFFER_PTR), W_TMP1
|
||||
.elseif ((i & 3) == 1)
|
||||
pshufb XMM_SHUFB_BSWAP, W_TMP1
|
||||
movdqa W_TMP1, W
|
||||
.elseif ((i & 3) == 2)
|
||||
paddd (K_BASE), W_TMP1
|
||||
.elseif ((i & 3) == 3)
|
||||
movdqa W_TMP1, WK(i&~3)
|
||||
W_PRECALC_ROTATE
|
||||
.endif
|
||||
.endm
|
||||
|
||||
/* message scheduling pre-compute for rounds 16-31
|
||||
*
|
||||
* - calculating last 32 w[i] values in 8 XMM registers
|
||||
* - pre-calculate K+w[i] values and store to mem, for later load by ALU add
|
||||
* instruction
|
||||
*
|
||||
* some "heavy-lifting" vectorization for rounds 16-31 due to w[i]->w[i-3]
|
||||
* dependency, but improves for 32-79
|
||||
*/
|
||||
.macro W_PRECALC_16_31_SSSE3
|
||||
# blended scheduling of vector and scalar instruction streams, one 4-wide
|
||||
# vector iteration / 4 scalar rounds
|
||||
.if ((i & 3) == 0)
|
||||
movdqa W_minus_12, W
|
||||
palignr $8, W_minus_16, W # w[i-14]
|
||||
movdqa W_minus_04, W_TMP1
|
||||
psrldq $4, W_TMP1 # w[i-3]
|
||||
pxor W_minus_08, W
|
||||
.elseif ((i & 3) == 1)
|
||||
pxor W_minus_16, W_TMP1
|
||||
pxor W_TMP1, W
|
||||
movdqa W, W_TMP2
|
||||
movdqa W, W_TMP1
|
||||
pslldq $12, W_TMP2
|
||||
.elseif ((i & 3) == 2)
|
||||
psrld $31, W
|
||||
pslld $1, W_TMP1
|
||||
por W, W_TMP1
|
||||
movdqa W_TMP2, W
|
||||
psrld $30, W_TMP2
|
||||
pslld $2, W
|
||||
.elseif ((i & 3) == 3)
|
||||
pxor W, W_TMP1
|
||||
pxor W_TMP2, W_TMP1
|
||||
movdqa W_TMP1, W
|
||||
paddd K_XMM(K_BASE), W_TMP1
|
||||
movdqa W_TMP1, WK(i&~3)
|
||||
W_PRECALC_ROTATE
|
||||
.endif
|
||||
.endm
|
||||
|
||||
/* message scheduling pre-compute for rounds 32-79
|
||||
*
|
||||
* in SHA-1 specification: w[i] = (w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]) rol 1
|
||||
* instead we do equal: w[i] = (w[i-6] ^ w[i-16] ^ w[i-28] ^ w[i-32]) rol 2
|
||||
* allows more efficient vectorization since w[i]=>w[i-3] dependency is broken
|
||||
*/
|
||||
.macro W_PRECALC_32_79_SSSE3
|
||||
.if ((i & 3) == 0)
|
||||
movdqa W_minus_04, W_TMP1
|
||||
pxor W_minus_28, W # W is W_minus_32 before xor
|
||||
palignr $8, W_minus_08, W_TMP1
|
||||
.elseif ((i & 3) == 1)
|
||||
pxor W_minus_16, W
|
||||
pxor W_TMP1, W
|
||||
movdqa W, W_TMP1
|
||||
.elseif ((i & 3) == 2)
|
||||
psrld $30, W
|
||||
pslld $2, W_TMP1
|
||||
por W, W_TMP1
|
||||
.elseif ((i & 3) == 3)
|
||||
movdqa W_TMP1, W
|
||||
paddd K_XMM(K_BASE), W_TMP1
|
||||
movdqa W_TMP1, WK(i&~3)
|
||||
W_PRECALC_ROTATE
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.endm // W_PRECALC_SSSE3
|
||||
|
||||
|
||||
#define K1 0x5a827999
|
||||
#define K2 0x6ed9eba1
|
||||
#define K3 0x8f1bbcdc
|
||||
#define K4 0xca62c1d6
|
||||
|
||||
.section .rodata
|
||||
.align 16
|
||||
|
||||
K_XMM_AR:
|
||||
.long K1, K1, K1, K1
|
||||
.long K2, K2, K2, K2
|
||||
.long K3, K3, K3, K3
|
||||
.long K4, K4, K4, K4
|
||||
|
||||
BSWAP_SHUFB_CTL:
|
||||
.long 0x00010203
|
||||
.long 0x04050607
|
||||
.long 0x08090a0b
|
||||
.long 0x0c0d0e0f
|
||||
|
||||
|
||||
.section .text
|
||||
|
||||
W_PRECALC_SSSE3
|
||||
.macro xmm_mov a, b
|
||||
movdqu \a,\b
|
||||
.endm
|
||||
|
||||
/* SSSE3 optimized implementation:
|
||||
* extern "C" void sha1_transform_ssse3(u32 *digest, const char *data, u32 *ws,
|
||||
* unsigned int rounds);
|
||||
*/
|
||||
SHA1_VECTOR_ASM sha1_transform_ssse3
|
||||
|
||||
#ifdef SHA1_ENABLE_AVX_SUPPORT
|
||||
|
||||
.macro W_PRECALC_AVX
|
||||
|
||||
.purgem W_PRECALC_00_15
|
||||
.macro W_PRECALC_00_15
|
||||
W_PRECALC_00_15_AVX
|
||||
.endm
|
||||
.purgem W_PRECALC_16_31
|
||||
.macro W_PRECALC_16_31
|
||||
W_PRECALC_16_31_AVX
|
||||
.endm
|
||||
.purgem W_PRECALC_32_79
|
||||
.macro W_PRECALC_32_79
|
||||
W_PRECALC_32_79_AVX
|
||||
.endm
|
||||
|
||||
.macro W_PRECALC_00_15_AVX
|
||||
.if ((i & 3) == 0)
|
||||
vmovdqu (i*4)(BUFFER_PTR), W_TMP1
|
||||
.elseif ((i & 3) == 1)
|
||||
vpshufb XMM_SHUFB_BSWAP, W_TMP1, W
|
||||
.elseif ((i & 3) == 2)
|
||||
vpaddd (K_BASE), W, W_TMP1
|
||||
.elseif ((i & 3) == 3)
|
||||
vmovdqa W_TMP1, WK(i&~3)
|
||||
W_PRECALC_ROTATE
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro W_PRECALC_16_31_AVX
|
||||
.if ((i & 3) == 0)
|
||||
vpalignr $8, W_minus_16, W_minus_12, W # w[i-14]
|
||||
vpsrldq $4, W_minus_04, W_TMP1 # w[i-3]
|
||||
vpxor W_minus_08, W, W
|
||||
vpxor W_minus_16, W_TMP1, W_TMP1
|
||||
.elseif ((i & 3) == 1)
|
||||
vpxor W_TMP1, W, W
|
||||
vpslldq $12, W, W_TMP2
|
||||
vpslld $1, W, W_TMP1
|
||||
.elseif ((i & 3) == 2)
|
||||
vpsrld $31, W, W
|
||||
vpor W, W_TMP1, W_TMP1
|
||||
vpslld $2, W_TMP2, W
|
||||
vpsrld $30, W_TMP2, W_TMP2
|
||||
.elseif ((i & 3) == 3)
|
||||
vpxor W, W_TMP1, W_TMP1
|
||||
vpxor W_TMP2, W_TMP1, W
|
||||
vpaddd K_XMM(K_BASE), W, W_TMP1
|
||||
vmovdqu W_TMP1, WK(i&~3)
|
||||
W_PRECALC_ROTATE
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.macro W_PRECALC_32_79_AVX
|
||||
.if ((i & 3) == 0)
|
||||
vpalignr $8, W_minus_08, W_minus_04, W_TMP1
|
||||
vpxor W_minus_28, W, W # W is W_minus_32 before xor
|
||||
.elseif ((i & 3) == 1)
|
||||
vpxor W_minus_16, W_TMP1, W_TMP1
|
||||
vpxor W_TMP1, W, W
|
||||
.elseif ((i & 3) == 2)
|
||||
vpslld $2, W, W_TMP1
|
||||
vpsrld $30, W, W
|
||||
vpor W, W_TMP1, W
|
||||
.elseif ((i & 3) == 3)
|
||||
vpaddd K_XMM(K_BASE), W, W_TMP1
|
||||
vmovdqu W_TMP1, WK(i&~3)
|
||||
W_PRECALC_ROTATE
|
||||
.endif
|
||||
.endm
|
||||
|
||||
.endm // W_PRECALC_AVX
|
||||
|
||||
W_PRECALC_AVX
|
||||
.purgem xmm_mov
|
||||
.macro xmm_mov a, b
|
||||
vmovdqu \a,\b
|
||||
.endm
|
||||
|
||||
|
||||
/* AVX optimized implementation:
|
||||
* extern "C" void sha1_transform_avx(u32 *digest, const char *data, u32 *ws,
|
||||
* unsigned int rounds);
|
||||
*/
|
||||
SHA1_VECTOR_ASM sha1_transform_avx
|
||||
|
||||
#endif
|
240
arch/x86/crypto/sha1_ssse3_glue.c
Normal file
240
arch/x86/crypto/sha1_ssse3_glue.c
Normal file
@ -0,0 +1,240 @@
|
||||
/*
|
||||
* Cryptographic API.
|
||||
*
|
||||
* Glue code for the SHA1 Secure Hash Algorithm assembler implementation using
|
||||
* Supplemental SSE3 instructions.
|
||||
*
|
||||
* This file is based on sha1_generic.c
|
||||
*
|
||||
* Copyright (c) Alan Smithee.
|
||||
* Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
|
||||
* Copyright (c) Jean-Francois Dive <jef@linuxbe.org>
|
||||
* Copyright (c) Mathias Krause <minipli@googlemail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <crypto/internal/hash.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/cryptohash.h>
|
||||
#include <linux/types.h>
|
||||
#include <crypto/sha.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/i387.h>
|
||||
#include <asm/xcr.h>
|
||||
#include <asm/xsave.h>
|
||||
|
||||
|
||||
asmlinkage void sha1_transform_ssse3(u32 *digest, const char *data,
|
||||
unsigned int rounds);
|
||||
#ifdef SHA1_ENABLE_AVX_SUPPORT
|
||||
asmlinkage void sha1_transform_avx(u32 *digest, const char *data,
|
||||
unsigned int rounds);
|
||||
#endif
|
||||
|
||||
static asmlinkage void (*sha1_transform_asm)(u32 *, const char *, unsigned int);
|
||||
|
||||
|
||||
static int sha1_ssse3_init(struct shash_desc *desc)
|
||||
{
|
||||
struct sha1_state *sctx = shash_desc_ctx(desc);
|
||||
|
||||
*sctx = (struct sha1_state){
|
||||
.state = { SHA1_H0, SHA1_H1, SHA1_H2, SHA1_H3, SHA1_H4 },
|
||||
};
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __sha1_ssse3_update(struct shash_desc *desc, const u8 *data,
|
||||
unsigned int len, unsigned int partial)
|
||||
{
|
||||
struct sha1_state *sctx = shash_desc_ctx(desc);
|
||||
unsigned int done = 0;
|
||||
|
||||
sctx->count += len;
|
||||
|
||||
if (partial) {
|
||||
done = SHA1_BLOCK_SIZE - partial;
|
||||
memcpy(sctx->buffer + partial, data, done);
|
||||
sha1_transform_asm(sctx->state, sctx->buffer, 1);
|
||||
}
|
||||
|
||||
if (len - done >= SHA1_BLOCK_SIZE) {
|
||||
const unsigned int rounds = (len - done) / SHA1_BLOCK_SIZE;
|
||||
|
||||
sha1_transform_asm(sctx->state, data + done, rounds);
|
||||
done += rounds * SHA1_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
memcpy(sctx->buffer, data + done, len - done);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sha1_ssse3_update(struct shash_desc *desc, const u8 *data,
|
||||
unsigned int len)
|
||||
{
|
||||
struct sha1_state *sctx = shash_desc_ctx(desc);
|
||||
unsigned int partial = sctx->count % SHA1_BLOCK_SIZE;
|
||||
int res;
|
||||
|
||||
/* Handle the fast case right here */
|
||||
if (partial + len < SHA1_BLOCK_SIZE) {
|
||||
sctx->count += len;
|
||||
memcpy(sctx->buffer + partial, data, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!irq_fpu_usable()) {
|
||||
res = crypto_sha1_update(desc, data, len);
|
||||
} else {
|
||||
kernel_fpu_begin();
|
||||
res = __sha1_ssse3_update(desc, data, len, partial);
|
||||
kernel_fpu_end();
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* Add padding and return the message digest. */
|
||||
static int sha1_ssse3_final(struct shash_desc *desc, u8 *out)
|
||||
{
|
||||
struct sha1_state *sctx = shash_desc_ctx(desc);
|
||||
unsigned int i, index, padlen;
|
||||
__be32 *dst = (__be32 *)out;
|
||||
__be64 bits;
|
||||
static const u8 padding[SHA1_BLOCK_SIZE] = { 0x80, };
|
||||
|
||||
bits = cpu_to_be64(sctx->count << 3);
|
||||
|
||||
/* Pad out to 56 mod 64 and append length */
|
||||
index = sctx->count % SHA1_BLOCK_SIZE;
|
||||
padlen = (index < 56) ? (56 - index) : ((SHA1_BLOCK_SIZE+56) - index);
|
||||
if (!irq_fpu_usable()) {
|
||||
crypto_sha1_update(desc, padding, padlen);
|
||||
crypto_sha1_update(desc, (const u8 *)&bits, sizeof(bits));
|
||||
} else {
|
||||
kernel_fpu_begin();
|
||||
/* We need to fill a whole block for __sha1_ssse3_update() */
|
||||
if (padlen <= 56) {
|
||||
sctx->count += padlen;
|
||||
memcpy(sctx->buffer + index, padding, padlen);
|
||||
} else {
|
||||
__sha1_ssse3_update(desc, padding, padlen, index);
|
||||
}
|
||||
__sha1_ssse3_update(desc, (const u8 *)&bits, sizeof(bits), 56);
|
||||
kernel_fpu_end();
|
||||
}
|
||||
|
||||
/* Store state in digest */
|
||||
for (i = 0; i < 5; i++)
|
||||
dst[i] = cpu_to_be32(sctx->state[i]);
|
||||
|
||||
/* Wipe context */
|
||||
memset(sctx, 0, sizeof(*sctx));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sha1_ssse3_export(struct shash_desc *desc, void *out)
|
||||
{
|
||||
struct sha1_state *sctx = shash_desc_ctx(desc);
|
||||
|
||||
memcpy(out, sctx, sizeof(*sctx));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sha1_ssse3_import(struct shash_desc *desc, const void *in)
|
||||
{
|
||||
struct sha1_state *sctx = shash_desc_ctx(desc);
|
||||
|
||||
memcpy(sctx, in, sizeof(*sctx));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct shash_alg alg = {
|
||||
.digestsize = SHA1_DIGEST_SIZE,
|
||||
.init = sha1_ssse3_init,
|
||||
.update = sha1_ssse3_update,
|
||||
.final = sha1_ssse3_final,
|
||||
.export = sha1_ssse3_export,
|
||||
.import = sha1_ssse3_import,
|
||||
.descsize = sizeof(struct sha1_state),
|
||||
.statesize = sizeof(struct sha1_state),
|
||||
.base = {
|
||||
.cra_name = "sha1",
|
||||
.cra_driver_name= "sha1-ssse3",
|
||||
.cra_priority = 150,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_SHASH,
|
||||
.cra_blocksize = SHA1_BLOCK_SIZE,
|
||||
.cra_module = THIS_MODULE,
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef SHA1_ENABLE_AVX_SUPPORT
|
||||
static bool __init avx_usable(void)
|
||||
{
|
||||
u64 xcr0;
|
||||
|
||||
if (!cpu_has_avx || !cpu_has_osxsave)
|
||||
return false;
|
||||
|
||||
xcr0 = xgetbv(XCR_XFEATURE_ENABLED_MASK);
|
||||
if ((xcr0 & (XSTATE_SSE | XSTATE_YMM)) != (XSTATE_SSE | XSTATE_YMM)) {
|
||||
pr_info("AVX detected but unusable.\n");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int __init sha1_ssse3_mod_init(void)
|
||||
{
|
||||
/* test for SSSE3 first */
|
||||
if (cpu_has_ssse3)
|
||||
sha1_transform_asm = sha1_transform_ssse3;
|
||||
|
||||
#ifdef SHA1_ENABLE_AVX_SUPPORT
|
||||
/* allow AVX to override SSSE3, it's a little faster */
|
||||
if (avx_usable())
|
||||
sha1_transform_asm = sha1_transform_avx;
|
||||
#endif
|
||||
|
||||
if (sha1_transform_asm) {
|
||||
pr_info("Using %s optimized SHA-1 implementation\n",
|
||||
sha1_transform_asm == sha1_transform_ssse3 ? "SSSE3"
|
||||
: "AVX");
|
||||
return crypto_register_shash(&alg);
|
||||
}
|
||||
pr_info("Neither AVX nor SSSE3 is available/usable.\n");
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static void __exit sha1_ssse3_mod_fini(void)
|
||||
{
|
||||
crypto_unregister_shash(&alg);
|
||||
}
|
||||
|
||||
module_init(sha1_ssse3_mod_init);
|
||||
module_exit(sha1_ssse3_mod_fini);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm, Supplemental SSE3 accelerated");
|
||||
|
||||
MODULE_ALIAS("sha1");
|
@ -26,7 +26,7 @@
|
||||
|
||||
#define in_blk 12 /* input byte array address parameter*/
|
||||
#define out_blk 8 /* output byte array address parameter*/
|
||||
#define tfm 4 /* Twofish context structure */
|
||||
#define ctx 4 /* Twofish context structure */
|
||||
|
||||
#define a_offset 0
|
||||
#define b_offset 4
|
||||
@ -229,8 +229,8 @@ twofish_enc_blk:
|
||||
push %esi
|
||||
push %edi
|
||||
|
||||
mov tfm + 16(%esp), %ebp /* abuse the base pointer: set new base bointer to the crypto tfm */
|
||||
add $crypto_tfm_ctx_offset, %ebp /* ctx address */
|
||||
mov ctx + 16(%esp), %ebp /* abuse the base pointer: set new base
|
||||
* pointer to the ctx address */
|
||||
mov in_blk+16(%esp),%edi /* input address in edi */
|
||||
|
||||
mov (%edi), %eax
|
||||
@ -285,8 +285,8 @@ twofish_dec_blk:
|
||||
push %edi
|
||||
|
||||
|
||||
mov tfm + 16(%esp), %ebp /* abuse the base pointer: set new base bointer to the crypto tfm */
|
||||
add $crypto_tfm_ctx_offset, %ebp /* ctx address */
|
||||
mov ctx + 16(%esp), %ebp /* abuse the base pointer: set new base
|
||||
* pointer to the ctx address */
|
||||
mov in_blk+16(%esp),%edi /* input address in edi */
|
||||
|
||||
mov (%edi), %eax
|
||||
|
316
arch/x86/crypto/twofish-x86_64-asm_64-3way.S
Normal file
316
arch/x86/crypto/twofish-x86_64-asm_64-3way.S
Normal file
@ -0,0 +1,316 @@
|
||||
/*
|
||||
* Twofish Cipher 3-way parallel algorithm (x86_64)
|
||||
*
|
||||
* Copyright (C) 2011 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA
|
||||
*
|
||||
*/
|
||||
|
||||
.file "twofish-x86_64-asm-3way.S"
|
||||
.text
|
||||
|
||||
/* structure of crypto context */
|
||||
#define s0 0
|
||||
#define s1 1024
|
||||
#define s2 2048
|
||||
#define s3 3072
|
||||
#define w 4096
|
||||
#define k 4128
|
||||
|
||||
/**********************************************************************
|
||||
3-way twofish
|
||||
**********************************************************************/
|
||||
#define CTX %rdi
|
||||
#define RIO %rdx
|
||||
|
||||
#define RAB0 %rax
|
||||
#define RAB1 %rbx
|
||||
#define RAB2 %rcx
|
||||
|
||||
#define RAB0d %eax
|
||||
#define RAB1d %ebx
|
||||
#define RAB2d %ecx
|
||||
|
||||
#define RAB0bh %ah
|
||||
#define RAB1bh %bh
|
||||
#define RAB2bh %ch
|
||||
|
||||
#define RAB0bl %al
|
||||
#define RAB1bl %bl
|
||||
#define RAB2bl %cl
|
||||
|
||||
#define RCD0 %r8
|
||||
#define RCD1 %r9
|
||||
#define RCD2 %r10
|
||||
|
||||
#define RCD0d %r8d
|
||||
#define RCD1d %r9d
|
||||
#define RCD2d %r10d
|
||||
|
||||
#define RX0 %rbp
|
||||
#define RX1 %r11
|
||||
#define RX2 %r12
|
||||
|
||||
#define RX0d %ebp
|
||||
#define RX1d %r11d
|
||||
#define RX2d %r12d
|
||||
|
||||
#define RY0 %r13
|
||||
#define RY1 %r14
|
||||
#define RY2 %r15
|
||||
|
||||
#define RY0d %r13d
|
||||
#define RY1d %r14d
|
||||
#define RY2d %r15d
|
||||
|
||||
#define RT0 %rdx
|
||||
#define RT1 %rsi
|
||||
|
||||
#define RT0d %edx
|
||||
#define RT1d %esi
|
||||
|
||||
#define do16bit_ror(rot, op1, op2, T0, T1, tmp1, tmp2, ab, dst) \
|
||||
movzbl ab ## bl, tmp2 ## d; \
|
||||
movzbl ab ## bh, tmp1 ## d; \
|
||||
rorq $(rot), ab; \
|
||||
op1##l T0(CTX, tmp2, 4), dst ## d; \
|
||||
op2##l T1(CTX, tmp1, 4), dst ## d;
|
||||
|
||||
/*
|
||||
* Combined G1 & G2 function. Reordered with help of rotates to have moves
|
||||
* at begining.
|
||||
*/
|
||||
#define g1g2_3(ab, cd, Tx0, Tx1, Tx2, Tx3, Ty0, Ty1, Ty2, Ty3, x, y) \
|
||||
/* G1,1 && G2,1 */ \
|
||||
do16bit_ror(32, mov, xor, Tx0, Tx1, RT0, x ## 0, ab ## 0, x ## 0); \
|
||||
do16bit_ror(48, mov, xor, Ty1, Ty2, RT0, y ## 0, ab ## 0, y ## 0); \
|
||||
\
|
||||
do16bit_ror(32, mov, xor, Tx0, Tx1, RT0, x ## 1, ab ## 1, x ## 1); \
|
||||
do16bit_ror(48, mov, xor, Ty1, Ty2, RT0, y ## 1, ab ## 1, y ## 1); \
|
||||
\
|
||||
do16bit_ror(32, mov, xor, Tx0, Tx1, RT0, x ## 2, ab ## 2, x ## 2); \
|
||||
do16bit_ror(48, mov, xor, Ty1, Ty2, RT0, y ## 2, ab ## 2, y ## 2); \
|
||||
\
|
||||
/* G1,2 && G2,2 */ \
|
||||
do16bit_ror(32, xor, xor, Tx2, Tx3, RT0, RT1, ab ## 0, x ## 0); \
|
||||
do16bit_ror(16, xor, xor, Ty3, Ty0, RT0, RT1, ab ## 0, y ## 0); \
|
||||
xchgq cd ## 0, ab ## 0; \
|
||||
\
|
||||
do16bit_ror(32, xor, xor, Tx2, Tx3, RT0, RT1, ab ## 1, x ## 1); \
|
||||
do16bit_ror(16, xor, xor, Ty3, Ty0, RT0, RT1, ab ## 1, y ## 1); \
|
||||
xchgq cd ## 1, ab ## 1; \
|
||||
\
|
||||
do16bit_ror(32, xor, xor, Tx2, Tx3, RT0, RT1, ab ## 2, x ## 2); \
|
||||
do16bit_ror(16, xor, xor, Ty3, Ty0, RT0, RT1, ab ## 2, y ## 2); \
|
||||
xchgq cd ## 2, ab ## 2;
|
||||
|
||||
#define enc_round_end(ab, x, y, n) \
|
||||
addl y ## d, x ## d; \
|
||||
addl x ## d, y ## d; \
|
||||
addl k+4*(2*(n))(CTX), x ## d; \
|
||||
xorl ab ## d, x ## d; \
|
||||
addl k+4*(2*(n)+1)(CTX), y ## d; \
|
||||
shrq $32, ab; \
|
||||
roll $1, ab ## d; \
|
||||
xorl y ## d, ab ## d; \
|
||||
shlq $32, ab; \
|
||||
rorl $1, x ## d; \
|
||||
orq x, ab;
|
||||
|
||||
#define dec_round_end(ba, x, y, n) \
|
||||
addl y ## d, x ## d; \
|
||||
addl x ## d, y ## d; \
|
||||
addl k+4*(2*(n))(CTX), x ## d; \
|
||||
addl k+4*(2*(n)+1)(CTX), y ## d; \
|
||||
xorl ba ## d, y ## d; \
|
||||
shrq $32, ba; \
|
||||
roll $1, ba ## d; \
|
||||
xorl x ## d, ba ## d; \
|
||||
shlq $32, ba; \
|
||||
rorl $1, y ## d; \
|
||||
orq y, ba;
|
||||
|
||||
#define encrypt_round3(ab, cd, n) \
|
||||
g1g2_3(ab, cd, s0, s1, s2, s3, s0, s1, s2, s3, RX, RY); \
|
||||
\
|
||||
enc_round_end(ab ## 0, RX0, RY0, n); \
|
||||
enc_round_end(ab ## 1, RX1, RY1, n); \
|
||||
enc_round_end(ab ## 2, RX2, RY2, n);
|
||||
|
||||
#define decrypt_round3(ba, dc, n) \
|
||||
g1g2_3(ba, dc, s1, s2, s3, s0, s3, s0, s1, s2, RY, RX); \
|
||||
\
|
||||
dec_round_end(ba ## 0, RX0, RY0, n); \
|
||||
dec_round_end(ba ## 1, RX1, RY1, n); \
|
||||
dec_round_end(ba ## 2, RX2, RY2, n);
|
||||
|
||||
#define encrypt_cycle3(ab, cd, n) \
|
||||
encrypt_round3(ab, cd, n*2); \
|
||||
encrypt_round3(ab, cd, (n*2)+1);
|
||||
|
||||
#define decrypt_cycle3(ba, dc, n) \
|
||||
decrypt_round3(ba, dc, (n*2)+1); \
|
||||
decrypt_round3(ba, dc, (n*2));
|
||||
|
||||
#define inpack3(in, n, xy, m) \
|
||||
movq 4*(n)(in), xy ## 0; \
|
||||
xorq w+4*m(CTX), xy ## 0; \
|
||||
\
|
||||
movq 4*(4+(n))(in), xy ## 1; \
|
||||
xorq w+4*m(CTX), xy ## 1; \
|
||||
\
|
||||
movq 4*(8+(n))(in), xy ## 2; \
|
||||
xorq w+4*m(CTX), xy ## 2;
|
||||
|
||||
#define outunpack3(op, out, n, xy, m) \
|
||||
xorq w+4*m(CTX), xy ## 0; \
|
||||
op ## q xy ## 0, 4*(n)(out); \
|
||||
\
|
||||
xorq w+4*m(CTX), xy ## 1; \
|
||||
op ## q xy ## 1, 4*(4+(n))(out); \
|
||||
\
|
||||
xorq w+4*m(CTX), xy ## 2; \
|
||||
op ## q xy ## 2, 4*(8+(n))(out);
|
||||
|
||||
#define inpack_enc3() \
|
||||
inpack3(RIO, 0, RAB, 0); \
|
||||
inpack3(RIO, 2, RCD, 2);
|
||||
|
||||
#define outunpack_enc3(op) \
|
||||
outunpack3(op, RIO, 2, RAB, 6); \
|
||||
outunpack3(op, RIO, 0, RCD, 4);
|
||||
|
||||
#define inpack_dec3() \
|
||||
inpack3(RIO, 0, RAB, 4); \
|
||||
rorq $32, RAB0; \
|
||||
rorq $32, RAB1; \
|
||||
rorq $32, RAB2; \
|
||||
inpack3(RIO, 2, RCD, 6); \
|
||||
rorq $32, RCD0; \
|
||||
rorq $32, RCD1; \
|
||||
rorq $32, RCD2;
|
||||
|
||||
#define outunpack_dec3() \
|
||||
rorq $32, RCD0; \
|
||||
rorq $32, RCD1; \
|
||||
rorq $32, RCD2; \
|
||||
outunpack3(mov, RIO, 0, RCD, 0); \
|
||||
rorq $32, RAB0; \
|
||||
rorq $32, RAB1; \
|
||||
rorq $32, RAB2; \
|
||||
outunpack3(mov, RIO, 2, RAB, 2);
|
||||
|
||||
.align 8
|
||||
.global __twofish_enc_blk_3way
|
||||
.type __twofish_enc_blk_3way,@function;
|
||||
|
||||
__twofish_enc_blk_3way:
|
||||
/* input:
|
||||
* %rdi: ctx, CTX
|
||||
* %rsi: dst
|
||||
* %rdx: src, RIO
|
||||
* %rcx: bool, if true: xor output
|
||||
*/
|
||||
pushq %r15;
|
||||
pushq %r14;
|
||||
pushq %r13;
|
||||
pushq %r12;
|
||||
pushq %rbp;
|
||||
pushq %rbx;
|
||||
|
||||
pushq %rcx; /* bool xor */
|
||||
pushq %rsi; /* dst */
|
||||
|
||||
inpack_enc3();
|
||||
|
||||
encrypt_cycle3(RAB, RCD, 0);
|
||||
encrypt_cycle3(RAB, RCD, 1);
|
||||
encrypt_cycle3(RAB, RCD, 2);
|
||||
encrypt_cycle3(RAB, RCD, 3);
|
||||
encrypt_cycle3(RAB, RCD, 4);
|
||||
encrypt_cycle3(RAB, RCD, 5);
|
||||
encrypt_cycle3(RAB, RCD, 6);
|
||||
encrypt_cycle3(RAB, RCD, 7);
|
||||
|
||||
popq RIO; /* dst */
|
||||
popq %rbp; /* bool xor */
|
||||
|
||||
testb %bpl, %bpl;
|
||||
jnz __enc_xor3;
|
||||
|
||||
outunpack_enc3(mov);
|
||||
|
||||
popq %rbx;
|
||||
popq %rbp;
|
||||
popq %r12;
|
||||
popq %r13;
|
||||
popq %r14;
|
||||
popq %r15;
|
||||
ret;
|
||||
|
||||
__enc_xor3:
|
||||
outunpack_enc3(xor);
|
||||
|
||||
popq %rbx;
|
||||
popq %rbp;
|
||||
popq %r12;
|
||||
popq %r13;
|
||||
popq %r14;
|
||||
popq %r15;
|
||||
ret;
|
||||
|
||||
.global twofish_dec_blk_3way
|
||||
.type twofish_dec_blk_3way,@function;
|
||||
|
||||
twofish_dec_blk_3way:
|
||||
/* input:
|
||||
* %rdi: ctx, CTX
|
||||
* %rsi: dst
|
||||
* %rdx: src, RIO
|
||||
*/
|
||||
pushq %r15;
|
||||
pushq %r14;
|
||||
pushq %r13;
|
||||
pushq %r12;
|
||||
pushq %rbp;
|
||||
pushq %rbx;
|
||||
|
||||
pushq %rsi; /* dst */
|
||||
|
||||
inpack_dec3();
|
||||
|
||||
decrypt_cycle3(RAB, RCD, 7);
|
||||
decrypt_cycle3(RAB, RCD, 6);
|
||||
decrypt_cycle3(RAB, RCD, 5);
|
||||
decrypt_cycle3(RAB, RCD, 4);
|
||||
decrypt_cycle3(RAB, RCD, 3);
|
||||
decrypt_cycle3(RAB, RCD, 2);
|
||||
decrypt_cycle3(RAB, RCD, 1);
|
||||
decrypt_cycle3(RAB, RCD, 0);
|
||||
|
||||
popq RIO; /* dst */
|
||||
|
||||
outunpack_dec3();
|
||||
|
||||
popq %rbx;
|
||||
popq %rbp;
|
||||
popq %r12;
|
||||
popq %r13;
|
||||
popq %r14;
|
||||
popq %r15;
|
||||
ret;
|
||||
|
@ -221,10 +221,9 @@
|
||||
twofish_enc_blk:
|
||||
pushq R1
|
||||
|
||||
/* %rdi contains the crypto tfm address */
|
||||
/* %rdi contains the ctx address */
|
||||
/* %rsi contains the output address */
|
||||
/* %rdx contains the input address */
|
||||
add $crypto_tfm_ctx_offset, %rdi /* set ctx address */
|
||||
/* ctx address is moved to free one non-rex register
|
||||
as target for the 8bit high operations */
|
||||
mov %rdi, %r11
|
||||
@ -274,10 +273,9 @@ twofish_enc_blk:
|
||||
twofish_dec_blk:
|
||||
pushq R1
|
||||
|
||||
/* %rdi contains the crypto tfm address */
|
||||
/* %rdi contains the ctx address */
|
||||
/* %rsi contains the output address */
|
||||
/* %rdx contains the input address */
|
||||
add $crypto_tfm_ctx_offset, %rdi /* set ctx address */
|
||||
/* ctx address is moved to free one non-rex register
|
||||
as target for the 8bit high operations */
|
||||
mov %rdi, %r11
|
||||
|
@ -44,17 +44,21 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
asmlinkage void twofish_enc_blk(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
|
||||
asmlinkage void twofish_dec_blk(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
|
||||
asmlinkage void twofish_enc_blk(struct twofish_ctx *ctx, u8 *dst,
|
||||
const u8 *src);
|
||||
EXPORT_SYMBOL_GPL(twofish_enc_blk);
|
||||
asmlinkage void twofish_dec_blk(struct twofish_ctx *ctx, u8 *dst,
|
||||
const u8 *src);
|
||||
EXPORT_SYMBOL_GPL(twofish_dec_blk);
|
||||
|
||||
static void twofish_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
|
||||
{
|
||||
twofish_enc_blk(tfm, dst, src);
|
||||
twofish_enc_blk(crypto_tfm_ctx(tfm), dst, src);
|
||||
}
|
||||
|
||||
static void twofish_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
|
||||
{
|
||||
twofish_dec_blk(tfm, dst, src);
|
||||
twofish_dec_blk(crypto_tfm_ctx(tfm), dst, src);
|
||||
}
|
||||
|
||||
static struct crypto_alg alg = {
|
||||
|
472
arch/x86/crypto/twofish_glue_3way.c
Normal file
472
arch/x86/crypto/twofish_glue_3way.c
Normal file
@ -0,0 +1,472 @@
|
||||
/*
|
||||
* Glue Code for 3-way parallel assembler optimized version of Twofish
|
||||
*
|
||||
* Copyright (c) 2011 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
|
||||
*
|
||||
* CBC & ECB parts based on code (crypto/cbc.c,ecb.c) by:
|
||||
* Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
|
||||
* CTR part based on code (crypto/ctr.c) by:
|
||||
* (C) Copyright IBM Corp. 2007 - Joy Latten <latten@us.ibm.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <crypto/algapi.h>
|
||||
#include <crypto/twofish.h>
|
||||
#include <crypto/b128ops.h>
|
||||
|
||||
/* regular block cipher functions from twofish_x86_64 module */
|
||||
asmlinkage void twofish_enc_blk(struct twofish_ctx *ctx, u8 *dst,
|
||||
const u8 *src);
|
||||
asmlinkage void twofish_dec_blk(struct twofish_ctx *ctx, u8 *dst,
|
||||
const u8 *src);
|
||||
|
||||
/* 3-way parallel cipher functions */
|
||||
asmlinkage void __twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst,
|
||||
const u8 *src, bool xor);
|
||||
asmlinkage void twofish_dec_blk_3way(struct twofish_ctx *ctx, u8 *dst,
|
||||
const u8 *src);
|
||||
|
||||
static inline void twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst,
|
||||
const u8 *src)
|
||||
{
|
||||
__twofish_enc_blk_3way(ctx, dst, src, false);
|
||||
}
|
||||
|
||||
static inline void twofish_enc_blk_xor_3way(struct twofish_ctx *ctx, u8 *dst,
|
||||
const u8 *src)
|
||||
{
|
||||
__twofish_enc_blk_3way(ctx, dst, src, true);
|
||||
}
|
||||
|
||||
static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk,
|
||||
void (*fn)(struct twofish_ctx *, u8 *, const u8 *),
|
||||
void (*fn_3way)(struct twofish_ctx *, u8 *, const u8 *))
|
||||
{
|
||||
struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
|
||||
unsigned int bsize = TF_BLOCK_SIZE;
|
||||
unsigned int nbytes;
|
||||
int err;
|
||||
|
||||
err = blkcipher_walk_virt(desc, walk);
|
||||
|
||||
while ((nbytes = walk->nbytes)) {
|
||||
u8 *wsrc = walk->src.virt.addr;
|
||||
u8 *wdst = walk->dst.virt.addr;
|
||||
|
||||
/* Process three block batch */
|
||||
if (nbytes >= bsize * 3) {
|
||||
do {
|
||||
fn_3way(ctx, wdst, wsrc);
|
||||
|
||||
wsrc += bsize * 3;
|
||||
wdst += bsize * 3;
|
||||
nbytes -= bsize * 3;
|
||||
} while (nbytes >= bsize * 3);
|
||||
|
||||
if (nbytes < bsize)
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Handle leftovers */
|
||||
do {
|
||||
fn(ctx, wdst, wsrc);
|
||||
|
||||
wsrc += bsize;
|
||||
wdst += bsize;
|
||||
nbytes -= bsize;
|
||||
} while (nbytes >= bsize);
|
||||
|
||||
done:
|
||||
err = blkcipher_walk_done(desc, walk, nbytes);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
|
||||
struct scatterlist *src, unsigned int nbytes)
|
||||
{
|
||||
struct blkcipher_walk walk;
|
||||
|
||||
blkcipher_walk_init(&walk, dst, src, nbytes);
|
||||
return ecb_crypt(desc, &walk, twofish_enc_blk, twofish_enc_blk_3way);
|
||||
}
|
||||
|
||||
static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
|
||||
struct scatterlist *src, unsigned int nbytes)
|
||||
{
|
||||
struct blkcipher_walk walk;
|
||||
|
||||
blkcipher_walk_init(&walk, dst, src, nbytes);
|
||||
return ecb_crypt(desc, &walk, twofish_dec_blk, twofish_dec_blk_3way);
|
||||
}
|
||||
|
||||
static struct crypto_alg blk_ecb_alg = {
|
||||
.cra_name = "ecb(twofish)",
|
||||
.cra_driver_name = "ecb-twofish-3way",
|
||||
.cra_priority = 300,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
|
||||
.cra_blocksize = TF_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct twofish_ctx),
|
||||
.cra_alignmask = 0,
|
||||
.cra_type = &crypto_blkcipher_type,
|
||||
.cra_module = THIS_MODULE,
|
||||
.cra_list = LIST_HEAD_INIT(blk_ecb_alg.cra_list),
|
||||
.cra_u = {
|
||||
.blkcipher = {
|
||||
.min_keysize = TF_MIN_KEY_SIZE,
|
||||
.max_keysize = TF_MAX_KEY_SIZE,
|
||||
.setkey = twofish_setkey,
|
||||
.encrypt = ecb_encrypt,
|
||||
.decrypt = ecb_decrypt,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static unsigned int __cbc_encrypt(struct blkcipher_desc *desc,
|
||||
struct blkcipher_walk *walk)
|
||||
{
|
||||
struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
|
||||
unsigned int bsize = TF_BLOCK_SIZE;
|
||||
unsigned int nbytes = walk->nbytes;
|
||||
u128 *src = (u128 *)walk->src.virt.addr;
|
||||
u128 *dst = (u128 *)walk->dst.virt.addr;
|
||||
u128 *iv = (u128 *)walk->iv;
|
||||
|
||||
do {
|
||||
u128_xor(dst, src, iv);
|
||||
twofish_enc_blk(ctx, (u8 *)dst, (u8 *)dst);
|
||||
iv = dst;
|
||||
|
||||
src += 1;
|
||||
dst += 1;
|
||||
nbytes -= bsize;
|
||||
} while (nbytes >= bsize);
|
||||
|
||||
u128_xor((u128 *)walk->iv, (u128 *)walk->iv, iv);
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
|
||||
struct scatterlist *src, unsigned int nbytes)
|
||||
{
|
||||
struct blkcipher_walk walk;
|
||||
int err;
|
||||
|
||||
blkcipher_walk_init(&walk, dst, src, nbytes);
|
||||
err = blkcipher_walk_virt(desc, &walk);
|
||||
|
||||
while ((nbytes = walk.nbytes)) {
|
||||
nbytes = __cbc_encrypt(desc, &walk);
|
||||
err = blkcipher_walk_done(desc, &walk, nbytes);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static unsigned int __cbc_decrypt(struct blkcipher_desc *desc,
|
||||
struct blkcipher_walk *walk)
|
||||
{
|
||||
struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
|
||||
unsigned int bsize = TF_BLOCK_SIZE;
|
||||
unsigned int nbytes = walk->nbytes;
|
||||
u128 *src = (u128 *)walk->src.virt.addr;
|
||||
u128 *dst = (u128 *)walk->dst.virt.addr;
|
||||
u128 ivs[3 - 1];
|
||||
u128 last_iv;
|
||||
|
||||
/* Start of the last block. */
|
||||
src += nbytes / bsize - 1;
|
||||
dst += nbytes / bsize - 1;
|
||||
|
||||
last_iv = *src;
|
||||
|
||||
/* Process three block batch */
|
||||
if (nbytes >= bsize * 3) {
|
||||
do {
|
||||
nbytes -= bsize * (3 - 1);
|
||||
src -= 3 - 1;
|
||||
dst -= 3 - 1;
|
||||
|
||||
ivs[0] = src[0];
|
||||
ivs[1] = src[1];
|
||||
|
||||
twofish_dec_blk_3way(ctx, (u8 *)dst, (u8 *)src);
|
||||
|
||||
u128_xor(dst + 1, dst + 1, ivs + 0);
|
||||
u128_xor(dst + 2, dst + 2, ivs + 1);
|
||||
|
||||
nbytes -= bsize;
|
||||
if (nbytes < bsize)
|
||||
goto done;
|
||||
|
||||
u128_xor(dst, dst, src - 1);
|
||||
src -= 1;
|
||||
dst -= 1;
|
||||
} while (nbytes >= bsize * 3);
|
||||
|
||||
if (nbytes < bsize)
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Handle leftovers */
|
||||
for (;;) {
|
||||
twofish_dec_blk(ctx, (u8 *)dst, (u8 *)src);
|
||||
|
||||
nbytes -= bsize;
|
||||
if (nbytes < bsize)
|
||||
break;
|
||||
|
||||
u128_xor(dst, dst, src - 1);
|
||||
src -= 1;
|
||||
dst -= 1;
|
||||
}
|
||||
|
||||
done:
|
||||
u128_xor(dst, dst, (u128 *)walk->iv);
|
||||
*(u128 *)walk->iv = last_iv;
|
||||
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
|
||||
struct scatterlist *src, unsigned int nbytes)
|
||||
{
|
||||
struct blkcipher_walk walk;
|
||||
int err;
|
||||
|
||||
blkcipher_walk_init(&walk, dst, src, nbytes);
|
||||
err = blkcipher_walk_virt(desc, &walk);
|
||||
|
||||
while ((nbytes = walk.nbytes)) {
|
||||
nbytes = __cbc_decrypt(desc, &walk);
|
||||
err = blkcipher_walk_done(desc, &walk, nbytes);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct crypto_alg blk_cbc_alg = {
|
||||
.cra_name = "cbc(twofish)",
|
||||
.cra_driver_name = "cbc-twofish-3way",
|
||||
.cra_priority = 300,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
|
||||
.cra_blocksize = TF_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct twofish_ctx),
|
||||
.cra_alignmask = 0,
|
||||
.cra_type = &crypto_blkcipher_type,
|
||||
.cra_module = THIS_MODULE,
|
||||
.cra_list = LIST_HEAD_INIT(blk_cbc_alg.cra_list),
|
||||
.cra_u = {
|
||||
.blkcipher = {
|
||||
.min_keysize = TF_MIN_KEY_SIZE,
|
||||
.max_keysize = TF_MAX_KEY_SIZE,
|
||||
.ivsize = TF_BLOCK_SIZE,
|
||||
.setkey = twofish_setkey,
|
||||
.encrypt = cbc_encrypt,
|
||||
.decrypt = cbc_decrypt,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static inline void u128_to_be128(be128 *dst, const u128 *src)
|
||||
{
|
||||
dst->a = cpu_to_be64(src->a);
|
||||
dst->b = cpu_to_be64(src->b);
|
||||
}
|
||||
|
||||
static inline void be128_to_u128(u128 *dst, const be128 *src)
|
||||
{
|
||||
dst->a = be64_to_cpu(src->a);
|
||||
dst->b = be64_to_cpu(src->b);
|
||||
}
|
||||
|
||||
static inline void u128_inc(u128 *i)
|
||||
{
|
||||
i->b++;
|
||||
if (!i->b)
|
||||
i->a++;
|
||||
}
|
||||
|
||||
static void ctr_crypt_final(struct blkcipher_desc *desc,
|
||||
struct blkcipher_walk *walk)
|
||||
{
|
||||
struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
|
||||
u8 *ctrblk = walk->iv;
|
||||
u8 keystream[TF_BLOCK_SIZE];
|
||||
u8 *src = walk->src.virt.addr;
|
||||
u8 *dst = walk->dst.virt.addr;
|
||||
unsigned int nbytes = walk->nbytes;
|
||||
|
||||
twofish_enc_blk(ctx, keystream, ctrblk);
|
||||
crypto_xor(keystream, src, nbytes);
|
||||
memcpy(dst, keystream, nbytes);
|
||||
|
||||
crypto_inc(ctrblk, TF_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
static unsigned int __ctr_crypt(struct blkcipher_desc *desc,
|
||||
struct blkcipher_walk *walk)
|
||||
{
|
||||
struct twofish_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
|
||||
unsigned int bsize = TF_BLOCK_SIZE;
|
||||
unsigned int nbytes = walk->nbytes;
|
||||
u128 *src = (u128 *)walk->src.virt.addr;
|
||||
u128 *dst = (u128 *)walk->dst.virt.addr;
|
||||
u128 ctrblk;
|
||||
be128 ctrblocks[3];
|
||||
|
||||
be128_to_u128(&ctrblk, (be128 *)walk->iv);
|
||||
|
||||
/* Process three block batch */
|
||||
if (nbytes >= bsize * 3) {
|
||||
do {
|
||||
if (dst != src) {
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[1];
|
||||
dst[2] = src[2];
|
||||
}
|
||||
|
||||
/* create ctrblks for parallel encrypt */
|
||||
u128_to_be128(&ctrblocks[0], &ctrblk);
|
||||
u128_inc(&ctrblk);
|
||||
u128_to_be128(&ctrblocks[1], &ctrblk);
|
||||
u128_inc(&ctrblk);
|
||||
u128_to_be128(&ctrblocks[2], &ctrblk);
|
||||
u128_inc(&ctrblk);
|
||||
|
||||
twofish_enc_blk_xor_3way(ctx, (u8 *)dst,
|
||||
(u8 *)ctrblocks);
|
||||
|
||||
src += 3;
|
||||
dst += 3;
|
||||
nbytes -= bsize * 3;
|
||||
} while (nbytes >= bsize * 3);
|
||||
|
||||
if (nbytes < bsize)
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Handle leftovers */
|
||||
do {
|
||||
if (dst != src)
|
||||
*dst = *src;
|
||||
|
||||
u128_to_be128(&ctrblocks[0], &ctrblk);
|
||||
u128_inc(&ctrblk);
|
||||
|
||||
twofish_enc_blk(ctx, (u8 *)ctrblocks, (u8 *)ctrblocks);
|
||||
u128_xor(dst, dst, (u128 *)ctrblocks);
|
||||
|
||||
src += 1;
|
||||
dst += 1;
|
||||
nbytes -= bsize;
|
||||
} while (nbytes >= bsize);
|
||||
|
||||
done:
|
||||
u128_to_be128((be128 *)walk->iv, &ctrblk);
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
static int ctr_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
|
||||
struct scatterlist *src, unsigned int nbytes)
|
||||
{
|
||||
struct blkcipher_walk walk;
|
||||
int err;
|
||||
|
||||
blkcipher_walk_init(&walk, dst, src, nbytes);
|
||||
err = blkcipher_walk_virt_block(desc, &walk, TF_BLOCK_SIZE);
|
||||
|
||||
while ((nbytes = walk.nbytes) >= TF_BLOCK_SIZE) {
|
||||
nbytes = __ctr_crypt(desc, &walk);
|
||||
err = blkcipher_walk_done(desc, &walk, nbytes);
|
||||
}
|
||||
|
||||
if (walk.nbytes) {
|
||||
ctr_crypt_final(desc, &walk);
|
||||
err = blkcipher_walk_done(desc, &walk, 0);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct crypto_alg blk_ctr_alg = {
|
||||
.cra_name = "ctr(twofish)",
|
||||
.cra_driver_name = "ctr-twofish-3way",
|
||||
.cra_priority = 300,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
|
||||
.cra_blocksize = 1,
|
||||
.cra_ctxsize = sizeof(struct twofish_ctx),
|
||||
.cra_alignmask = 0,
|
||||
.cra_type = &crypto_blkcipher_type,
|
||||
.cra_module = THIS_MODULE,
|
||||
.cra_list = LIST_HEAD_INIT(blk_ctr_alg.cra_list),
|
||||
.cra_u = {
|
||||
.blkcipher = {
|
||||
.min_keysize = TF_MIN_KEY_SIZE,
|
||||
.max_keysize = TF_MAX_KEY_SIZE,
|
||||
.ivsize = TF_BLOCK_SIZE,
|
||||
.setkey = twofish_setkey,
|
||||
.encrypt = ctr_crypt,
|
||||
.decrypt = ctr_crypt,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
int __init init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = crypto_register_alg(&blk_ecb_alg);
|
||||
if (err)
|
||||
goto ecb_err;
|
||||
err = crypto_register_alg(&blk_cbc_alg);
|
||||
if (err)
|
||||
goto cbc_err;
|
||||
err = crypto_register_alg(&blk_ctr_alg);
|
||||
if (err)
|
||||
goto ctr_err;
|
||||
|
||||
return 0;
|
||||
|
||||
ctr_err:
|
||||
crypto_unregister_alg(&blk_cbc_alg);
|
||||
cbc_err:
|
||||
crypto_unregister_alg(&blk_ecb_alg);
|
||||
ecb_err:
|
||||
return err;
|
||||
}
|
||||
|
||||
void __exit fini(void)
|
||||
{
|
||||
crypto_unregister_alg(&blk_ctr_alg);
|
||||
crypto_unregister_alg(&blk_cbc_alg);
|
||||
crypto_unregister_alg(&blk_ecb_alg);
|
||||
}
|
||||
|
||||
module_init(init);
|
||||
module_exit(fini);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Twofish Cipher Algorithm, 3-way parallel asm optimized");
|
||||
MODULE_ALIAS("twofish");
|
||||
MODULE_ALIAS("twofish-asm");
|
@ -259,7 +259,9 @@ extern const char * const x86_power_flags[32];
|
||||
#define cpu_has_xmm boot_cpu_has(X86_FEATURE_XMM)
|
||||
#define cpu_has_xmm2 boot_cpu_has(X86_FEATURE_XMM2)
|
||||
#define cpu_has_xmm3 boot_cpu_has(X86_FEATURE_XMM3)
|
||||
#define cpu_has_ssse3 boot_cpu_has(X86_FEATURE_SSSE3)
|
||||
#define cpu_has_aes boot_cpu_has(X86_FEATURE_AES)
|
||||
#define cpu_has_avx boot_cpu_has(X86_FEATURE_AVX)
|
||||
#define cpu_has_ht boot_cpu_has(X86_FEATURE_HT)
|
||||
#define cpu_has_mp boot_cpu_has(X86_FEATURE_MP)
|
||||
#define cpu_has_nx boot_cpu_has(X86_FEATURE_NX)
|
||||
@ -287,6 +289,7 @@ extern const char * const x86_power_flags[32];
|
||||
#define cpu_has_xmm4_2 boot_cpu_has(X86_FEATURE_XMM4_2)
|
||||
#define cpu_has_x2apic boot_cpu_has(X86_FEATURE_X2APIC)
|
||||
#define cpu_has_xsave boot_cpu_has(X86_FEATURE_XSAVE)
|
||||
#define cpu_has_osxsave boot_cpu_has(X86_FEATURE_OSXSAVE)
|
||||
#define cpu_has_hypervisor boot_cpu_has(X86_FEATURE_HYPERVISOR)
|
||||
#define cpu_has_pclmulqdq boot_cpu_has(X86_FEATURE_PCLMULQDQ)
|
||||
#define cpu_has_perfctr_core boot_cpu_has(X86_FEATURE_PERFCTR_CORE)
|
||||
|
@ -100,6 +100,14 @@ config CRYPTO_MANAGER2
|
||||
select CRYPTO_BLKCIPHER2
|
||||
select CRYPTO_PCOMP2
|
||||
|
||||
config CRYPTO_USER
|
||||
tristate "Userspace cryptographic algorithm configuration"
|
||||
depends on NET
|
||||
select CRYPTO_MANAGER
|
||||
help
|
||||
Userapace configuration for cryptographic instantiations such as
|
||||
cbc(aes).
|
||||
|
||||
config CRYPTO_MANAGER_DISABLE_TESTS
|
||||
bool "Disable run-time self tests"
|
||||
default y
|
||||
@ -407,6 +415,16 @@ config CRYPTO_SHA1
|
||||
help
|
||||
SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2).
|
||||
|
||||
config CRYPTO_SHA1_SSSE3
|
||||
tristate "SHA1 digest algorithm (SSSE3/AVX)"
|
||||
depends on X86 && 64BIT
|
||||
select CRYPTO_SHA1
|
||||
select CRYPTO_HASH
|
||||
help
|
||||
SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2) implemented
|
||||
using Supplemental SSE3 (SSSE3) instructions or Advanced Vector
|
||||
Extensions (AVX), when available.
|
||||
|
||||
config CRYPTO_SHA256
|
||||
tristate "SHA224 and SHA256 digest algorithm"
|
||||
select CRYPTO_HASH
|
||||
@ -590,6 +608,7 @@ config CRYPTO_ARC4
|
||||
config CRYPTO_BLOWFISH
|
||||
tristate "Blowfish cipher algorithm"
|
||||
select CRYPTO_ALGAPI
|
||||
select CRYPTO_BLOWFISH_COMMON
|
||||
help
|
||||
Blowfish cipher algorithm, by Bruce Schneier.
|
||||
|
||||
@ -600,6 +619,30 @@ config CRYPTO_BLOWFISH
|
||||
See also:
|
||||
<http://www.schneier.com/blowfish.html>
|
||||
|
||||
config CRYPTO_BLOWFISH_COMMON
|
||||
tristate
|
||||
help
|
||||
Common parts of the Blowfish cipher algorithm shared by the
|
||||
generic c and the assembler implementations.
|
||||
|
||||
See also:
|
||||
<http://www.schneier.com/blowfish.html>
|
||||
|
||||
config CRYPTO_BLOWFISH_X86_64
|
||||
tristate "Blowfish cipher algorithm (x86_64)"
|
||||
depends on (X86 || UML_X86) && 64BIT
|
||||
select CRYPTO_ALGAPI
|
||||
select CRYPTO_BLOWFISH_COMMON
|
||||
help
|
||||
Blowfish cipher algorithm (x86_64), by Bruce Schneier.
|
||||
|
||||
This is a variable key length cipher which can use keys from 32
|
||||
bits to 448 bits in length. It's fast, simple and specifically
|
||||
designed for use on "large microprocessors".
|
||||
|
||||
See also:
|
||||
<http://www.schneier.com/blowfish.html>
|
||||
|
||||
config CRYPTO_CAMELLIA
|
||||
tristate "Camellia cipher algorithms"
|
||||
depends on CRYPTO
|
||||
@ -793,6 +836,26 @@ config CRYPTO_TWOFISH_X86_64
|
||||
See also:
|
||||
<http://www.schneier.com/twofish.html>
|
||||
|
||||
config CRYPTO_TWOFISH_X86_64_3WAY
|
||||
tristate "Twofish cipher algorithm (x86_64, 3-way parallel)"
|
||||
depends on (X86 || UML_X86) && 64BIT
|
||||
select CRYPTO_ALGAPI
|
||||
select CRYPTO_TWOFISH_COMMON
|
||||
select CRYPTO_TWOFISH_X86_64
|
||||
help
|
||||
Twofish cipher algorithm (x86_64, 3-way parallel).
|
||||
|
||||
Twofish was submitted as an AES (Advanced Encryption Standard)
|
||||
candidate cipher by researchers at CounterPane Systems. It is a
|
||||
16 round block cipher supporting key sizes of 128, 192, and 256
|
||||
bits.
|
||||
|
||||
This module provides Twofish cipher algorithm that processes three
|
||||
blocks parallel, utilizing resources of out-of-order CPUs better.
|
||||
|
||||
See also:
|
||||
<http://www.schneier.com/twofish.html>
|
||||
|
||||
comment "Compression"
|
||||
|
||||
config CRYPTO_DEFLATE
|
||||
|
@ -31,6 +31,7 @@ obj-$(CONFIG_CRYPTO_PCOMP2) += pcompress.o
|
||||
cryptomgr-y := algboss.o testmgr.o
|
||||
|
||||
obj-$(CONFIG_CRYPTO_MANAGER2) += cryptomgr.o
|
||||
obj-$(CONFIG_CRYPTO_USER) += crypto_user.o
|
||||
obj-$(CONFIG_CRYPTO_HMAC) += hmac.o
|
||||
obj-$(CONFIG_CRYPTO_VMAC) += vmac.o
|
||||
obj-$(CONFIG_CRYPTO_XCBC) += xcbc.o
|
||||
@ -60,7 +61,8 @@ obj-$(CONFIG_CRYPTO_PCRYPT) += pcrypt.o
|
||||
obj-$(CONFIG_CRYPTO_CRYPTD) += cryptd.o
|
||||
obj-$(CONFIG_CRYPTO_DES) += des_generic.o
|
||||
obj-$(CONFIG_CRYPTO_FCRYPT) += fcrypt.o
|
||||
obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish.o
|
||||
obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish_generic.o
|
||||
obj-$(CONFIG_CRYPTO_BLOWFISH_COMMON) += blowfish_common.o
|
||||
obj-$(CONFIG_CRYPTO_TWOFISH) += twofish_generic.o
|
||||
obj-$(CONFIG_CRYPTO_TWOFISH_COMMON) += twofish_common.o
|
||||
obj-$(CONFIG_CRYPTO_SERPENT) += serpent.o
|
||||
|
@ -23,6 +23,8 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/cryptouser.h>
|
||||
#include <net/netlink.h>
|
||||
|
||||
#include <crypto/scatterwalk.h>
|
||||
|
||||
@ -381,6 +383,28 @@ static int crypto_init_ablkcipher_ops(struct crypto_tfm *tfm, u32 type,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int crypto_ablkcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
|
||||
{
|
||||
struct crypto_report_blkcipher rblkcipher;
|
||||
|
||||
snprintf(rblkcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "ablkcipher");
|
||||
snprintf(rblkcipher.geniv, CRYPTO_MAX_ALG_NAME, "%s",
|
||||
alg->cra_ablkcipher.geniv ?: "<default>");
|
||||
|
||||
rblkcipher.blocksize = alg->cra_blocksize;
|
||||
rblkcipher.min_keysize = alg->cra_ablkcipher.min_keysize;
|
||||
rblkcipher.max_keysize = alg->cra_ablkcipher.max_keysize;
|
||||
rblkcipher.ivsize = alg->cra_ablkcipher.ivsize;
|
||||
|
||||
NLA_PUT(skb, CRYPTOCFGA_REPORT_BLKCIPHER,
|
||||
sizeof(struct crypto_report_blkcipher), &rblkcipher);
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static void crypto_ablkcipher_show(struct seq_file *m, struct crypto_alg *alg)
|
||||
__attribute__ ((unused));
|
||||
static void crypto_ablkcipher_show(struct seq_file *m, struct crypto_alg *alg)
|
||||
@ -403,6 +427,7 @@ const struct crypto_type crypto_ablkcipher_type = {
|
||||
#ifdef CONFIG_PROC_FS
|
||||
.show = crypto_ablkcipher_show,
|
||||
#endif
|
||||
.report = crypto_ablkcipher_report,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(crypto_ablkcipher_type);
|
||||
|
||||
@ -432,6 +457,28 @@ static int crypto_init_givcipher_ops(struct crypto_tfm *tfm, u32 type,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int crypto_givcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
|
||||
{
|
||||
struct crypto_report_blkcipher rblkcipher;
|
||||
|
||||
snprintf(rblkcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "givcipher");
|
||||
snprintf(rblkcipher.geniv, CRYPTO_MAX_ALG_NAME, "%s",
|
||||
alg->cra_ablkcipher.geniv ?: "<built-in>");
|
||||
|
||||
rblkcipher.blocksize = alg->cra_blocksize;
|
||||
rblkcipher.min_keysize = alg->cra_ablkcipher.min_keysize;
|
||||
rblkcipher.max_keysize = alg->cra_ablkcipher.max_keysize;
|
||||
rblkcipher.ivsize = alg->cra_ablkcipher.ivsize;
|
||||
|
||||
NLA_PUT(skb, CRYPTOCFGA_REPORT_BLKCIPHER,
|
||||
sizeof(struct crypto_report_blkcipher), &rblkcipher);
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static void crypto_givcipher_show(struct seq_file *m, struct crypto_alg *alg)
|
||||
__attribute__ ((unused));
|
||||
static void crypto_givcipher_show(struct seq_file *m, struct crypto_alg *alg)
|
||||
@ -454,6 +501,7 @@ const struct crypto_type crypto_givcipher_type = {
|
||||
#ifdef CONFIG_PROC_FS
|
||||
.show = crypto_givcipher_show,
|
||||
#endif
|
||||
.report = crypto_givcipher_report,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(crypto_givcipher_type);
|
||||
|
||||
|
@ -21,6 +21,8 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/cryptouser.h>
|
||||
#include <net/netlink.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
@ -109,6 +111,28 @@ static int crypto_init_aead_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int crypto_aead_report(struct sk_buff *skb, struct crypto_alg *alg)
|
||||
{
|
||||
struct crypto_report_aead raead;
|
||||
struct aead_alg *aead = &alg->cra_aead;
|
||||
|
||||
snprintf(raead.type, CRYPTO_MAX_ALG_NAME, "%s", "aead");
|
||||
snprintf(raead.geniv, CRYPTO_MAX_ALG_NAME, "%s",
|
||||
aead->geniv ?: "<built-in>");
|
||||
|
||||
raead.blocksize = alg->cra_blocksize;
|
||||
raead.maxauthsize = aead->maxauthsize;
|
||||
raead.ivsize = aead->ivsize;
|
||||
|
||||
NLA_PUT(skb, CRYPTOCFGA_REPORT_AEAD,
|
||||
sizeof(struct crypto_report_aead), &raead);
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg)
|
||||
__attribute__ ((unused));
|
||||
static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg)
|
||||
@ -130,6 +154,7 @@ const struct crypto_type crypto_aead_type = {
|
||||
#ifdef CONFIG_PROC_FS
|
||||
.show = crypto_aead_show,
|
||||
#endif
|
||||
.report = crypto_aead_report,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(crypto_aead_type);
|
||||
|
||||
@ -165,6 +190,28 @@ static int crypto_init_nivaead_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int crypto_nivaead_report(struct sk_buff *skb, struct crypto_alg *alg)
|
||||
{
|
||||
struct crypto_report_aead raead;
|
||||
struct aead_alg *aead = &alg->cra_aead;
|
||||
|
||||
snprintf(raead.type, CRYPTO_MAX_ALG_NAME, "%s", "nivaead");
|
||||
snprintf(raead.geniv, CRYPTO_MAX_ALG_NAME, "%s", aead->geniv);
|
||||
|
||||
raead.blocksize = alg->cra_blocksize;
|
||||
raead.maxauthsize = aead->maxauthsize;
|
||||
raead.ivsize = aead->ivsize;
|
||||
|
||||
NLA_PUT(skb, CRYPTOCFGA_REPORT_AEAD,
|
||||
sizeof(struct crypto_report_aead), &raead);
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
|
||||
static void crypto_nivaead_show(struct seq_file *m, struct crypto_alg *alg)
|
||||
__attribute__ ((unused));
|
||||
static void crypto_nivaead_show(struct seq_file *m, struct crypto_alg *alg)
|
||||
@ -186,6 +233,7 @@ const struct crypto_type crypto_nivaead_type = {
|
||||
#ifdef CONFIG_PROC_FS
|
||||
.show = crypto_nivaead_show,
|
||||
#endif
|
||||
.report = crypto_nivaead_report,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(crypto_nivaead_type);
|
||||
|
||||
|
@ -21,6 +21,8 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/cryptouser.h>
|
||||
#include <net/netlink.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
@ -397,6 +399,24 @@ static unsigned int crypto_ahash_extsize(struct crypto_alg *alg)
|
||||
return sizeof(struct crypto_shash *);
|
||||
}
|
||||
|
||||
static int crypto_ahash_report(struct sk_buff *skb, struct crypto_alg *alg)
|
||||
{
|
||||
struct crypto_report_hash rhash;
|
||||
|
||||
snprintf(rhash.type, CRYPTO_MAX_ALG_NAME, "%s", "ahash");
|
||||
|
||||
rhash.blocksize = alg->cra_blocksize;
|
||||
rhash.digestsize = __crypto_hash_alg_common(alg)->digestsize;
|
||||
|
||||
NLA_PUT(skb, CRYPTOCFGA_REPORT_HASH,
|
||||
sizeof(struct crypto_report_hash), &rhash);
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static void crypto_ahash_show(struct seq_file *m, struct crypto_alg *alg)
|
||||
__attribute__ ((unused));
|
||||
static void crypto_ahash_show(struct seq_file *m, struct crypto_alg *alg)
|
||||
@ -415,6 +435,7 @@ const struct crypto_type crypto_ahash_type = {
|
||||
#ifdef CONFIG_PROC_FS
|
||||
.show = crypto_ahash_show,
|
||||
#endif
|
||||
.report = crypto_ahash_report,
|
||||
.maskclear = ~CRYPTO_ALG_TYPE_MASK,
|
||||
.maskset = CRYPTO_ALG_TYPE_AHASH_MASK,
|
||||
.type = CRYPTO_ALG_TYPE_AHASH,
|
||||
|
@ -22,8 +22,6 @@
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
static void crypto_remove_final(struct list_head *list);
|
||||
|
||||
static LIST_HEAD(crypto_template_list);
|
||||
|
||||
void crypto_larval_error(const char *name, u32 type, u32 mask)
|
||||
@ -129,9 +127,8 @@ static void crypto_remove_spawn(struct crypto_spawn *spawn,
|
||||
BUG_ON(!list_empty(&inst->alg.cra_users));
|
||||
}
|
||||
|
||||
static void crypto_remove_spawns(struct crypto_alg *alg,
|
||||
struct list_head *list,
|
||||
struct crypto_alg *nalg)
|
||||
void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list,
|
||||
struct crypto_alg *nalg)
|
||||
{
|
||||
u32 new_type = (nalg ?: alg)->cra_flags;
|
||||
struct crypto_spawn *spawn, *n;
|
||||
@ -177,6 +174,7 @@ static void crypto_remove_spawns(struct crypto_alg *alg,
|
||||
crypto_remove_spawn(spawn, list);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_remove_spawns);
|
||||
|
||||
static struct crypto_larval *__crypto_register_alg(struct crypto_alg *alg)
|
||||
{
|
||||
@ -321,7 +319,7 @@ unlock:
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_alg_tested);
|
||||
|
||||
static void crypto_remove_final(struct list_head *list)
|
||||
void crypto_remove_final(struct list_head *list)
|
||||
{
|
||||
struct crypto_alg *alg;
|
||||
struct crypto_alg *n;
|
||||
@ -331,6 +329,7 @@ static void crypto_remove_final(struct list_head *list)
|
||||
crypto_alg_put(alg);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_remove_final);
|
||||
|
||||
static void crypto_wait_for_test(struct crypto_larval *larval)
|
||||
{
|
||||
@ -493,6 +492,7 @@ int crypto_register_instance(struct crypto_template *tmpl,
|
||||
goto err;
|
||||
|
||||
inst->alg.cra_module = tmpl->module;
|
||||
inst->alg.cra_flags |= CRYPTO_ALG_INSTANCE;
|
||||
|
||||
down_write(&crypto_alg_sem);
|
||||
|
||||
|
@ -24,6 +24,8 @@
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/cryptouser.h>
|
||||
#include <net/netlink.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
@ -492,6 +494,28 @@ static int crypto_init_blkcipher_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
|
||||
return crypto_init_blkcipher_ops_async(tfm);
|
||||
}
|
||||
|
||||
static int crypto_blkcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
|
||||
{
|
||||
struct crypto_report_blkcipher rblkcipher;
|
||||
|
||||
snprintf(rblkcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "blkcipher");
|
||||
snprintf(rblkcipher.geniv, CRYPTO_MAX_ALG_NAME, "%s",
|
||||
alg->cra_blkcipher.geniv ?: "<default>");
|
||||
|
||||
rblkcipher.blocksize = alg->cra_blocksize;
|
||||
rblkcipher.min_keysize = alg->cra_blkcipher.min_keysize;
|
||||
rblkcipher.max_keysize = alg->cra_blkcipher.max_keysize;
|
||||
rblkcipher.ivsize = alg->cra_blkcipher.ivsize;
|
||||
|
||||
NLA_PUT(skb, CRYPTOCFGA_REPORT_BLKCIPHER,
|
||||
sizeof(struct crypto_report_blkcipher), &rblkcipher);
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static void crypto_blkcipher_show(struct seq_file *m, struct crypto_alg *alg)
|
||||
__attribute__ ((unused));
|
||||
static void crypto_blkcipher_show(struct seq_file *m, struct crypto_alg *alg)
|
||||
@ -511,6 +535,7 @@ const struct crypto_type crypto_blkcipher_type = {
|
||||
#ifdef CONFIG_PROC_FS
|
||||
.show = crypto_blkcipher_show,
|
||||
#endif
|
||||
.report = crypto_blkcipher_report,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(crypto_blkcipher_type);
|
||||
|
||||
|
@ -1,6 +1,9 @@
|
||||
/*
|
||||
* Cryptographic API.
|
||||
*
|
||||
* Common Blowfish algorithm parts shared between the c and assembler
|
||||
* implementations.
|
||||
*
|
||||
* Blowfish Cipher Algorithm, by Bruce Schneier.
|
||||
* http://www.counterpane.com/blowfish.html
|
||||
*
|
||||
@ -22,15 +25,7 @@
|
||||
#include <asm/byteorder.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#define BF_BLOCK_SIZE 8
|
||||
#define BF_MIN_KEY_SIZE 4
|
||||
#define BF_MAX_KEY_SIZE 56
|
||||
|
||||
struct bf_ctx {
|
||||
u32 p[18];
|
||||
u32 s[1024];
|
||||
};
|
||||
#include <crypto/blowfish.h>
|
||||
|
||||
static const u32 bf_pbox[16 + 2] = {
|
||||
0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
|
||||
@ -309,9 +304,9 @@ static const u32 bf_sbox[256 * 4] = {
|
||||
#define GET32_0(x) (((x) >> (24)) & (0xff))
|
||||
|
||||
#define bf_F(x) (((S[GET32_0(x)] + S[256 + GET32_1(x)]) ^ \
|
||||
S[512 + GET32_2(x)]) + S[768 + GET32_3(x)])
|
||||
S[512 + GET32_2(x)]) + S[768 + GET32_3(x)])
|
||||
|
||||
#define ROUND(a, b, n) b ^= P[n]; a ^= bf_F (b)
|
||||
#define ROUND(a, b, n) ({ b ^= P[n]; a ^= bf_F(b); })
|
||||
|
||||
/*
|
||||
* The blowfish encipher, processes 64-bit blocks.
|
||||
@ -348,57 +343,10 @@ static void encrypt_block(struct bf_ctx *bctx, u32 *dst, u32 *src)
|
||||
dst[1] = yl;
|
||||
}
|
||||
|
||||
static void bf_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
|
||||
{
|
||||
const __be32 *in_blk = (const __be32 *)src;
|
||||
__be32 *const out_blk = (__be32 *)dst;
|
||||
u32 in32[2], out32[2];
|
||||
|
||||
in32[0] = be32_to_cpu(in_blk[0]);
|
||||
in32[1] = be32_to_cpu(in_blk[1]);
|
||||
encrypt_block(crypto_tfm_ctx(tfm), out32, in32);
|
||||
out_blk[0] = cpu_to_be32(out32[0]);
|
||||
out_blk[1] = cpu_to_be32(out32[1]);
|
||||
}
|
||||
|
||||
static void bf_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
|
||||
{
|
||||
struct bf_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
const __be32 *in_blk = (const __be32 *)src;
|
||||
__be32 *const out_blk = (__be32 *)dst;
|
||||
const u32 *P = ctx->p;
|
||||
const u32 *S = ctx->s;
|
||||
u32 yl = be32_to_cpu(in_blk[0]);
|
||||
u32 yr = be32_to_cpu(in_blk[1]);
|
||||
|
||||
ROUND(yr, yl, 17);
|
||||
ROUND(yl, yr, 16);
|
||||
ROUND(yr, yl, 15);
|
||||
ROUND(yl, yr, 14);
|
||||
ROUND(yr, yl, 13);
|
||||
ROUND(yl, yr, 12);
|
||||
ROUND(yr, yl, 11);
|
||||
ROUND(yl, yr, 10);
|
||||
ROUND(yr, yl, 9);
|
||||
ROUND(yl, yr, 8);
|
||||
ROUND(yr, yl, 7);
|
||||
ROUND(yl, yr, 6);
|
||||
ROUND(yr, yl, 5);
|
||||
ROUND(yl, yr, 4);
|
||||
ROUND(yr, yl, 3);
|
||||
ROUND(yl, yr, 2);
|
||||
|
||||
yl ^= P[1];
|
||||
yr ^= P[0];
|
||||
|
||||
out_blk[0] = cpu_to_be32(yr);
|
||||
out_blk[1] = cpu_to_be32(yl);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculates the blowfish S and P boxes for encryption and decryption.
|
||||
*/
|
||||
static int bf_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
|
||||
int blowfish_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
|
||||
{
|
||||
struct bf_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
u32 *P = ctx->p;
|
||||
@ -448,35 +396,7 @@ static int bf_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
|
||||
/* Bruce says not to bother with the weak key check. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct crypto_alg alg = {
|
||||
.cra_name = "blowfish",
|
||||
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
|
||||
.cra_blocksize = BF_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct bf_ctx),
|
||||
.cra_alignmask = 3,
|
||||
.cra_module = THIS_MODULE,
|
||||
.cra_list = LIST_HEAD_INIT(alg.cra_list),
|
||||
.cra_u = { .cipher = {
|
||||
.cia_min_keysize = BF_MIN_KEY_SIZE,
|
||||
.cia_max_keysize = BF_MAX_KEY_SIZE,
|
||||
.cia_setkey = bf_setkey,
|
||||
.cia_encrypt = bf_encrypt,
|
||||
.cia_decrypt = bf_decrypt } }
|
||||
};
|
||||
|
||||
static int __init blowfish_mod_init(void)
|
||||
{
|
||||
return crypto_register_alg(&alg);
|
||||
}
|
||||
|
||||
static void __exit blowfish_mod_fini(void)
|
||||
{
|
||||
crypto_unregister_alg(&alg);
|
||||
}
|
||||
|
||||
module_init(blowfish_mod_init);
|
||||
module_exit(blowfish_mod_fini);
|
||||
EXPORT_SYMBOL_GPL(blowfish_setkey);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Blowfish Cipher Algorithm");
|
||||
MODULE_DESCRIPTION("Blowfish Cipher common functions");
|
142
crypto/blowfish_generic.c
Normal file
142
crypto/blowfish_generic.c
Normal file
@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Cryptographic API.
|
||||
*
|
||||
* Blowfish Cipher Algorithm, by Bruce Schneier.
|
||||
* http://www.counterpane.com/blowfish.html
|
||||
*
|
||||
* Adapted from Kerneli implementation.
|
||||
*
|
||||
* Copyright (c) Herbert Valerio Riedel <hvr@hvrlab.org>
|
||||
* Copyright (c) Kyle McMartin <kyle@debian.org>
|
||||
* Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mm.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/types.h>
|
||||
#include <crypto/blowfish.h>
|
||||
|
||||
/*
|
||||
* Round loop unrolling macros, S is a pointer to a S-Box array
|
||||
* organized in 4 unsigned longs at a row.
|
||||
*/
|
||||
#define GET32_3(x) (((x) & 0xff))
|
||||
#define GET32_2(x) (((x) >> (8)) & (0xff))
|
||||
#define GET32_1(x) (((x) >> (16)) & (0xff))
|
||||
#define GET32_0(x) (((x) >> (24)) & (0xff))
|
||||
|
||||
#define bf_F(x) (((S[GET32_0(x)] + S[256 + GET32_1(x)]) ^ \
|
||||
S[512 + GET32_2(x)]) + S[768 + GET32_3(x)])
|
||||
|
||||
#define ROUND(a, b, n) ({ b ^= P[n]; a ^= bf_F(b); })
|
||||
|
||||
static void bf_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
|
||||
{
|
||||
struct bf_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
const __be32 *in_blk = (const __be32 *)src;
|
||||
__be32 *const out_blk = (__be32 *)dst;
|
||||
const u32 *P = ctx->p;
|
||||
const u32 *S = ctx->s;
|
||||
u32 yl = be32_to_cpu(in_blk[0]);
|
||||
u32 yr = be32_to_cpu(in_blk[1]);
|
||||
|
||||
ROUND(yr, yl, 0);
|
||||
ROUND(yl, yr, 1);
|
||||
ROUND(yr, yl, 2);
|
||||
ROUND(yl, yr, 3);
|
||||
ROUND(yr, yl, 4);
|
||||
ROUND(yl, yr, 5);
|
||||
ROUND(yr, yl, 6);
|
||||
ROUND(yl, yr, 7);
|
||||
ROUND(yr, yl, 8);
|
||||
ROUND(yl, yr, 9);
|
||||
ROUND(yr, yl, 10);
|
||||
ROUND(yl, yr, 11);
|
||||
ROUND(yr, yl, 12);
|
||||
ROUND(yl, yr, 13);
|
||||
ROUND(yr, yl, 14);
|
||||
ROUND(yl, yr, 15);
|
||||
|
||||
yl ^= P[16];
|
||||
yr ^= P[17];
|
||||
|
||||
out_blk[0] = cpu_to_be32(yr);
|
||||
out_blk[1] = cpu_to_be32(yl);
|
||||
}
|
||||
|
||||
static void bf_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
|
||||
{
|
||||
struct bf_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
const __be32 *in_blk = (const __be32 *)src;
|
||||
__be32 *const out_blk = (__be32 *)dst;
|
||||
const u32 *P = ctx->p;
|
||||
const u32 *S = ctx->s;
|
||||
u32 yl = be32_to_cpu(in_blk[0]);
|
||||
u32 yr = be32_to_cpu(in_blk[1]);
|
||||
|
||||
ROUND(yr, yl, 17);
|
||||
ROUND(yl, yr, 16);
|
||||
ROUND(yr, yl, 15);
|
||||
ROUND(yl, yr, 14);
|
||||
ROUND(yr, yl, 13);
|
||||
ROUND(yl, yr, 12);
|
||||
ROUND(yr, yl, 11);
|
||||
ROUND(yl, yr, 10);
|
||||
ROUND(yr, yl, 9);
|
||||
ROUND(yl, yr, 8);
|
||||
ROUND(yr, yl, 7);
|
||||
ROUND(yl, yr, 6);
|
||||
ROUND(yr, yl, 5);
|
||||
ROUND(yl, yr, 4);
|
||||
ROUND(yr, yl, 3);
|
||||
ROUND(yl, yr, 2);
|
||||
|
||||
yl ^= P[1];
|
||||
yr ^= P[0];
|
||||
|
||||
out_blk[0] = cpu_to_be32(yr);
|
||||
out_blk[1] = cpu_to_be32(yl);
|
||||
}
|
||||
|
||||
static struct crypto_alg alg = {
|
||||
.cra_name = "blowfish",
|
||||
.cra_driver_name = "blowfish-generic",
|
||||
.cra_priority = 100,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
|
||||
.cra_blocksize = BF_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct bf_ctx),
|
||||
.cra_alignmask = 3,
|
||||
.cra_module = THIS_MODULE,
|
||||
.cra_list = LIST_HEAD_INIT(alg.cra_list),
|
||||
.cra_u = { .cipher = {
|
||||
.cia_min_keysize = BF_MIN_KEY_SIZE,
|
||||
.cia_max_keysize = BF_MAX_KEY_SIZE,
|
||||
.cia_setkey = blowfish_setkey,
|
||||
.cia_encrypt = bf_encrypt,
|
||||
.cia_decrypt = bf_decrypt } }
|
||||
};
|
||||
|
||||
static int __init blowfish_mod_init(void)
|
||||
{
|
||||
return crypto_register_alg(&alg);
|
||||
}
|
||||
|
||||
static void __exit blowfish_mod_fini(void)
|
||||
{
|
||||
crypto_unregister_alg(&alg);
|
||||
}
|
||||
|
||||
module_init(blowfish_mod_init);
|
||||
module_exit(blowfish_mod_fini);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Blowfish Cipher Algorithm");
|
||||
MODULE_ALIAS("blowfish");
|
@ -945,7 +945,7 @@ static void __exit cryptd_exit(void)
|
||||
crypto_unregister_template(&cryptd_tmpl);
|
||||
}
|
||||
|
||||
module_init(cryptd_init);
|
||||
subsys_initcall(cryptd_init);
|
||||
module_exit(cryptd_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
438
crypto/crypto_user.c
Normal file
438
crypto/crypto_user.c
Normal file
@ -0,0 +1,438 @@
|
||||
/*
|
||||
* Crypto user configuration API.
|
||||
*
|
||||
* Copyright (C) 2011 secunet Security Networks AG
|
||||
* Copyright (C) 2011 Steffen Klassert <steffen.klassert@secunet.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope 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, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/cryptouser.h>
|
||||
#include <net/netlink.h>
|
||||
#include <linux/security.h>
|
||||
#include <net/net_namespace.h>
|
||||
#include "internal.h"
|
||||
|
||||
DEFINE_MUTEX(crypto_cfg_mutex);
|
||||
|
||||
/* The crypto netlink socket */
|
||||
static struct sock *crypto_nlsk;
|
||||
|
||||
struct crypto_dump_info {
|
||||
struct sk_buff *in_skb;
|
||||
struct sk_buff *out_skb;
|
||||
u32 nlmsg_seq;
|
||||
u16 nlmsg_flags;
|
||||
};
|
||||
|
||||
static struct crypto_alg *crypto_alg_match(struct crypto_user_alg *p, int exact)
|
||||
{
|
||||
struct crypto_alg *q, *alg = NULL;
|
||||
|
||||
down_read(&crypto_alg_sem);
|
||||
|
||||
if (list_empty(&crypto_alg_list))
|
||||
return NULL;
|
||||
|
||||
list_for_each_entry(q, &crypto_alg_list, cra_list) {
|
||||
int match = 0;
|
||||
|
||||
if ((q->cra_flags ^ p->cru_type) & p->cru_mask)
|
||||
continue;
|
||||
|
||||
if (strlen(p->cru_driver_name))
|
||||
match = !strcmp(q->cra_driver_name,
|
||||
p->cru_driver_name);
|
||||
else if (!exact)
|
||||
match = !strcmp(q->cra_name, p->cru_name);
|
||||
|
||||
if (match) {
|
||||
alg = q;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
up_read(&crypto_alg_sem);
|
||||
|
||||
return alg;
|
||||
}
|
||||
|
||||
static int crypto_report_cipher(struct sk_buff *skb, struct crypto_alg *alg)
|
||||
{
|
||||
struct crypto_report_cipher rcipher;
|
||||
|
||||
snprintf(rcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "cipher");
|
||||
|
||||
rcipher.blocksize = alg->cra_blocksize;
|
||||
rcipher.min_keysize = alg->cra_cipher.cia_min_keysize;
|
||||
rcipher.max_keysize = alg->cra_cipher.cia_max_keysize;
|
||||
|
||||
NLA_PUT(skb, CRYPTOCFGA_REPORT_CIPHER,
|
||||
sizeof(struct crypto_report_cipher), &rcipher);
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static int crypto_report_comp(struct sk_buff *skb, struct crypto_alg *alg)
|
||||
{
|
||||
struct crypto_report_comp rcomp;
|
||||
|
||||
snprintf(rcomp.type, CRYPTO_MAX_ALG_NAME, "%s", "compression");
|
||||
|
||||
NLA_PUT(skb, CRYPTOCFGA_REPORT_COMPRESS,
|
||||
sizeof(struct crypto_report_comp), &rcomp);
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static int crypto_report_one(struct crypto_alg *alg,
|
||||
struct crypto_user_alg *ualg, struct sk_buff *skb)
|
||||
{
|
||||
memcpy(&ualg->cru_name, &alg->cra_name, sizeof(ualg->cru_name));
|
||||
memcpy(&ualg->cru_driver_name, &alg->cra_driver_name,
|
||||
sizeof(ualg->cru_driver_name));
|
||||
memcpy(&ualg->cru_module_name, module_name(alg->cra_module),
|
||||
CRYPTO_MAX_ALG_NAME);
|
||||
|
||||
ualg->cru_flags = alg->cra_flags;
|
||||
ualg->cru_refcnt = atomic_read(&alg->cra_refcnt);
|
||||
|
||||
NLA_PUT_U32(skb, CRYPTOCFGA_PRIORITY_VAL, alg->cra_priority);
|
||||
|
||||
if (alg->cra_flags & CRYPTO_ALG_LARVAL) {
|
||||
struct crypto_report_larval rl;
|
||||
|
||||
snprintf(rl.type, CRYPTO_MAX_ALG_NAME, "%s", "larval");
|
||||
|
||||
NLA_PUT(skb, CRYPTOCFGA_REPORT_LARVAL,
|
||||
sizeof(struct crypto_report_larval), &rl);
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (alg->cra_type && alg->cra_type->report) {
|
||||
if (alg->cra_type->report(skb, alg))
|
||||
goto nla_put_failure;
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (alg->cra_flags & (CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_LARVAL)) {
|
||||
case CRYPTO_ALG_TYPE_CIPHER:
|
||||
if (crypto_report_cipher(skb, alg))
|
||||
goto nla_put_failure;
|
||||
|
||||
break;
|
||||
case CRYPTO_ALG_TYPE_COMPRESS:
|
||||
if (crypto_report_comp(skb, alg))
|
||||
goto nla_put_failure;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static int crypto_report_alg(struct crypto_alg *alg,
|
||||
struct crypto_dump_info *info)
|
||||
{
|
||||
struct sk_buff *in_skb = info->in_skb;
|
||||
struct sk_buff *skb = info->out_skb;
|
||||
struct nlmsghdr *nlh;
|
||||
struct crypto_user_alg *ualg;
|
||||
int err = 0;
|
||||
|
||||
nlh = nlmsg_put(skb, NETLINK_CB(in_skb).pid, info->nlmsg_seq,
|
||||
CRYPTO_MSG_GETALG, sizeof(*ualg), info->nlmsg_flags);
|
||||
if (!nlh) {
|
||||
err = -EMSGSIZE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ualg = nlmsg_data(nlh);
|
||||
|
||||
err = crypto_report_one(alg, ualg, skb);
|
||||
if (err) {
|
||||
nlmsg_cancel(skb, nlh);
|
||||
goto out;
|
||||
}
|
||||
|
||||
nlmsg_end(skb, nlh);
|
||||
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int crypto_report(struct sk_buff *in_skb, struct nlmsghdr *in_nlh,
|
||||
struct nlattr **attrs)
|
||||
{
|
||||
struct crypto_user_alg *p = nlmsg_data(in_nlh);
|
||||
struct crypto_alg *alg;
|
||||
struct sk_buff *skb;
|
||||
struct crypto_dump_info info;
|
||||
int err;
|
||||
|
||||
if (!p->cru_driver_name)
|
||||
return -EINVAL;
|
||||
|
||||
alg = crypto_alg_match(p, 1);
|
||||
if (!alg)
|
||||
return -ENOENT;
|
||||
|
||||
skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
info.in_skb = in_skb;
|
||||
info.out_skb = skb;
|
||||
info.nlmsg_seq = in_nlh->nlmsg_seq;
|
||||
info.nlmsg_flags = 0;
|
||||
|
||||
err = crypto_report_alg(alg, &info);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return nlmsg_unicast(crypto_nlsk, skb, NETLINK_CB(in_skb).pid);
|
||||
}
|
||||
|
||||
static int crypto_dump_report(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
struct crypto_alg *alg;
|
||||
struct crypto_dump_info info;
|
||||
int err;
|
||||
|
||||
if (cb->args[0])
|
||||
goto out;
|
||||
|
||||
cb->args[0] = 1;
|
||||
|
||||
info.in_skb = cb->skb;
|
||||
info.out_skb = skb;
|
||||
info.nlmsg_seq = cb->nlh->nlmsg_seq;
|
||||
info.nlmsg_flags = NLM_F_MULTI;
|
||||
|
||||
list_for_each_entry(alg, &crypto_alg_list, cra_list) {
|
||||
err = crypto_report_alg(alg, &info);
|
||||
if (err)
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
out:
|
||||
return skb->len;
|
||||
out_err:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int crypto_dump_report_done(struct netlink_callback *cb)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int crypto_update_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
struct nlattr **attrs)
|
||||
{
|
||||
struct crypto_alg *alg;
|
||||
struct crypto_user_alg *p = nlmsg_data(nlh);
|
||||
struct nlattr *priority = attrs[CRYPTOCFGA_PRIORITY_VAL];
|
||||
LIST_HEAD(list);
|
||||
|
||||
if (priority && !strlen(p->cru_driver_name))
|
||||
return -EINVAL;
|
||||
|
||||
alg = crypto_alg_match(p, 1);
|
||||
if (!alg)
|
||||
return -ENOENT;
|
||||
|
||||
down_write(&crypto_alg_sem);
|
||||
|
||||
crypto_remove_spawns(alg, &list, NULL);
|
||||
|
||||
if (priority)
|
||||
alg->cra_priority = nla_get_u32(priority);
|
||||
|
||||
up_write(&crypto_alg_sem);
|
||||
|
||||
crypto_remove_final(&list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int crypto_del_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
struct nlattr **attrs)
|
||||
{
|
||||
struct crypto_alg *alg;
|
||||
struct crypto_user_alg *p = nlmsg_data(nlh);
|
||||
|
||||
alg = crypto_alg_match(p, 1);
|
||||
if (!alg)
|
||||
return -ENOENT;
|
||||
|
||||
/* We can not unregister core algorithms such as aes-generic.
|
||||
* We would loose the reference in the crypto_alg_list to this algorithm
|
||||
* if we try to unregister. Unregistering such an algorithm without
|
||||
* removing the module is not possible, so we restrict to crypto
|
||||
* instances that are build from templates. */
|
||||
if (!(alg->cra_flags & CRYPTO_ALG_INSTANCE))
|
||||
return -EINVAL;
|
||||
|
||||
if (atomic_read(&alg->cra_refcnt) != 1)
|
||||
return -EBUSY;
|
||||
|
||||
return crypto_unregister_alg(alg);
|
||||
}
|
||||
|
||||
static int crypto_add_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
struct nlattr **attrs)
|
||||
{
|
||||
int exact;
|
||||
const char *name;
|
||||
struct crypto_alg *alg;
|
||||
struct crypto_user_alg *p = nlmsg_data(nlh);
|
||||
struct nlattr *priority = attrs[CRYPTOCFGA_PRIORITY_VAL];
|
||||
|
||||
if (strlen(p->cru_driver_name))
|
||||
exact = 1;
|
||||
|
||||
if (priority && !exact)
|
||||
return -EINVAL;
|
||||
|
||||
alg = crypto_alg_match(p, exact);
|
||||
if (alg)
|
||||
return -EEXIST;
|
||||
|
||||
if (strlen(p->cru_driver_name))
|
||||
name = p->cru_driver_name;
|
||||
else
|
||||
name = p->cru_name;
|
||||
|
||||
alg = crypto_alg_mod_lookup(name, p->cru_type, p->cru_mask);
|
||||
if (IS_ERR(alg))
|
||||
return PTR_ERR(alg);
|
||||
|
||||
down_write(&crypto_alg_sem);
|
||||
|
||||
if (priority)
|
||||
alg->cra_priority = nla_get_u32(priority);
|
||||
|
||||
up_write(&crypto_alg_sem);
|
||||
|
||||
crypto_mod_put(alg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define MSGSIZE(type) sizeof(struct type)
|
||||
|
||||
static const int crypto_msg_min[CRYPTO_NR_MSGTYPES] = {
|
||||
[CRYPTO_MSG_NEWALG - CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
|
||||
[CRYPTO_MSG_DELALG - CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
|
||||
[CRYPTO_MSG_UPDATEALG - CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
|
||||
[CRYPTO_MSG_GETALG - CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
|
||||
};
|
||||
|
||||
static const struct nla_policy crypto_policy[CRYPTOCFGA_MAX+1] = {
|
||||
[CRYPTOCFGA_PRIORITY_VAL] = { .type = NLA_U32},
|
||||
};
|
||||
|
||||
#undef MSGSIZE
|
||||
|
||||
static struct crypto_link {
|
||||
int (*doit)(struct sk_buff *, struct nlmsghdr *, struct nlattr **);
|
||||
int (*dump)(struct sk_buff *, struct netlink_callback *);
|
||||
int (*done)(struct netlink_callback *);
|
||||
} crypto_dispatch[CRYPTO_NR_MSGTYPES] = {
|
||||
[CRYPTO_MSG_NEWALG - CRYPTO_MSG_BASE] = { .doit = crypto_add_alg},
|
||||
[CRYPTO_MSG_DELALG - CRYPTO_MSG_BASE] = { .doit = crypto_del_alg},
|
||||
[CRYPTO_MSG_UPDATEALG - CRYPTO_MSG_BASE] = { .doit = crypto_update_alg},
|
||||
[CRYPTO_MSG_GETALG - CRYPTO_MSG_BASE] = { .doit = crypto_report,
|
||||
.dump = crypto_dump_report,
|
||||
.done = crypto_dump_report_done},
|
||||
};
|
||||
|
||||
static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
|
||||
{
|
||||
struct nlattr *attrs[CRYPTOCFGA_MAX+1];
|
||||
struct crypto_link *link;
|
||||
int type, err;
|
||||
|
||||
type = nlh->nlmsg_type;
|
||||
if (type > CRYPTO_MSG_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
type -= CRYPTO_MSG_BASE;
|
||||
link = &crypto_dispatch[type];
|
||||
|
||||
if (security_netlink_recv(skb, CAP_NET_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
if ((type == (CRYPTO_MSG_GETALG - CRYPTO_MSG_BASE) &&
|
||||
(nlh->nlmsg_flags & NLM_F_DUMP))) {
|
||||
if (link->dump == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
return netlink_dump_start(crypto_nlsk, skb, nlh,
|
||||
link->dump, link->done, 0);
|
||||
}
|
||||
|
||||
err = nlmsg_parse(nlh, crypto_msg_min[type], attrs, CRYPTOCFGA_MAX,
|
||||
crypto_policy);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (link->doit == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
return link->doit(skb, nlh, attrs);
|
||||
}
|
||||
|
||||
static void crypto_netlink_rcv(struct sk_buff *skb)
|
||||
{
|
||||
mutex_lock(&crypto_cfg_mutex);
|
||||
netlink_rcv_skb(skb, &crypto_user_rcv_msg);
|
||||
mutex_unlock(&crypto_cfg_mutex);
|
||||
}
|
||||
|
||||
static int __init crypto_user_init(void)
|
||||
{
|
||||
crypto_nlsk = netlink_kernel_create(&init_net, NETLINK_CRYPTO,
|
||||
0, crypto_netlink_rcv,
|
||||
NULL, THIS_MODULE);
|
||||
if (!crypto_nlsk)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit crypto_user_exit(void)
|
||||
{
|
||||
netlink_kernel_release(crypto_nlsk);
|
||||
}
|
||||
|
||||
module_init(crypto_user_init);
|
||||
module_exit(crypto_user_exit);
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Steffen Klassert <steffen.klassert@secunet.com>");
|
||||
MODULE_DESCRIPTION("Crypto userspace configuration API");
|
@ -86,6 +86,9 @@ struct crypto_alg *crypto_larval_lookup(const char *name, u32 type, u32 mask);
|
||||
void crypto_larval_error(const char *name, u32 type, u32 mask);
|
||||
void crypto_alg_tested(const char *name, int err);
|
||||
|
||||
void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list,
|
||||
struct crypto_alg *nalg);
|
||||
void crypto_remove_final(struct list_head *list);
|
||||
void crypto_shoot_alg(struct crypto_alg *alg);
|
||||
struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type,
|
||||
u32 mask);
|
||||
|
@ -24,6 +24,8 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/cryptouser.h>
|
||||
#include <net/netlink.h>
|
||||
|
||||
#include <crypto/compress.h>
|
||||
#include <crypto/internal/compress.h>
|
||||
@ -46,6 +48,21 @@ static int crypto_pcomp_init_tfm(struct crypto_tfm *tfm)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int crypto_pcomp_report(struct sk_buff *skb, struct crypto_alg *alg)
|
||||
{
|
||||
struct crypto_report_comp rpcomp;
|
||||
|
||||
snprintf(rpcomp.type, CRYPTO_MAX_ALG_NAME, "%s", "pcomp");
|
||||
|
||||
NLA_PUT(skb, CRYPTOCFGA_REPORT_COMPRESS,
|
||||
sizeof(struct crypto_report_comp), &rpcomp);
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static void crypto_pcomp_show(struct seq_file *m, struct crypto_alg *alg)
|
||||
__attribute__ ((unused));
|
||||
static void crypto_pcomp_show(struct seq_file *m, struct crypto_alg *alg)
|
||||
@ -60,6 +77,7 @@ static const struct crypto_type crypto_pcomp_type = {
|
||||
#ifdef CONFIG_PROC_FS
|
||||
.show = crypto_pcomp_show,
|
||||
#endif
|
||||
.report = crypto_pcomp_report,
|
||||
.maskclear = ~CRYPTO_ALG_TYPE_MASK,
|
||||
.maskset = CRYPTO_ALG_TYPE_MASK,
|
||||
.type = CRYPTO_ALG_TYPE_PCOMPRESS,
|
||||
|
20
crypto/rng.c
20
crypto/rng.c
@ -21,6 +21,8 @@
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/cryptouser.h>
|
||||
#include <net/netlink.h>
|
||||
|
||||
static DEFINE_MUTEX(crypto_default_rng_lock);
|
||||
struct crypto_rng *crypto_default_rng;
|
||||
@ -58,6 +60,23 @@ static int crypto_init_rng_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int crypto_rng_report(struct sk_buff *skb, struct crypto_alg *alg)
|
||||
{
|
||||
struct crypto_report_rng rrng;
|
||||
|
||||
snprintf(rrng.type, CRYPTO_MAX_ALG_NAME, "%s", "rng");
|
||||
|
||||
rrng.seedsize = alg->cra_rng.seedsize;
|
||||
|
||||
NLA_PUT(skb, CRYPTOCFGA_REPORT_RNG,
|
||||
sizeof(struct crypto_report_rng), &rrng);
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg)
|
||||
__attribute__ ((unused));
|
||||
static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg)
|
||||
@ -78,6 +97,7 @@ const struct crypto_type crypto_rng_type = {
|
||||
#ifdef CONFIG_PROC_FS
|
||||
.show = crypto_rng_show,
|
||||
#endif
|
||||
.report = crypto_rng_report,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(crypto_rng_type);
|
||||
|
||||
|
@ -36,7 +36,7 @@ static int sha1_init(struct shash_desc *desc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sha1_update(struct shash_desc *desc, const u8 *data,
|
||||
int crypto_sha1_update(struct shash_desc *desc, const u8 *data,
|
||||
unsigned int len)
|
||||
{
|
||||
struct sha1_state *sctx = shash_desc_ctx(desc);
|
||||
@ -71,6 +71,7 @@ static int sha1_update(struct shash_desc *desc, const u8 *data,
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(crypto_sha1_update);
|
||||
|
||||
|
||||
/* Add padding and return the message digest. */
|
||||
@ -87,10 +88,10 @@ static int sha1_final(struct shash_desc *desc, u8 *out)
|
||||
/* Pad out to 56 mod 64 */
|
||||
index = sctx->count & 0x3f;
|
||||
padlen = (index < 56) ? (56 - index) : ((64+56) - index);
|
||||
sha1_update(desc, padding, padlen);
|
||||
crypto_sha1_update(desc, padding, padlen);
|
||||
|
||||
/* Append length */
|
||||
sha1_update(desc, (const u8 *)&bits, sizeof(bits));
|
||||
crypto_sha1_update(desc, (const u8 *)&bits, sizeof(bits));
|
||||
|
||||
/* Store state in digest */
|
||||
for (i = 0; i < 5; i++)
|
||||
@ -121,7 +122,7 @@ static int sha1_import(struct shash_desc *desc, const void *in)
|
||||
static struct shash_alg alg = {
|
||||
.digestsize = SHA1_DIGEST_SIZE,
|
||||
.init = sha1_init,
|
||||
.update = sha1_update,
|
||||
.update = crypto_sha1_update,
|
||||
.final = sha1_final,
|
||||
.export = sha1_export,
|
||||
.import = sha1_import,
|
||||
|
@ -17,6 +17,8 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/cryptouser.h>
|
||||
#include <net/netlink.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
@ -522,6 +524,24 @@ static unsigned int crypto_shash_extsize(struct crypto_alg *alg)
|
||||
return alg->cra_ctxsize;
|
||||
}
|
||||
|
||||
static int crypto_shash_report(struct sk_buff *skb, struct crypto_alg *alg)
|
||||
{
|
||||
struct crypto_report_hash rhash;
|
||||
struct shash_alg *salg = __crypto_shash_alg(alg);
|
||||
|
||||
snprintf(rhash.type, CRYPTO_MAX_ALG_NAME, "%s", "shash");
|
||||
rhash.blocksize = alg->cra_blocksize;
|
||||
rhash.digestsize = salg->digestsize;
|
||||
|
||||
NLA_PUT(skb, CRYPTOCFGA_REPORT_HASH,
|
||||
sizeof(struct crypto_report_hash), &rhash);
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static void crypto_shash_show(struct seq_file *m, struct crypto_alg *alg)
|
||||
__attribute__ ((unused));
|
||||
static void crypto_shash_show(struct seq_file *m, struct crypto_alg *alg)
|
||||
@ -541,6 +561,7 @@ static const struct crypto_type crypto_shash_type = {
|
||||
#ifdef CONFIG_PROC_FS
|
||||
.show = crypto_shash_show,
|
||||
#endif
|
||||
.report = crypto_shash_report,
|
||||
.maskclear = ~CRYPTO_ALG_TYPE_MASK,
|
||||
.maskset = CRYPTO_ALG_TYPE_MASK,
|
||||
.type = CRYPTO_ALG_TYPE_SHASH,
|
||||
|
@ -782,11 +782,13 @@ static int do_test(int m)
|
||||
case 7:
|
||||
ret += tcrypt_test("ecb(blowfish)");
|
||||
ret += tcrypt_test("cbc(blowfish)");
|
||||
ret += tcrypt_test("ctr(blowfish)");
|
||||
break;
|
||||
|
||||
case 8:
|
||||
ret += tcrypt_test("ecb(twofish)");
|
||||
ret += tcrypt_test("cbc(twofish)");
|
||||
ret += tcrypt_test("ctr(twofish)");
|
||||
break;
|
||||
|
||||
case 9:
|
||||
@ -1039,6 +1041,10 @@ static int do_test(int m)
|
||||
speed_template_16_24_32);
|
||||
test_cipher_speed("cbc(twofish)", DECRYPT, sec, NULL, 0,
|
||||
speed_template_16_24_32);
|
||||
test_cipher_speed("ctr(twofish)", ENCRYPT, sec, NULL, 0,
|
||||
speed_template_16_24_32);
|
||||
test_cipher_speed("ctr(twofish)", DECRYPT, sec, NULL, 0,
|
||||
speed_template_16_24_32);
|
||||
break;
|
||||
|
||||
case 203:
|
||||
@ -1050,6 +1056,10 @@ static int do_test(int m)
|
||||
speed_template_8_32);
|
||||
test_cipher_speed("cbc(blowfish)", DECRYPT, sec, NULL, 0,
|
||||
speed_template_8_32);
|
||||
test_cipher_speed("ctr(blowfish)", ENCRYPT, sec, NULL, 0,
|
||||
speed_template_8_32);
|
||||
test_cipher_speed("ctr(blowfish)", DECRYPT, sec, NULL, 0,
|
||||
speed_template_8_32);
|
||||
break;
|
||||
|
||||
case 204:
|
||||
|
@ -1755,6 +1755,36 @@ static const struct alg_test_desc alg_test_descs[] = {
|
||||
}
|
||||
}
|
||||
}
|
||||
}, {
|
||||
.alg = "ctr(blowfish)",
|
||||
.test = alg_test_skcipher,
|
||||
.suite = {
|
||||
.cipher = {
|
||||
.enc = {
|
||||
.vecs = bf_ctr_enc_tv_template,
|
||||
.count = BF_CTR_ENC_TEST_VECTORS
|
||||
},
|
||||
.dec = {
|
||||
.vecs = bf_ctr_dec_tv_template,
|
||||
.count = BF_CTR_DEC_TEST_VECTORS
|
||||
}
|
||||
}
|
||||
}
|
||||
}, {
|
||||
.alg = "ctr(twofish)",
|
||||
.test = alg_test_skcipher,
|
||||
.suite = {
|
||||
.cipher = {
|
||||
.enc = {
|
||||
.vecs = tf_ctr_enc_tv_template,
|
||||
.count = TF_CTR_ENC_TEST_VECTORS
|
||||
},
|
||||
.dec = {
|
||||
.vecs = tf_ctr_dec_tv_template,
|
||||
.count = TF_CTR_DEC_TEST_VECTORS
|
||||
}
|
||||
}
|
||||
}
|
||||
}, {
|
||||
.alg = "cts(cbc(aes))",
|
||||
.test = alg_test_skcipher,
|
||||
|
398
crypto/testmgr.h
398
crypto/testmgr.h
@ -2391,10 +2391,12 @@ static struct cipher_testvec des3_ede_cbc_dec_tv_template[] = {
|
||||
/*
|
||||
* Blowfish test vectors.
|
||||
*/
|
||||
#define BF_ENC_TEST_VECTORS 6
|
||||
#define BF_DEC_TEST_VECTORS 6
|
||||
#define BF_CBC_ENC_TEST_VECTORS 1
|
||||
#define BF_CBC_DEC_TEST_VECTORS 1
|
||||
#define BF_ENC_TEST_VECTORS 7
|
||||
#define BF_DEC_TEST_VECTORS 7
|
||||
#define BF_CBC_ENC_TEST_VECTORS 2
|
||||
#define BF_CBC_DEC_TEST_VECTORS 2
|
||||
#define BF_CTR_ENC_TEST_VECTORS 2
|
||||
#define BF_CTR_DEC_TEST_VECTORS 2
|
||||
|
||||
static struct cipher_testvec bf_enc_tv_template[] = {
|
||||
{ /* DES test vectors from OpenSSL */
|
||||
@ -2448,6 +2450,24 @@ static struct cipher_testvec bf_enc_tv_template[] = {
|
||||
.ilen = 8,
|
||||
.result = "\xc0\x45\x04\x01\x2e\x4e\x1f\x53",
|
||||
.rlen = 8,
|
||||
}, { /* Generated with Crypto++ */
|
||||
.key = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
|
||||
"\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
|
||||
"\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
|
||||
"\x78\xBE\x9B\x78\x55\x32\x0F\x55",
|
||||
.klen = 32,
|
||||
.input = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
|
||||
"\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
|
||||
"\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
|
||||
"\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
|
||||
"\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
|
||||
.ilen = 40,
|
||||
.result = "\x96\x87\x3D\x0C\x7B\xFB\xBD\x1F"
|
||||
"\xE3\xC1\x99\x6D\x39\xD4\xC2\x7D"
|
||||
"\xD7\x87\xA1\xF2\xDF\x51\x71\x26"
|
||||
"\xC2\xF4\x6D\xFF\xF6\xCD\x6B\x40"
|
||||
"\xE1\xB3\xBF\xD4\x38\x2B\xC8\x3B",
|
||||
.rlen = 40,
|
||||
},
|
||||
};
|
||||
|
||||
@ -2503,6 +2523,24 @@ static struct cipher_testvec bf_dec_tv_template[] = {
|
||||
.ilen = 8,
|
||||
.result = "\xfe\xdc\xba\x98\x76\x54\x32\x10",
|
||||
.rlen = 8,
|
||||
}, { /* Generated with Crypto++ */
|
||||
.key = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
|
||||
"\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
|
||||
"\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
|
||||
"\x78\xBE\x9B\x78\x55\x32\x0F\x55",
|
||||
.klen = 32,
|
||||
.input = "\x96\x87\x3D\x0C\x7B\xFB\xBD\x1F"
|
||||
"\xE3\xC1\x99\x6D\x39\xD4\xC2\x7D"
|
||||
"\xD7\x87\xA1\xF2\xDF\x51\x71\x26"
|
||||
"\xC2\xF4\x6D\xFF\xF6\xCD\x6B\x40"
|
||||
"\xE1\xB3\xBF\xD4\x38\x2B\xC8\x3B",
|
||||
.ilen = 40,
|
||||
.result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
|
||||
"\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
|
||||
"\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
|
||||
"\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
|
||||
"\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
|
||||
.rlen = 40,
|
||||
},
|
||||
};
|
||||
|
||||
@ -2522,6 +2560,25 @@ static struct cipher_testvec bf_cbc_enc_tv_template[] = {
|
||||
"\x58\xde\xb9\xe7\x15\x46\x16\xd9"
|
||||
"\x59\xf1\x65\x2b\xd5\xff\x92\xcc",
|
||||
.rlen = 32,
|
||||
}, { /* Generated with Crypto++ */
|
||||
.key = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
|
||||
"\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
|
||||
"\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
|
||||
"\x78\xBE\x9B\x78\x55\x32\x0F\x55",
|
||||
.klen = 32,
|
||||
.iv = "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F",
|
||||
.input = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
|
||||
"\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
|
||||
"\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
|
||||
"\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
|
||||
"\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
|
||||
.ilen = 40,
|
||||
.result = "\xB4\xFE\xA5\xBB\x3D\x2C\x27\x06"
|
||||
"\x06\x2B\x3A\x92\xB2\xF5\x5E\x62"
|
||||
"\x84\xCD\xF7\x66\x7E\x41\x6C\x8E"
|
||||
"\x1B\xD9\x02\xB6\x48\xB0\x87\x25"
|
||||
"\x01\x9C\x93\x63\x51\x60\x82\xD2",
|
||||
.rlen = 40,
|
||||
},
|
||||
};
|
||||
|
||||
@ -2541,16 +2598,125 @@ static struct cipher_testvec bf_cbc_dec_tv_template[] = {
|
||||
"\x68\x65\x20\x74\x69\x6d\x65\x20"
|
||||
"\x66\x6f\x72\x20\x00\x00\x00\x00",
|
||||
.rlen = 32,
|
||||
}, { /* Generated with Crypto++ */
|
||||
.key = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
|
||||
"\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
|
||||
"\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
|
||||
"\x78\xBE\x9B\x78\x55\x32\x0F\x55",
|
||||
.klen = 32,
|
||||
.iv = "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F",
|
||||
.input = "\xB4\xFE\xA5\xBB\x3D\x2C\x27\x06"
|
||||
"\x06\x2B\x3A\x92\xB2\xF5\x5E\x62"
|
||||
"\x84\xCD\xF7\x66\x7E\x41\x6C\x8E"
|
||||
"\x1B\xD9\x02\xB6\x48\xB0\x87\x25"
|
||||
"\x01\x9C\x93\x63\x51\x60\x82\xD2",
|
||||
.ilen = 40,
|
||||
.result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
|
||||
"\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
|
||||
"\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
|
||||
"\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
|
||||
"\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
|
||||
.rlen = 40,
|
||||
},
|
||||
};
|
||||
|
||||
static struct cipher_testvec bf_ctr_enc_tv_template[] = {
|
||||
{ /* Generated with Crypto++ */
|
||||
.key = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
|
||||
"\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
|
||||
"\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
|
||||
"\x78\xBE\x9B\x78\x55\x32\x0F\x55",
|
||||
.klen = 32,
|
||||
.iv = "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F",
|
||||
.input = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
|
||||
"\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
|
||||
"\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
|
||||
"\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
|
||||
"\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
|
||||
.ilen = 40,
|
||||
.result = "\xC7\xA3\xDF\xB9\x05\xF4\x9E\x8D"
|
||||
"\x9E\xDF\x38\x18\x83\x07\xEF\xC1"
|
||||
"\x93\x3C\xAA\xAA\xFE\x06\x42\xCC"
|
||||
"\x0D\x70\x86\x5A\x44\xAD\x85\x17"
|
||||
"\xE4\x1F\x5E\xA5\x89\xAC\x32\xBC",
|
||||
.rlen = 40,
|
||||
}, { /* Generated with Crypto++ */
|
||||
.key = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
|
||||
"\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
|
||||
"\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
|
||||
"\x78\xBE\x9B\x78\x55\x32\x0F\x55",
|
||||
.klen = 32,
|
||||
.iv = "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F",
|
||||
.input = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
|
||||
"\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
|
||||
"\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
|
||||
"\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
|
||||
"\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
|
||||
"\x6D\x04\x9B",
|
||||
.ilen = 43,
|
||||
.result = "\xC7\xA3\xDF\xB9\x05\xF4\x9E\x8D"
|
||||
"\x9E\xDF\x38\x18\x83\x07\xEF\xC1"
|
||||
"\x93\x3C\xAA\xAA\xFE\x06\x42\xCC"
|
||||
"\x0D\x70\x86\x5A\x44\xAD\x85\x17"
|
||||
"\xE4\x1F\x5E\xA5\x89\xAC\x32\xBC"
|
||||
"\x3D\xA7\xE9",
|
||||
.rlen = 43,
|
||||
},
|
||||
};
|
||||
|
||||
static struct cipher_testvec bf_ctr_dec_tv_template[] = {
|
||||
{ /* Generated with Crypto++ */
|
||||
.key = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
|
||||
"\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
|
||||
"\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
|
||||
"\x78\xBE\x9B\x78\x55\x32\x0F\x55",
|
||||
.klen = 32,
|
||||
.iv = "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F",
|
||||
.input = "\xC7\xA3\xDF\xB9\x05\xF4\x9E\x8D"
|
||||
"\x9E\xDF\x38\x18\x83\x07\xEF\xC1"
|
||||
"\x93\x3C\xAA\xAA\xFE\x06\x42\xCC"
|
||||
"\x0D\x70\x86\x5A\x44\xAD\x85\x17"
|
||||
"\xE4\x1F\x5E\xA5\x89\xAC\x32\xBC",
|
||||
.ilen = 40,
|
||||
.result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
|
||||
"\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
|
||||
"\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
|
||||
"\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
|
||||
"\x1E\x92\x29\xC0\x34\xCB\x62\xF9",
|
||||
.rlen = 40,
|
||||
}, { /* Generated with Crypto++ */
|
||||
.key = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
|
||||
"\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
|
||||
"\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
|
||||
"\x78\xBE\x9B\x78\x55\x32\x0F\x55",
|
||||
.klen = 32,
|
||||
.iv = "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F",
|
||||
.input = "\xC7\xA3\xDF\xB9\x05\xF4\x9E\x8D"
|
||||
"\x9E\xDF\x38\x18\x83\x07\xEF\xC1"
|
||||
"\x93\x3C\xAA\xAA\xFE\x06\x42\xCC"
|
||||
"\x0D\x70\x86\x5A\x44\xAD\x85\x17"
|
||||
"\xE4\x1F\x5E\xA5\x89\xAC\x32\xBC"
|
||||
"\x3D\xA7\xE9",
|
||||
.ilen = 43,
|
||||
.result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
|
||||
"\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
|
||||
"\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
|
||||
"\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
|
||||
"\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
|
||||
"\x6D\x04\x9B",
|
||||
.rlen = 43,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* Twofish test vectors.
|
||||
*/
|
||||
#define TF_ENC_TEST_VECTORS 3
|
||||
#define TF_DEC_TEST_VECTORS 3
|
||||
#define TF_CBC_ENC_TEST_VECTORS 4
|
||||
#define TF_CBC_DEC_TEST_VECTORS 4
|
||||
#define TF_ENC_TEST_VECTORS 4
|
||||
#define TF_DEC_TEST_VECTORS 4
|
||||
#define TF_CBC_ENC_TEST_VECTORS 5
|
||||
#define TF_CBC_DEC_TEST_VECTORS 5
|
||||
#define TF_CTR_ENC_TEST_VECTORS 2
|
||||
#define TF_CTR_DEC_TEST_VECTORS 2
|
||||
|
||||
static struct cipher_testvec tf_enc_tv_template[] = {
|
||||
{
|
||||
@ -2582,6 +2748,30 @@ static struct cipher_testvec tf_enc_tv_template[] = {
|
||||
.result = "\x37\x52\x7b\xe0\x05\x23\x34\xb8"
|
||||
"\x9f\x0c\xfc\xca\xe8\x7c\xfa\x20",
|
||||
.rlen = 16,
|
||||
}, { /* Generated with Crypto++ */
|
||||
.key = "\x3F\x85\x62\x3F\x1C\xF9\xD6\x1C"
|
||||
"\xF9\xD6\xB3\x90\x6D\x4A\x90\x6D"
|
||||
"\x4A\x27\x04\xE1\x27\x04\xE1\xBE"
|
||||
"\x9B\x78\xBE\x9B\x78\x55\x32\x0F",
|
||||
.klen = 32,
|
||||
.input = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
|
||||
"\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
|
||||
"\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
|
||||
"\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
|
||||
"\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
|
||||
"\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
|
||||
"\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
|
||||
"\x51\xE8\x5C\xF3\x8A\x21\x95\x2C",
|
||||
.ilen = 64,
|
||||
.result = "\x88\xCB\x1E\xC2\xAF\x8A\x97\xFF"
|
||||
"\xF6\x90\x46\x9C\x4A\x0F\x08\xDC"
|
||||
"\xDE\xAB\xAD\xFA\xFC\xA8\xC2\x3D"
|
||||
"\xE0\xE4\x8B\x3F\xD5\xA3\xF7\x14"
|
||||
"\x34\x9E\xB6\x08\xB2\xDD\xA8\xF5"
|
||||
"\xDF\xFA\xC7\xE8\x09\x50\x76\x08"
|
||||
"\xA2\xB6\x6A\x59\xC0\x2B\x6D\x05"
|
||||
"\x89\xF6\x82\xF0\xD3\xDB\x06\x02",
|
||||
.rlen = 64,
|
||||
},
|
||||
};
|
||||
|
||||
@ -2615,6 +2805,30 @@ static struct cipher_testvec tf_dec_tv_template[] = {
|
||||
.ilen = 16,
|
||||
.result = zeroed_string,
|
||||
.rlen = 16,
|
||||
}, { /* Generated with Crypto++ */
|
||||
.key = "\x3F\x85\x62\x3F\x1C\xF9\xD6\x1C"
|
||||
"\xF9\xD6\xB3\x90\x6D\x4A\x90\x6D"
|
||||
"\x4A\x27\x04\xE1\x27\x04\xE1\xBE"
|
||||
"\x9B\x78\xBE\x9B\x78\x55\x32\x0F",
|
||||
.klen = 32,
|
||||
.input = "\x88\xCB\x1E\xC2\xAF\x8A\x97\xFF"
|
||||
"\xF6\x90\x46\x9C\x4A\x0F\x08\xDC"
|
||||
"\xDE\xAB\xAD\xFA\xFC\xA8\xC2\x3D"
|
||||
"\xE0\xE4\x8B\x3F\xD5\xA3\xF7\x14"
|
||||
"\x34\x9E\xB6\x08\xB2\xDD\xA8\xF5"
|
||||
"\xDF\xFA\xC7\xE8\x09\x50\x76\x08"
|
||||
"\xA2\xB6\x6A\x59\xC0\x2B\x6D\x05"
|
||||
"\x89\xF6\x82\xF0\xD3\xDB\x06\x02",
|
||||
.ilen = 64,
|
||||
.result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
|
||||
"\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
|
||||
"\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
|
||||
"\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
|
||||
"\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
|
||||
"\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
|
||||
"\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
|
||||
"\x51\xE8\x5C\xF3\x8A\x21\x95\x2C",
|
||||
.rlen = 64,
|
||||
},
|
||||
};
|
||||
|
||||
@ -2661,6 +2875,32 @@ static struct cipher_testvec tf_cbc_enc_tv_template[] = {
|
||||
"\x05\xef\x8c\x61\xa8\x11\x58\x26"
|
||||
"\x34\xba\x5c\xb7\x10\x6a\xa6\x41",
|
||||
.rlen = 48,
|
||||
}, { /* Generated with Crypto++ */
|
||||
.key = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
|
||||
"\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
|
||||
"\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
|
||||
"\x78\xBE\x9B\x78\x55\x32\x0F\x55",
|
||||
.klen = 32,
|
||||
.iv = "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F"
|
||||
"\xC4\x29\x8E\xF3\x35\x9A\xFF\x64",
|
||||
.input = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
|
||||
"\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
|
||||
"\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
|
||||
"\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
|
||||
"\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
|
||||
"\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
|
||||
"\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
|
||||
"\x51\xE8\x5C\xF3\x8A\x21\x95\x2C",
|
||||
.ilen = 64,
|
||||
.result = "\xC8\xFF\xF2\x53\xA6\x27\x09\xD1"
|
||||
"\x33\x38\xC2\xC0\x0C\x14\x7E\xB5"
|
||||
"\x26\x1B\x05\x0C\x05\x12\x3F\xC0"
|
||||
"\xF9\x1C\x02\x28\x40\x96\x6F\xD0"
|
||||
"\x3D\x32\xDF\xDA\x56\x00\x6E\xEE"
|
||||
"\x5B\x2A\x72\x9D\xC2\x4D\x19\xBC"
|
||||
"\x8C\x53\xFA\x87\x6F\xDD\x81\xA3"
|
||||
"\xB1\xD3\x44\x65\xDF\xE7\x63\x38",
|
||||
.rlen = 64,
|
||||
},
|
||||
};
|
||||
|
||||
@ -2707,6 +2947,148 @@ static struct cipher_testvec tf_cbc_dec_tv_template[] = {
|
||||
.ilen = 48,
|
||||
.result = zeroed_string,
|
||||
.rlen = 48,
|
||||
}, { /* Generated with Crypto++ */
|
||||
.key = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
|
||||
"\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
|
||||
"\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
|
||||
"\x78\xBE\x9B\x78\x55\x32\x0F\x55",
|
||||
.klen = 32,
|
||||
.iv = "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F"
|
||||
"\xC4\x29\x8E\xF3\x35\x9A\xFF\x64",
|
||||
.input = "\xC8\xFF\xF2\x53\xA6\x27\x09\xD1"
|
||||
"\x33\x38\xC2\xC0\x0C\x14\x7E\xB5"
|
||||
"\x26\x1B\x05\x0C\x05\x12\x3F\xC0"
|
||||
"\xF9\x1C\x02\x28\x40\x96\x6F\xD0"
|
||||
"\x3D\x32\xDF\xDA\x56\x00\x6E\xEE"
|
||||
"\x5B\x2A\x72\x9D\xC2\x4D\x19\xBC"
|
||||
"\x8C\x53\xFA\x87\x6F\xDD\x81\xA3"
|
||||
"\xB1\xD3\x44\x65\xDF\xE7\x63\x38",
|
||||
.ilen = 64,
|
||||
.result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
|
||||
"\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
|
||||
"\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
|
||||
"\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
|
||||
"\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
|
||||
"\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
|
||||
"\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
|
||||
"\x51\xE8\x5C\xF3\x8A\x21\x95\x2C",
|
||||
.rlen = 64,
|
||||
},
|
||||
};
|
||||
|
||||
static struct cipher_testvec tf_ctr_enc_tv_template[] = {
|
||||
{ /* Generated with Crypto++ */
|
||||
.key = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
|
||||
"\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
|
||||
"\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
|
||||
"\x78\xBE\x9B\x78\x55\x32\x0F\x55",
|
||||
.klen = 32,
|
||||
.iv = "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F"
|
||||
"\xC4\x29\x8E\xF3\x35\x9A\xFF\x64",
|
||||
.input = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
|
||||
"\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
|
||||
"\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
|
||||
"\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
|
||||
"\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
|
||||
"\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
|
||||
"\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
|
||||
"\x51\xE8\x5C\xF3\x8A\x21\x95\x2C",
|
||||
.ilen = 64,
|
||||
.result = "\xDF\xDD\x69\xFA\xB0\x2E\xFD\xFE"
|
||||
"\x70\x9E\xC5\x4B\xC9\xD4\xA1\x30"
|
||||
"\x26\x9B\x89\xA1\xEE\x43\xE0\x52"
|
||||
"\x55\x17\x4E\xC7\x0E\x33\x1F\xF1"
|
||||
"\x9F\x8D\x40\x9F\x24\xFD\x92\xA0"
|
||||
"\xBC\x8F\x35\xDD\x67\x38\xD8\xAA"
|
||||
"\xCF\xF8\x48\xCA\xFB\xE4\x5C\x60"
|
||||
"\x01\x41\x21\x12\x38\xAB\x52\x4F",
|
||||
.rlen = 64,
|
||||
}, { /* Generated with Crypto++ */
|
||||
.key = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
|
||||
"\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
|
||||
"\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
|
||||
"\x78\xBE\x9B\x78\x55\x32\x0F\x55",
|
||||
.klen = 32,
|
||||
.iv = "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F"
|
||||
"\xC4\x29\x8E\xF3\x35\x9A\xFF\x64",
|
||||
.input = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
|
||||
"\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
|
||||
"\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
|
||||
"\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
|
||||
"\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
|
||||
"\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
|
||||
"\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
|
||||
"\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
|
||||
"\xC3\x37\xCE",
|
||||
.ilen = 67,
|
||||
.result = "\xDF\xDD\x69\xFA\xB0\x2E\xFD\xFE"
|
||||
"\x70\x9E\xC5\x4B\xC9\xD4\xA1\x30"
|
||||
"\x26\x9B\x89\xA1\xEE\x43\xE0\x52"
|
||||
"\x55\x17\x4E\xC7\x0E\x33\x1F\xF1"
|
||||
"\x9F\x8D\x40\x9F\x24\xFD\x92\xA0"
|
||||
"\xBC\x8F\x35\xDD\x67\x38\xD8\xAA"
|
||||
"\xCF\xF8\x48\xCA\xFB\xE4\x5C\x60"
|
||||
"\x01\x41\x21\x12\x38\xAB\x52\x4F"
|
||||
"\xA8\x57\x20",
|
||||
.rlen = 67,
|
||||
},
|
||||
};
|
||||
|
||||
static struct cipher_testvec tf_ctr_dec_tv_template[] = {
|
||||
{ /* Generated with Crypto++ */
|
||||
.key = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
|
||||
"\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
|
||||
"\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
|
||||
"\x78\xBE\x9B\x78\x55\x32\x0F\x55",
|
||||
.klen = 32,
|
||||
.iv = "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F"
|
||||
"\xC4\x29\x8E\xF3\x35\x9A\xFF\x64",
|
||||
.input = "\xDF\xDD\x69\xFA\xB0\x2E\xFD\xFE"
|
||||
"\x70\x9E\xC5\x4B\xC9\xD4\xA1\x30"
|
||||
"\x26\x9B\x89\xA1\xEE\x43\xE0\x52"
|
||||
"\x55\x17\x4E\xC7\x0E\x33\x1F\xF1"
|
||||
"\x9F\x8D\x40\x9F\x24\xFD\x92\xA0"
|
||||
"\xBC\x8F\x35\xDD\x67\x38\xD8\xAA"
|
||||
"\xCF\xF8\x48\xCA\xFB\xE4\x5C\x60"
|
||||
"\x01\x41\x21\x12\x38\xAB\x52\x4F",
|
||||
.ilen = 64,
|
||||
.result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
|
||||
"\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
|
||||
"\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
|
||||
"\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
|
||||
"\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
|
||||
"\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
|
||||
"\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
|
||||
"\x51\xE8\x5C\xF3\x8A\x21\x95\x2C",
|
||||
.rlen = 64,
|
||||
}, { /* Generated with Crypto++ */
|
||||
.key = "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
|
||||
"\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
|
||||
"\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
|
||||
"\x78\xBE\x9B\x78\x55\x32\x0F\x55",
|
||||
.klen = 32,
|
||||
.iv = "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F"
|
||||
"\xC4\x29\x8E\xF3\x35\x9A\xFF\x64",
|
||||
.input = "\xDF\xDD\x69\xFA\xB0\x2E\xFD\xFE"
|
||||
"\x70\x9E\xC5\x4B\xC9\xD4\xA1\x30"
|
||||
"\x26\x9B\x89\xA1\xEE\x43\xE0\x52"
|
||||
"\x55\x17\x4E\xC7\x0E\x33\x1F\xF1"
|
||||
"\x9F\x8D\x40\x9F\x24\xFD\x92\xA0"
|
||||
"\xBC\x8F\x35\xDD\x67\x38\xD8\xAA"
|
||||
"\xCF\xF8\x48\xCA\xFB\xE4\x5C\x60"
|
||||
"\x01\x41\x21\x12\x38\xAB\x52\x4F"
|
||||
"\xA8\x57\x20",
|
||||
.ilen = 67,
|
||||
.result = "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
|
||||
"\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
|
||||
"\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
|
||||
"\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
|
||||
"\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
|
||||
"\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
|
||||
"\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
|
||||
"\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
|
||||
"\xC3\x37\xCE",
|
||||
.rlen = 67,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -762,11 +762,17 @@ static const u64 C7[256] = {
|
||||
0x86228644a411c286ULL,
|
||||
};
|
||||
|
||||
static const u64 rc[WHIRLPOOL_ROUNDS + 1] = {
|
||||
0x0000000000000000ULL, 0x1823c6e887b8014fULL, 0x36a6d2f5796f9152ULL,
|
||||
0x60bc9b8ea30c7b35ULL, 0x1de0d7c22e4bfe57ULL, 0x157737e59ff04adaULL,
|
||||
0x58c9290ab1a06b85ULL, 0xbd5d10f4cb3e0567ULL, 0xe427418ba77d95d8ULL,
|
||||
0xfbee7c66dd17479eULL, 0xca2dbf07ad5a8333ULL,
|
||||
static const u64 rc[WHIRLPOOL_ROUNDS] = {
|
||||
0x1823c6e887b8014fULL,
|
||||
0x36a6d2f5796f9152ULL,
|
||||
0x60bc9b8ea30c7b35ULL,
|
||||
0x1de0d7c22e4bfe57ULL,
|
||||
0x157737e59ff04adaULL,
|
||||
0x58c9290ab1a06b85ULL,
|
||||
0xbd5d10f4cb3e0567ULL,
|
||||
0xe427418ba77d95d8ULL,
|
||||
0xfbee7c66dd17479eULL,
|
||||
0xca2dbf07ad5a8333ULL,
|
||||
};
|
||||
|
||||
/**
|
||||
@ -793,7 +799,7 @@ static void wp512_process_buffer(struct wp512_ctx *wctx) {
|
||||
state[6] = block[6] ^ (K[6] = wctx->hash[6]);
|
||||
state[7] = block[7] ^ (K[7] = wctx->hash[7]);
|
||||
|
||||
for (r = 1; r <= WHIRLPOOL_ROUNDS; r++) {
|
||||
for (r = 0; r < WHIRLPOOL_ROUNDS; r++) {
|
||||
|
||||
L[0] = C0[(int)(K[0] >> 56) ] ^
|
||||
C1[(int)(K[7] >> 48) & 0xff] ^
|
||||
|
@ -200,6 +200,7 @@ config CRYPTO_DEV_HIFN_795X
|
||||
select CRYPTO_BLKCIPHER
|
||||
select HW_RANDOM if CRYPTO_DEV_HIFN_795X_RNG
|
||||
depends on PCI
|
||||
depends on !ARCH_DMA_ADDR_T_64BIT
|
||||
help
|
||||
This option allows you to have support for HIFN 795x crypto adapters.
|
||||
|
||||
@ -266,7 +267,7 @@ config CRYPTO_DEV_OMAP_AES
|
||||
|
||||
config CRYPTO_DEV_PICOXCELL
|
||||
tristate "Support for picoXcell IPSEC and Layer2 crypto engines"
|
||||
depends on ARCH_PICOXCELL
|
||||
depends on ARCH_PICOXCELL && HAVE_CLK
|
||||
select CRYPTO_AES
|
||||
select CRYPTO_AUTHENC
|
||||
select CRYPTO_ALGAPI
|
||||
|
@ -2744,10 +2744,8 @@ static int __init hifn_init(void)
|
||||
unsigned int freq;
|
||||
int err;
|
||||
|
||||
if (sizeof(dma_addr_t) > 4) {
|
||||
printk(KERN_INFO "HIFN supports only 32-bit addresses.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
/* HIFN supports only 32-bit addresses */
|
||||
BUILD_BUG_ON(sizeof(dma_addr_t) != 4);
|
||||
|
||||
if (strncmp(hifn_pll_ref, "ext", 3) &&
|
||||
strncmp(hifn_pll_ref, "pci", 3)) {
|
||||
|
@ -1006,9 +1006,9 @@ static int n2_do_ecb(struct ablkcipher_request *req, bool encrypt)
|
||||
|
||||
spin_unlock_irqrestore(&qp->lock, flags);
|
||||
|
||||
out:
|
||||
put_cpu();
|
||||
|
||||
out:
|
||||
n2_chunk_complete(req, NULL);
|
||||
return err;
|
||||
}
|
||||
@ -1096,9 +1096,9 @@ static int n2_do_chaining(struct ablkcipher_request *req, bool encrypt)
|
||||
|
||||
spin_unlock_irqrestore(&qp->lock, flags);
|
||||
|
||||
out:
|
||||
put_cpu();
|
||||
|
||||
out:
|
||||
n2_chunk_complete(req, err ? NULL : final_iv_addr);
|
||||
return err;
|
||||
}
|
||||
|
@ -508,10 +508,8 @@ static int __init padlock_init(void)
|
||||
int ret;
|
||||
struct cpuinfo_x86 *c = &cpu_data(0);
|
||||
|
||||
if (!cpu_has_xcrypt) {
|
||||
printk(KERN_NOTICE PFX "VIA PadLock not detected.\n");
|
||||
if (!cpu_has_xcrypt)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!cpu_has_xcrypt_enabled) {
|
||||
printk(KERN_NOTICE PFX "VIA PadLock detected, but not enabled. Hmm, strange...\n");
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
@ -1241,8 +1242,8 @@ static void spacc_spacc_complete(unsigned long data)
|
||||
spin_unlock_irqrestore(&engine->hw_lock, flags);
|
||||
|
||||
list_for_each_entry_safe(req, tmp, &completed, list) {
|
||||
req->complete(req);
|
||||
list_del(&req->list);
|
||||
req->complete(req);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1657,10 +1658,33 @@ static struct spacc_alg l2_engine_algs[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static int __devinit spacc_probe(struct platform_device *pdev,
|
||||
unsigned max_ctxs, size_t cipher_pg_sz,
|
||||
size_t hash_pg_sz, size_t fifo_sz,
|
||||
struct spacc_alg *algs, size_t num_algs)
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id spacc_of_id_table[] = {
|
||||
{ .compatible = "picochip,spacc-ipsec" },
|
||||
{ .compatible = "picochip,spacc-l2" },
|
||||
{}
|
||||
};
|
||||
#else /* CONFIG_OF */
|
||||
#define spacc_of_id_table NULL
|
||||
#endif /* CONFIG_OF */
|
||||
|
||||
static bool spacc_is_compatible(struct platform_device *pdev,
|
||||
const char *spacc_type)
|
||||
{
|
||||
const struct platform_device_id *platid = platform_get_device_id(pdev);
|
||||
|
||||
if (platid && !strcmp(platid->name, spacc_type))
|
||||
return true;
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
if (of_device_is_compatible(pdev->dev.of_node, spacc_type))
|
||||
return true;
|
||||
#endif /* CONFIG_OF */
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int __devinit spacc_probe(struct platform_device *pdev)
|
||||
{
|
||||
int i, err, ret = -EINVAL;
|
||||
struct resource *mem, *irq;
|
||||
@ -1669,13 +1693,25 @@ static int __devinit spacc_probe(struct platform_device *pdev,
|
||||
if (!engine)
|
||||
return -ENOMEM;
|
||||
|
||||
engine->max_ctxs = max_ctxs;
|
||||
engine->cipher_pg_sz = cipher_pg_sz;
|
||||
engine->hash_pg_sz = hash_pg_sz;
|
||||
engine->fifo_sz = fifo_sz;
|
||||
engine->algs = algs;
|
||||
engine->num_algs = num_algs;
|
||||
engine->name = dev_name(&pdev->dev);
|
||||
if (spacc_is_compatible(pdev, "picochip,spacc-ipsec")) {
|
||||
engine->max_ctxs = SPACC_CRYPTO_IPSEC_MAX_CTXS;
|
||||
engine->cipher_pg_sz = SPACC_CRYPTO_IPSEC_CIPHER_PG_SZ;
|
||||
engine->hash_pg_sz = SPACC_CRYPTO_IPSEC_HASH_PG_SZ;
|
||||
engine->fifo_sz = SPACC_CRYPTO_IPSEC_FIFO_SZ;
|
||||
engine->algs = ipsec_engine_algs;
|
||||
engine->num_algs = ARRAY_SIZE(ipsec_engine_algs);
|
||||
} else if (spacc_is_compatible(pdev, "picochip,spacc-l2")) {
|
||||
engine->max_ctxs = SPACC_CRYPTO_L2_MAX_CTXS;
|
||||
engine->cipher_pg_sz = SPACC_CRYPTO_L2_CIPHER_PG_SZ;
|
||||
engine->hash_pg_sz = SPACC_CRYPTO_L2_HASH_PG_SZ;
|
||||
engine->fifo_sz = SPACC_CRYPTO_L2_FIFO_SZ;
|
||||
engine->algs = l2_engine_algs;
|
||||
engine->num_algs = ARRAY_SIZE(l2_engine_algs);
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
engine->name = dev_name(&pdev->dev);
|
||||
|
||||
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||
@ -1711,7 +1747,7 @@ static int __devinit spacc_probe(struct platform_device *pdev,
|
||||
|
||||
spin_lock_init(&engine->hw_lock);
|
||||
|
||||
engine->clk = clk_get(&pdev->dev, NULL);
|
||||
engine->clk = clk_get(&pdev->dev, "ref");
|
||||
if (IS_ERR(engine->clk)) {
|
||||
dev_info(&pdev->dev, "clk unavailable\n");
|
||||
device_remove_file(&pdev->dev, &dev_attr_stat_irq_thresh);
|
||||
@ -1800,72 +1836,33 @@ static int __devexit spacc_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit ipsec_probe(struct platform_device *pdev)
|
||||
{
|
||||
return spacc_probe(pdev, SPACC_CRYPTO_IPSEC_MAX_CTXS,
|
||||
SPACC_CRYPTO_IPSEC_CIPHER_PG_SZ,
|
||||
SPACC_CRYPTO_IPSEC_HASH_PG_SZ,
|
||||
SPACC_CRYPTO_IPSEC_FIFO_SZ, ipsec_engine_algs,
|
||||
ARRAY_SIZE(ipsec_engine_algs));
|
||||
}
|
||||
|
||||
static struct platform_driver ipsec_driver = {
|
||||
.probe = ipsec_probe,
|
||||
.remove = __devexit_p(spacc_remove),
|
||||
.driver = {
|
||||
.name = "picoxcell-ipsec",
|
||||
#ifdef CONFIG_PM
|
||||
.pm = &spacc_pm_ops,
|
||||
#endif /* CONFIG_PM */
|
||||
},
|
||||
static const struct platform_device_id spacc_id_table[] = {
|
||||
{ "picochip,spacc-ipsec", },
|
||||
{ "picochip,spacc-l2", },
|
||||
};
|
||||
|
||||
static int __devinit l2_probe(struct platform_device *pdev)
|
||||
{
|
||||
return spacc_probe(pdev, SPACC_CRYPTO_L2_MAX_CTXS,
|
||||
SPACC_CRYPTO_L2_CIPHER_PG_SZ,
|
||||
SPACC_CRYPTO_L2_HASH_PG_SZ, SPACC_CRYPTO_L2_FIFO_SZ,
|
||||
l2_engine_algs, ARRAY_SIZE(l2_engine_algs));
|
||||
}
|
||||
|
||||
static struct platform_driver l2_driver = {
|
||||
.probe = l2_probe,
|
||||
static struct platform_driver spacc_driver = {
|
||||
.probe = spacc_probe,
|
||||
.remove = __devexit_p(spacc_remove),
|
||||
.driver = {
|
||||
.name = "picoxcell-l2",
|
||||
.name = "picochip,spacc",
|
||||
#ifdef CONFIG_PM
|
||||
.pm = &spacc_pm_ops,
|
||||
#endif /* CONFIG_PM */
|
||||
.of_match_table = spacc_of_id_table,
|
||||
},
|
||||
.id_table = spacc_id_table,
|
||||
};
|
||||
|
||||
static int __init spacc_init(void)
|
||||
{
|
||||
int ret = platform_driver_register(&ipsec_driver);
|
||||
if (ret) {
|
||||
pr_err("failed to register ipsec spacc driver");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = platform_driver_register(&l2_driver);
|
||||
if (ret) {
|
||||
pr_err("failed to register l2 spacc driver");
|
||||
goto l2_failed;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
l2_failed:
|
||||
platform_driver_unregister(&ipsec_driver);
|
||||
out:
|
||||
return ret;
|
||||
return platform_driver_register(&spacc_driver);
|
||||
}
|
||||
module_init(spacc_init);
|
||||
|
||||
static void __exit spacc_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&ipsec_driver);
|
||||
platform_driver_unregister(&l2_driver);
|
||||
platform_driver_unregister(&spacc_driver);
|
||||
}
|
||||
module_exit(spacc_exit);
|
||||
|
||||
|
@ -416,7 +416,7 @@ static void talitos_done(unsigned long data)
|
||||
/*
|
||||
* locate current (offending) descriptor
|
||||
*/
|
||||
static struct talitos_desc *current_desc(struct device *dev, int ch)
|
||||
static u32 current_desc_hdr(struct device *dev, int ch)
|
||||
{
|
||||
struct talitos_private *priv = dev_get_drvdata(dev);
|
||||
int tail = priv->chan[ch].tail;
|
||||
@ -428,23 +428,25 @@ static struct talitos_desc *current_desc(struct device *dev, int ch)
|
||||
tail = (tail + 1) & (priv->fifo_len - 1);
|
||||
if (tail == priv->chan[ch].tail) {
|
||||
dev_err(dev, "couldn't locate current descriptor\n");
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return priv->chan[ch].fifo[tail].desc;
|
||||
return priv->chan[ch].fifo[tail].desc->hdr;
|
||||
}
|
||||
|
||||
/*
|
||||
* user diagnostics; report root cause of error based on execution unit status
|
||||
*/
|
||||
static void report_eu_error(struct device *dev, int ch,
|
||||
struct talitos_desc *desc)
|
||||
static void report_eu_error(struct device *dev, int ch, u32 desc_hdr)
|
||||
{
|
||||
struct talitos_private *priv = dev_get_drvdata(dev);
|
||||
int i;
|
||||
|
||||
switch (desc->hdr & DESC_HDR_SEL0_MASK) {
|
||||
if (!desc_hdr)
|
||||
desc_hdr = in_be32(priv->reg + TALITOS_DESCBUF(ch));
|
||||
|
||||
switch (desc_hdr & DESC_HDR_SEL0_MASK) {
|
||||
case DESC_HDR_SEL0_AFEU:
|
||||
dev_err(dev, "AFEUISR 0x%08x_%08x\n",
|
||||
in_be32(priv->reg + TALITOS_AFEUISR),
|
||||
@ -488,7 +490,7 @@ static void report_eu_error(struct device *dev, int ch,
|
||||
break;
|
||||
}
|
||||
|
||||
switch (desc->hdr & DESC_HDR_SEL1_MASK) {
|
||||
switch (desc_hdr & DESC_HDR_SEL1_MASK) {
|
||||
case DESC_HDR_SEL1_MDEUA:
|
||||
case DESC_HDR_SEL1_MDEUB:
|
||||
dev_err(dev, "MDEUISR 0x%08x_%08x\n",
|
||||
@ -550,7 +552,7 @@ static void talitos_error(unsigned long data, u32 isr, u32 isr_lo)
|
||||
if (v_lo & TALITOS_CCPSR_LO_IEU)
|
||||
dev_err(dev, "invalid execution unit error\n");
|
||||
if (v_lo & TALITOS_CCPSR_LO_EU)
|
||||
report_eu_error(dev, ch, current_desc(dev, ch));
|
||||
report_eu_error(dev, ch, current_desc_hdr(dev, ch));
|
||||
if (v_lo & TALITOS_CCPSR_LO_GB)
|
||||
dev_err(dev, "gather boundary error\n");
|
||||
if (v_lo & TALITOS_CCPSR_LO_GRL)
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/skbuff.h>
|
||||
|
||||
struct module;
|
||||
struct rtattr;
|
||||
@ -26,6 +27,7 @@ struct crypto_type {
|
||||
int (*init)(struct crypto_tfm *tfm, u32 type, u32 mask);
|
||||
int (*init_tfm)(struct crypto_tfm *tfm);
|
||||
void (*show)(struct seq_file *m, struct crypto_alg *alg);
|
||||
int (*report)(struct sk_buff *skb, struct crypto_alg *alg);
|
||||
struct crypto_alg *(*lookup)(const char *name, u32 type, u32 mask);
|
||||
|
||||
unsigned int type;
|
||||
|
23
include/crypto/blowfish.h
Normal file
23
include/crypto/blowfish.h
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Common values for blowfish algorithms
|
||||
*/
|
||||
|
||||
#ifndef _CRYPTO_BLOWFISH_H
|
||||
#define _CRYPTO_BLOWFISH_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/crypto.h>
|
||||
|
||||
#define BF_BLOCK_SIZE 8
|
||||
#define BF_MIN_KEY_SIZE 4
|
||||
#define BF_MAX_KEY_SIZE 56
|
||||
|
||||
struct bf_ctx {
|
||||
u32 p[18];
|
||||
u32 s[1024];
|
||||
};
|
||||
|
||||
int blowfish_setkey(struct crypto_tfm *tfm, const u8 *key,
|
||||
unsigned int key_len);
|
||||
|
||||
#endif
|
@ -82,4 +82,9 @@ struct sha512_state {
|
||||
u8 buf[SHA512_BLOCK_SIZE];
|
||||
};
|
||||
|
||||
struct shash_desc;
|
||||
|
||||
extern int crypto_sha1_update(struct shash_desc *desc, const u8 *data,
|
||||
unsigned int len);
|
||||
|
||||
#endif
|
||||
|
@ -71,6 +71,11 @@
|
||||
|
||||
#define CRYPTO_ALG_TESTED 0x00000400
|
||||
|
||||
/*
|
||||
* Set if the algorithm is an instance that is build from templates.
|
||||
*/
|
||||
#define CRYPTO_ALG_INSTANCE 0x00000800
|
||||
|
||||
/*
|
||||
* Transform masks and values (for crt_flags).
|
||||
*/
|
||||
|
102
include/linux/cryptouser.h
Normal file
102
include/linux/cryptouser.h
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Crypto user configuration API.
|
||||
*
|
||||
* Copyright (C) 2011 secunet Security Networks AG
|
||||
* Copyright (C) 2011 Steffen Klassert <steffen.klassert@secunet.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope 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, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
/* Netlink configuration messages. */
|
||||
enum {
|
||||
CRYPTO_MSG_BASE = 0x10,
|
||||
CRYPTO_MSG_NEWALG = 0x10,
|
||||
CRYPTO_MSG_DELALG,
|
||||
CRYPTO_MSG_UPDATEALG,
|
||||
CRYPTO_MSG_GETALG,
|
||||
__CRYPTO_MSG_MAX
|
||||
};
|
||||
#define CRYPTO_MSG_MAX (__CRYPTO_MSG_MAX - 1)
|
||||
#define CRYPTO_NR_MSGTYPES (CRYPTO_MSG_MAX + 1 - CRYPTO_MSG_BASE)
|
||||
|
||||
#define CRYPTO_MAX_NAME CRYPTO_MAX_ALG_NAME
|
||||
|
||||
/* Netlink message attributes. */
|
||||
enum crypto_attr_type_t {
|
||||
CRYPTOCFGA_UNSPEC,
|
||||
CRYPTOCFGA_PRIORITY_VAL, /* __u32 */
|
||||
CRYPTOCFGA_REPORT_LARVAL, /* struct crypto_report_larval */
|
||||
CRYPTOCFGA_REPORT_HASH, /* struct crypto_report_hash */
|
||||
CRYPTOCFGA_REPORT_BLKCIPHER, /* struct crypto_report_blkcipher */
|
||||
CRYPTOCFGA_REPORT_AEAD, /* struct crypto_report_aead */
|
||||
CRYPTOCFGA_REPORT_COMPRESS, /* struct crypto_report_comp */
|
||||
CRYPTOCFGA_REPORT_RNG, /* struct crypto_report_rng */
|
||||
CRYPTOCFGA_REPORT_CIPHER, /* struct crypto_report_cipher */
|
||||
__CRYPTOCFGA_MAX
|
||||
|
||||
#define CRYPTOCFGA_MAX (__CRYPTOCFGA_MAX - 1)
|
||||
};
|
||||
|
||||
struct crypto_user_alg {
|
||||
char cru_name[CRYPTO_MAX_ALG_NAME];
|
||||
char cru_driver_name[CRYPTO_MAX_ALG_NAME];
|
||||
char cru_module_name[CRYPTO_MAX_ALG_NAME];
|
||||
__u32 cru_type;
|
||||
__u32 cru_mask;
|
||||
__u32 cru_refcnt;
|
||||
__u32 cru_flags;
|
||||
};
|
||||
|
||||
struct crypto_report_larval {
|
||||
char type[CRYPTO_MAX_NAME];
|
||||
};
|
||||
|
||||
struct crypto_report_hash {
|
||||
char type[CRYPTO_MAX_NAME];
|
||||
unsigned int blocksize;
|
||||
unsigned int digestsize;
|
||||
};
|
||||
|
||||
struct crypto_report_cipher {
|
||||
char type[CRYPTO_MAX_ALG_NAME];
|
||||
unsigned int blocksize;
|
||||
unsigned int min_keysize;
|
||||
unsigned int max_keysize;
|
||||
};
|
||||
|
||||
struct crypto_report_blkcipher {
|
||||
char type[CRYPTO_MAX_NAME];
|
||||
char geniv[CRYPTO_MAX_NAME];
|
||||
unsigned int blocksize;
|
||||
unsigned int min_keysize;
|
||||
unsigned int max_keysize;
|
||||
unsigned int ivsize;
|
||||
};
|
||||
|
||||
struct crypto_report_aead {
|
||||
char type[CRYPTO_MAX_NAME];
|
||||
char geniv[CRYPTO_MAX_NAME];
|
||||
unsigned int blocksize;
|
||||
unsigned int maxauthsize;
|
||||
unsigned int ivsize;
|
||||
};
|
||||
|
||||
struct crypto_report_comp {
|
||||
char type[CRYPTO_MAX_NAME];
|
||||
};
|
||||
|
||||
struct crypto_report_rng {
|
||||
char type[CRYPTO_MAX_NAME];
|
||||
unsigned int seedsize;
|
||||
};
|
@ -25,6 +25,7 @@
|
||||
#define NETLINK_SCSITRANSPORT 18 /* SCSI Transports */
|
||||
#define NETLINK_ECRYPTFS 19
|
||||
#define NETLINK_RDMA 20
|
||||
#define NETLINK_CRYPTO 21 /* Crypto layer */
|
||||
|
||||
#define MAX_LINKS 32
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user