You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6: (64 commits) [BLOCK] dm-crypt: trivial comment improvements [CRYPTO] api: Deprecate crypto_digest_* and crypto_alg_available [CRYPTO] padlock: Convert padlock-sha to use crypto_hash [CRYPTO] users: Use crypto_comp and crypto_has_* [CRYPTO] api: Add crypto_comp and crypto_has_* [CRYPTO] users: Use crypto_hash interface instead of crypto_digest [SCSI] iscsi: Use crypto_hash interface instead of crypto_digest [CRYPTO] digest: Remove old HMAC implementation [CRYPTO] doc: Update documentation for hash and me [SCTP]: Use HMAC template and hash interface [IPSEC]: Use HMAC template and hash interface [CRYPTO] tcrypt: Use HMAC template and hash interface [CRYPTO] hmac: Add crypto template implementation [CRYPTO] digest: Added user API for new hash type [CRYPTO] api: Mark parts of cipher interface as deprecated [PATCH] scatterlist: Add const to sg_set_buf/sg_init_one pointer argument [CRYPTO] drivers: Remove obsolete block cipher operations [CRYPTO] users: Use block ciphers where applicable [SUNRPC] GSS: Use block ciphers where applicable [IPSEC] ESP: Use block ciphers where applicable ...
This commit is contained in:
@@ -19,15 +19,14 @@ At the lowest level are algorithms, which register dynamically with the
|
||||
API.
|
||||
|
||||
'Transforms' are user-instantiated objects, which maintain state, handle all
|
||||
of the implementation logic (e.g. manipulating page vectors), provide an
|
||||
abstraction to the underlying algorithms, and handle common logical
|
||||
operations (e.g. cipher modes, HMAC for digests). However, at the user
|
||||
of the implementation logic (e.g. manipulating page vectors) and provide an
|
||||
abstraction to the underlying algorithms. However, at the user
|
||||
level they are very simple.
|
||||
|
||||
Conceptually, the API layering looks like this:
|
||||
|
||||
[transform api] (user interface)
|
||||
[transform ops] (per-type logic glue e.g. cipher.c, digest.c)
|
||||
[transform ops] (per-type logic glue e.g. cipher.c, compress.c)
|
||||
[algorithm api] (for registering algorithms)
|
||||
|
||||
The idea is to make the user interface and algorithm registration API
|
||||
@@ -44,22 +43,27 @@ under development.
|
||||
Here's an example of how to use the API:
|
||||
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/scatterlist.h>
|
||||
|
||||
struct scatterlist sg[2];
|
||||
char result[128];
|
||||
struct crypto_tfm *tfm;
|
||||
struct crypto_hash *tfm;
|
||||
struct hash_desc desc;
|
||||
|
||||
tfm = crypto_alloc_tfm("md5", 0);
|
||||
if (tfm == NULL)
|
||||
tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC);
|
||||
if (IS_ERR(tfm))
|
||||
fail();
|
||||
|
||||
/* ... set up the scatterlists ... */
|
||||
|
||||
desc.tfm = tfm;
|
||||
desc.flags = 0;
|
||||
|
||||
crypto_digest_init(tfm);
|
||||
crypto_digest_update(tfm, &sg, 2);
|
||||
crypto_digest_final(tfm, result);
|
||||
if (crypto_hash_digest(&desc, &sg, 2, result))
|
||||
fail();
|
||||
|
||||
crypto_free_tfm(tfm);
|
||||
crypto_free_hash(tfm);
|
||||
|
||||
|
||||
Many real examples are available in the regression test module (tcrypt.c).
|
||||
@@ -126,7 +130,7 @@ might already be working on.
|
||||
BUGS
|
||||
|
||||
Send bug reports to:
|
||||
James Morris <jmorris@redhat.com>
|
||||
Herbert Xu <herbert@gondor.apana.org.au>
|
||||
Cc: David S. Miller <davem@redhat.com>
|
||||
|
||||
|
||||
@@ -134,13 +138,14 @@ FURTHER INFORMATION
|
||||
|
||||
For further patches and various updates, including the current TODO
|
||||
list, see:
|
||||
http://samba.org/~jamesm/crypto/
|
||||
http://gondor.apana.org.au/~herbert/crypto/
|
||||
|
||||
|
||||
AUTHORS
|
||||
|
||||
James Morris
|
||||
David S. Miller
|
||||
Herbert Xu
|
||||
|
||||
|
||||
CREDITS
|
||||
@@ -238,8 +243,11 @@ Anubis algorithm contributors:
|
||||
Tiger algorithm contributors:
|
||||
Aaron Grothe
|
||||
|
||||
VIA PadLock contributors:
|
||||
Michal Ludvig
|
||||
|
||||
Generic scatterwalk code by Adam J. Richter <adam@yggdrasil.com>
|
||||
|
||||
Please send any credits updates or corrections to:
|
||||
James Morris <jmorris@redhat.com>
|
||||
Herbert Xu <herbert@gondor.apana.org.au>
|
||||
|
||||
|
||||
@@ -5,5 +5,8 @@
|
||||
#
|
||||
|
||||
obj-$(CONFIG_CRYPTO_AES_586) += aes-i586.o
|
||||
obj-$(CONFIG_CRYPTO_TWOFISH_586) += twofish-i586.o
|
||||
|
||||
aes-i586-y := aes-i586-asm.o aes.o
|
||||
twofish-i586-y := twofish-i586-asm.o twofish.o
|
||||
|
||||
|
||||
@@ -379,12 +379,13 @@ static void gen_tabs(void)
|
||||
}
|
||||
|
||||
static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
|
||||
unsigned int key_len, u32 *flags)
|
||||
unsigned int key_len)
|
||||
{
|
||||
int i;
|
||||
u32 ss[8];
|
||||
struct aes_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
const __le32 *key = (const __le32 *)in_key;
|
||||
u32 *flags = &tfm->crt_flags;
|
||||
|
||||
/* encryption schedule */
|
||||
|
||||
|
||||
@@ -0,0 +1,335 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2006 by Joachim Fritschi, <jfritschi@freenet.de> *
|
||||
* *
|
||||
* 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-i586-asm.S"
|
||||
.text
|
||||
|
||||
#include <asm/asm-offsets.h>
|
||||
|
||||
/* return adress at 0 */
|
||||
|
||||
#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 a_offset 0
|
||||
#define b_offset 4
|
||||
#define c_offset 8
|
||||
#define d_offset 12
|
||||
|
||||
/* Structure of the crypto context struct*/
|
||||
|
||||
#define s0 0 /* S0 Array 256 Words each */
|
||||
#define s1 1024 /* S1 Array */
|
||||
#define s2 2048 /* S2 Array */
|
||||
#define s3 3072 /* S3 Array */
|
||||
#define w 4096 /* 8 whitening keys (word) */
|
||||
#define k 4128 /* key 1-32 ( word ) */
|
||||
|
||||
/* define a few register aliases to allow macro substitution */
|
||||
|
||||
#define R0D %eax
|
||||
#define R0B %al
|
||||
#define R0H %ah
|
||||
|
||||
#define R1D %ebx
|
||||
#define R1B %bl
|
||||
#define R1H %bh
|
||||
|
||||
#define R2D %ecx
|
||||
#define R2B %cl
|
||||
#define R2H %ch
|
||||
|
||||
#define R3D %edx
|
||||
#define R3B %dl
|
||||
#define R3H %dh
|
||||
|
||||
|
||||
/* performs input whitening */
|
||||
#define input_whitening(src,context,offset)\
|
||||
xor w+offset(context), src;
|
||||
|
||||
/* performs input whitening */
|
||||
#define output_whitening(src,context,offset)\
|
||||
xor w+16+offset(context), src;
|
||||
|
||||
/*
|
||||
* a input register containing a (rotated 16)
|
||||
* b input register containing b
|
||||
* c input register containing c
|
||||
* d input register containing d (already rol $1)
|
||||
* operations on a and b are interleaved to increase performance
|
||||
*/
|
||||
#define encrypt_round(a,b,c,d,round)\
|
||||
push d ## D;\
|
||||
movzx b ## B, %edi;\
|
||||
mov s1(%ebp,%edi,4),d ## D;\
|
||||
movzx a ## B, %edi;\
|
||||
mov s2(%ebp,%edi,4),%esi;\
|
||||
movzx b ## H, %edi;\
|
||||
ror $16, b ## D;\
|
||||
xor s2(%ebp,%edi,4),d ## D;\
|
||||
movzx a ## H, %edi;\
|
||||
ror $16, a ## D;\
|
||||
xor s3(%ebp,%edi,4),%esi;\
|
||||
movzx b ## B, %edi;\
|
||||
xor s3(%ebp,%edi,4),d ## D;\
|
||||
movzx a ## B, %edi;\
|
||||
xor (%ebp,%edi,4), %esi;\
|
||||
movzx b ## H, %edi;\
|
||||
ror $15, b ## D;\
|
||||
xor (%ebp,%edi,4), d ## D;\
|
||||
movzx a ## H, %edi;\
|
||||
xor s1(%ebp,%edi,4),%esi;\
|
||||
pop %edi;\
|
||||
add d ## D, %esi;\
|
||||
add %esi, d ## D;\
|
||||
add k+round(%ebp), %esi;\
|
||||
xor %esi, c ## D;\
|
||||
rol $15, c ## D;\
|
||||
add k+4+round(%ebp),d ## D;\
|
||||
xor %edi, d ## D;
|
||||
|
||||
/*
|
||||
* a input register containing a (rotated 16)
|
||||
* b input register containing b
|
||||
* c input register containing c
|
||||
* d input register containing d (already rol $1)
|
||||
* operations on a and b are interleaved to increase performance
|
||||
* last round has different rotations for the output preparation
|
||||
*/
|
||||
#define encrypt_last_round(a,b,c,d,round)\
|
||||
push d ## D;\
|
||||
movzx b ## B, %edi;\
|
||||
mov s1(%ebp,%edi,4),d ## D;\
|
||||
movzx a ## B, %edi;\
|
||||
mov s2(%ebp,%edi,4),%esi;\
|
||||
movzx b ## H, %edi;\
|
||||
ror $16, b ## D;\
|
||||
xor s2(%ebp,%edi,4),d ## D;\
|
||||
movzx a ## H, %edi;\
|
||||
ror $16, a ## D;\
|
||||
xor s3(%ebp,%edi,4),%esi;\
|
||||
movzx b ## B, %edi;\
|
||||
xor s3(%ebp,%edi,4),d ## D;\
|
||||
movzx a ## B, %edi;\
|
||||
xor (%ebp,%edi,4), %esi;\
|
||||
movzx b ## H, %edi;\
|
||||
ror $16, b ## D;\
|
||||
xor (%ebp,%edi,4), d ## D;\
|
||||
movzx a ## H, %edi;\
|
||||
xor s1(%ebp,%edi,4),%esi;\
|
||||
pop %edi;\
|
||||
add d ## D, %esi;\
|
||||
add %esi, d ## D;\
|
||||
add k+round(%ebp), %esi;\
|
||||
xor %esi, c ## D;\
|
||||
ror $1, c ## D;\
|
||||
add k+4+round(%ebp),d ## D;\
|
||||
xor %edi, d ## D;
|
||||
|
||||
/*
|
||||
* a input register containing a
|
||||
* b input register containing b (rotated 16)
|
||||
* c input register containing c
|
||||
* d input register containing d (already rol $1)
|
||||
* operations on a and b are interleaved to increase performance
|
||||
*/
|
||||
#define decrypt_round(a,b,c,d,round)\
|
||||
push c ## D;\
|
||||
movzx a ## B, %edi;\
|
||||
mov (%ebp,%edi,4), c ## D;\
|
||||
movzx b ## B, %edi;\
|
||||
mov s3(%ebp,%edi,4),%esi;\
|
||||
movzx a ## H, %edi;\
|
||||
ror $16, a ## D;\
|
||||
xor s1(%ebp,%edi,4),c ## D;\
|
||||
movzx b ## H, %edi;\
|
||||
ror $16, b ## D;\
|
||||
xor (%ebp,%edi,4), %esi;\
|
||||
movzx a ## B, %edi;\
|
||||
xor s2(%ebp,%edi,4),c ## D;\
|
||||
movzx b ## B, %edi;\
|
||||
xor s1(%ebp,%edi,4),%esi;\
|
||||
movzx a ## H, %edi;\
|
||||
ror $15, a ## D;\
|
||||
xor s3(%ebp,%edi,4),c ## D;\
|
||||
movzx b ## H, %edi;\
|
||||
xor s2(%ebp,%edi,4),%esi;\
|
||||
pop %edi;\
|
||||
add %esi, c ## D;\
|
||||
add c ## D, %esi;\
|
||||
add k+round(%ebp), c ## D;\
|
||||
xor %edi, c ## D;\
|
||||
add k+4+round(%ebp),%esi;\
|
||||
xor %esi, d ## D;\
|
||||
rol $15, d ## D;
|
||||
|
||||
/*
|
||||
* a input register containing a
|
||||
* b input register containing b (rotated 16)
|
||||
* c input register containing c
|
||||
* d input register containing d (already rol $1)
|
||||
* operations on a and b are interleaved to increase performance
|
||||
* last round has different rotations for the output preparation
|
||||
*/
|
||||
#define decrypt_last_round(a,b,c,d,round)\
|
||||
push c ## D;\
|
||||
movzx a ## B, %edi;\
|
||||
mov (%ebp,%edi,4), c ## D;\
|
||||
movzx b ## B, %edi;\
|
||||
mov s3(%ebp,%edi,4),%esi;\
|
||||
movzx a ## H, %edi;\
|
||||
ror $16, a ## D;\
|
||||
xor s1(%ebp,%edi,4),c ## D;\
|
||||
movzx b ## H, %edi;\
|
||||
ror $16, b ## D;\
|
||||
xor (%ebp,%edi,4), %esi;\
|
||||
movzx a ## B, %edi;\
|
||||
xor s2(%ebp,%edi,4),c ## D;\
|
||||
movzx b ## B, %edi;\
|
||||
xor s1(%ebp,%edi,4),%esi;\
|
||||
movzx a ## H, %edi;\
|
||||
ror $16, a ## D;\
|
||||
xor s3(%ebp,%edi,4),c ## D;\
|
||||
movzx b ## H, %edi;\
|
||||
xor s2(%ebp,%edi,4),%esi;\
|
||||
pop %edi;\
|
||||
add %esi, c ## D;\
|
||||
add c ## D, %esi;\
|
||||
add k+round(%ebp), c ## D;\
|
||||
xor %edi, c ## D;\
|
||||
add k+4+round(%ebp),%esi;\
|
||||
xor %esi, d ## D;\
|
||||
ror $1, d ## D;
|
||||
|
||||
.align 4
|
||||
.global twofish_enc_blk
|
||||
.global twofish_dec_blk
|
||||
|
||||
twofish_enc_blk:
|
||||
push %ebp /* save registers according to calling convention*/
|
||||
push %ebx
|
||||
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 adress */
|
||||
mov in_blk+16(%esp),%edi /* input adress in edi */
|
||||
|
||||
mov (%edi), %eax
|
||||
mov b_offset(%edi), %ebx
|
||||
mov c_offset(%edi), %ecx
|
||||
mov d_offset(%edi), %edx
|
||||
input_whitening(%eax,%ebp,a_offset)
|
||||
ror $16, %eax
|
||||
input_whitening(%ebx,%ebp,b_offset)
|
||||
input_whitening(%ecx,%ebp,c_offset)
|
||||
input_whitening(%edx,%ebp,d_offset)
|
||||
rol $1, %edx
|
||||
|
||||
encrypt_round(R0,R1,R2,R3,0);
|
||||
encrypt_round(R2,R3,R0,R1,8);
|
||||
encrypt_round(R0,R1,R2,R3,2*8);
|
||||
encrypt_round(R2,R3,R0,R1,3*8);
|
||||
encrypt_round(R0,R1,R2,R3,4*8);
|
||||
encrypt_round(R2,R3,R0,R1,5*8);
|
||||
encrypt_round(R0,R1,R2,R3,6*8);
|
||||
encrypt_round(R2,R3,R0,R1,7*8);
|
||||
encrypt_round(R0,R1,R2,R3,8*8);
|
||||
encrypt_round(R2,R3,R0,R1,9*8);
|
||||
encrypt_round(R0,R1,R2,R3,10*8);
|
||||
encrypt_round(R2,R3,R0,R1,11*8);
|
||||
encrypt_round(R0,R1,R2,R3,12*8);
|
||||
encrypt_round(R2,R3,R0,R1,13*8);
|
||||
encrypt_round(R0,R1,R2,R3,14*8);
|
||||
encrypt_last_round(R2,R3,R0,R1,15*8);
|
||||
|
||||
output_whitening(%eax,%ebp,c_offset)
|
||||
output_whitening(%ebx,%ebp,d_offset)
|
||||
output_whitening(%ecx,%ebp,a_offset)
|
||||
output_whitening(%edx,%ebp,b_offset)
|
||||
mov out_blk+16(%esp),%edi;
|
||||
mov %eax, c_offset(%edi)
|
||||
mov %ebx, d_offset(%edi)
|
||||
mov %ecx, (%edi)
|
||||
mov %edx, b_offset(%edi)
|
||||
|
||||
pop %edi
|
||||
pop %esi
|
||||
pop %ebx
|
||||
pop %ebp
|
||||
mov $1, %eax
|
||||
ret
|
||||
|
||||
twofish_dec_blk:
|
||||
push %ebp /* save registers according to calling convention*/
|
||||
push %ebx
|
||||
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 adress */
|
||||
mov in_blk+16(%esp),%edi /* input adress in edi */
|
||||
|
||||
mov (%edi), %eax
|
||||
mov b_offset(%edi), %ebx
|
||||
mov c_offset(%edi), %ecx
|
||||
mov d_offset(%edi), %edx
|
||||
output_whitening(%eax,%ebp,a_offset)
|
||||
output_whitening(%ebx,%ebp,b_offset)
|
||||
ror $16, %ebx
|
||||
output_whitening(%ecx,%ebp,c_offset)
|
||||
output_whitening(%edx,%ebp,d_offset)
|
||||
rol $1, %ecx
|
||||
|
||||
decrypt_round(R0,R1,R2,R3,15*8);
|
||||
decrypt_round(R2,R3,R0,R1,14*8);
|
||||
decrypt_round(R0,R1,R2,R3,13*8);
|
||||
decrypt_round(R2,R3,R0,R1,12*8);
|
||||
decrypt_round(R0,R1,R2,R3,11*8);
|
||||
decrypt_round(R2,R3,R0,R1,10*8);
|
||||
decrypt_round(R0,R1,R2,R3,9*8);
|
||||
decrypt_round(R2,R3,R0,R1,8*8);
|
||||
decrypt_round(R0,R1,R2,R3,7*8);
|
||||
decrypt_round(R2,R3,R0,R1,6*8);
|
||||
decrypt_round(R0,R1,R2,R3,5*8);
|
||||
decrypt_round(R2,R3,R0,R1,4*8);
|
||||
decrypt_round(R0,R1,R2,R3,3*8);
|
||||
decrypt_round(R2,R3,R0,R1,2*8);
|
||||
decrypt_round(R0,R1,R2,R3,1*8);
|
||||
decrypt_last_round(R2,R3,R0,R1,0);
|
||||
|
||||
input_whitening(%eax,%ebp,c_offset)
|
||||
input_whitening(%ebx,%ebp,d_offset)
|
||||
input_whitening(%ecx,%ebp,a_offset)
|
||||
input_whitening(%edx,%ebp,b_offset)
|
||||
mov out_blk+16(%esp),%edi;
|
||||
mov %eax, c_offset(%edi)
|
||||
mov %ebx, d_offset(%edi)
|
||||
mov %ecx, (%edi)
|
||||
mov %edx, b_offset(%edi)
|
||||
|
||||
pop %edi
|
||||
pop %esi
|
||||
pop %ebx
|
||||
pop %ebp
|
||||
mov $1, %eax
|
||||
ret
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Glue Code for optimized 586 assembler version of TWOFISH
|
||||
*
|
||||
* Originally Twofish for GPG
|
||||
* By Matthew Skala <mskala@ansuz.sooke.bc.ca>, July 26, 1998
|
||||
* 256-bit key length added March 20, 1999
|
||||
* Some modifications to reduce the text size by Werner Koch, April, 1998
|
||||
* Ported to the kerneli patch by Marc Mutz <Marc@Mutz.com>
|
||||
* Ported to CryptoAPI by Colin Slater <hoho@tacomeat.net>
|
||||
*
|
||||
* The original author has disclaimed all copyright interest in this
|
||||
* code and thus put it in the public domain. The subsequent authors
|
||||
* have put this under the GNU General Public License.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* This code is a "clean room" implementation, written from the paper
|
||||
* _Twofish: A 128-Bit Block Cipher_ by Bruce Schneier, John Kelsey,
|
||||
* Doug Whiting, David Wagner, Chris Hall, and Niels Ferguson, available
|
||||
* through http://www.counterpane.com/twofish.html
|
||||
*
|
||||
* For background information on multiplication in finite fields, used for
|
||||
* the matrix operations in the key schedule, see the book _Contemporary
|
||||
* Abstract Algebra_ by Joseph A. Gallian, especially chapter 22 in the
|
||||
* Third Edition.
|
||||
*/
|
||||
|
||||
#include <crypto/twofish.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/init.h>
|
||||
#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);
|
||||
|
||||
static void twofish_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
|
||||
{
|
||||
twofish_enc_blk(tfm, dst, src);
|
||||
}
|
||||
|
||||
static void twofish_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
|
||||
{
|
||||
twofish_dec_blk(tfm, dst, src);
|
||||
}
|
||||
|
||||
static struct crypto_alg alg = {
|
||||
.cra_name = "twofish",
|
||||
.cra_driver_name = "twofish-i586",
|
||||
.cra_priority = 200,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
|
||||
.cra_blocksize = TF_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct twofish_ctx),
|
||||
.cra_alignmask = 3,
|
||||
.cra_module = THIS_MODULE,
|
||||
.cra_list = LIST_HEAD_INIT(alg.cra_list),
|
||||
.cra_u = {
|
||||
.cipher = {
|
||||
.cia_min_keysize = TF_MIN_KEY_SIZE,
|
||||
.cia_max_keysize = TF_MAX_KEY_SIZE,
|
||||
.cia_setkey = twofish_setkey,
|
||||
.cia_encrypt = twofish_encrypt,
|
||||
.cia_decrypt = twofish_decrypt
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static int __init init(void)
|
||||
{
|
||||
return crypto_register_alg(&alg);
|
||||
}
|
||||
|
||||
static void __exit fini(void)
|
||||
{
|
||||
crypto_unregister_alg(&alg);
|
||||
}
|
||||
|
||||
module_init(init);
|
||||
module_exit(fini);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION ("Twofish Cipher Algorithm, i586 asm optimized");
|
||||
MODULE_ALIAS("twofish");
|
||||
+219
-116
@@ -16,9 +16,9 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <crypto/algapi.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/crypto.h>
|
||||
#include "crypt_s390.h"
|
||||
|
||||
#define AES_MIN_KEY_SIZE 16
|
||||
@@ -34,13 +34,16 @@ int has_aes_256 = 0;
|
||||
struct s390_aes_ctx {
|
||||
u8 iv[AES_BLOCK_SIZE];
|
||||
u8 key[AES_MAX_KEY_SIZE];
|
||||
long enc;
|
||||
long dec;
|
||||
int key_len;
|
||||
};
|
||||
|
||||
static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
|
||||
unsigned int key_len, u32 *flags)
|
||||
unsigned int key_len)
|
||||
{
|
||||
struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
|
||||
u32 *flags = &tfm->crt_flags;
|
||||
|
||||
switch (key_len) {
|
||||
case 16:
|
||||
@@ -110,117 +113,11 @@ static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int aes_encrypt_ecb(const struct cipher_desc *desc, u8 *out,
|
||||
const u8 *in, unsigned int nbytes)
|
||||
{
|
||||
struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm);
|
||||
int ret;
|
||||
|
||||
/* only use complete blocks */
|
||||
nbytes &= ~(AES_BLOCK_SIZE - 1);
|
||||
|
||||
switch (sctx->key_len) {
|
||||
case 16:
|
||||
ret = crypt_s390_km(KM_AES_128_ENCRYPT, &sctx->key, out, in, nbytes);
|
||||
BUG_ON((ret < 0) || (ret != nbytes));
|
||||
break;
|
||||
case 24:
|
||||
ret = crypt_s390_km(KM_AES_192_ENCRYPT, &sctx->key, out, in, nbytes);
|
||||
BUG_ON((ret < 0) || (ret != nbytes));
|
||||
break;
|
||||
case 32:
|
||||
ret = crypt_s390_km(KM_AES_256_ENCRYPT, &sctx->key, out, in, nbytes);
|
||||
BUG_ON((ret < 0) || (ret != nbytes));
|
||||
break;
|
||||
}
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
static unsigned int aes_decrypt_ecb(const struct cipher_desc *desc, u8 *out,
|
||||
const u8 *in, unsigned int nbytes)
|
||||
{
|
||||
struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm);
|
||||
int ret;
|
||||
|
||||
/* only use complete blocks */
|
||||
nbytes &= ~(AES_BLOCK_SIZE - 1);
|
||||
|
||||
switch (sctx->key_len) {
|
||||
case 16:
|
||||
ret = crypt_s390_km(KM_AES_128_DECRYPT, &sctx->key, out, in, nbytes);
|
||||
BUG_ON((ret < 0) || (ret != nbytes));
|
||||
break;
|
||||
case 24:
|
||||
ret = crypt_s390_km(KM_AES_192_DECRYPT, &sctx->key, out, in, nbytes);
|
||||
BUG_ON((ret < 0) || (ret != nbytes));
|
||||
break;
|
||||
case 32:
|
||||
ret = crypt_s390_km(KM_AES_256_DECRYPT, &sctx->key, out, in, nbytes);
|
||||
BUG_ON((ret < 0) || (ret != nbytes));
|
||||
break;
|
||||
}
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
static unsigned int aes_encrypt_cbc(const struct cipher_desc *desc, u8 *out,
|
||||
const u8 *in, unsigned int nbytes)
|
||||
{
|
||||
struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm);
|
||||
int ret;
|
||||
|
||||
/* only use complete blocks */
|
||||
nbytes &= ~(AES_BLOCK_SIZE - 1);
|
||||
|
||||
memcpy(&sctx->iv, desc->info, AES_BLOCK_SIZE);
|
||||
switch (sctx->key_len) {
|
||||
case 16:
|
||||
ret = crypt_s390_kmc(KMC_AES_128_ENCRYPT, &sctx->iv, out, in, nbytes);
|
||||
BUG_ON((ret < 0) || (ret != nbytes));
|
||||
break;
|
||||
case 24:
|
||||
ret = crypt_s390_kmc(KMC_AES_192_ENCRYPT, &sctx->iv, out, in, nbytes);
|
||||
BUG_ON((ret < 0) || (ret != nbytes));
|
||||
break;
|
||||
case 32:
|
||||
ret = crypt_s390_kmc(KMC_AES_256_ENCRYPT, &sctx->iv, out, in, nbytes);
|
||||
BUG_ON((ret < 0) || (ret != nbytes));
|
||||
break;
|
||||
}
|
||||
memcpy(desc->info, &sctx->iv, AES_BLOCK_SIZE);
|
||||
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
static unsigned int aes_decrypt_cbc(const struct cipher_desc *desc, u8 *out,
|
||||
const u8 *in, unsigned int nbytes)
|
||||
{
|
||||
struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm);
|
||||
int ret;
|
||||
|
||||
/* only use complete blocks */
|
||||
nbytes &= ~(AES_BLOCK_SIZE - 1);
|
||||
|
||||
memcpy(&sctx->iv, desc->info, AES_BLOCK_SIZE);
|
||||
switch (sctx->key_len) {
|
||||
case 16:
|
||||
ret = crypt_s390_kmc(KMC_AES_128_DECRYPT, &sctx->iv, out, in, nbytes);
|
||||
BUG_ON((ret < 0) || (ret != nbytes));
|
||||
break;
|
||||
case 24:
|
||||
ret = crypt_s390_kmc(KMC_AES_192_DECRYPT, &sctx->iv, out, in, nbytes);
|
||||
BUG_ON((ret < 0) || (ret != nbytes));
|
||||
break;
|
||||
case 32:
|
||||
ret = crypt_s390_kmc(KMC_AES_256_DECRYPT, &sctx->iv, out, in, nbytes);
|
||||
BUG_ON((ret < 0) || (ret != nbytes));
|
||||
break;
|
||||
}
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
|
||||
static struct crypto_alg aes_alg = {
|
||||
.cra_name = "aes",
|
||||
.cra_driver_name = "aes-s390",
|
||||
.cra_priority = CRYPT_S390_PRIORITY,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
|
||||
.cra_blocksize = AES_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct s390_aes_ctx),
|
||||
@@ -233,10 +130,189 @@ static struct crypto_alg aes_alg = {
|
||||
.cia_setkey = aes_set_key,
|
||||
.cia_encrypt = aes_encrypt,
|
||||
.cia_decrypt = aes_decrypt,
|
||||
.cia_encrypt_ecb = aes_encrypt_ecb,
|
||||
.cia_decrypt_ecb = aes_decrypt_ecb,
|
||||
.cia_encrypt_cbc = aes_encrypt_cbc,
|
||||
.cia_decrypt_cbc = aes_decrypt_cbc,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static int ecb_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
|
||||
unsigned int key_len)
|
||||
{
|
||||
struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
|
||||
|
||||
switch (key_len) {
|
||||
case 16:
|
||||
sctx->enc = KM_AES_128_ENCRYPT;
|
||||
sctx->dec = KM_AES_128_DECRYPT;
|
||||
break;
|
||||
case 24:
|
||||
sctx->enc = KM_AES_192_ENCRYPT;
|
||||
sctx->dec = KM_AES_192_DECRYPT;
|
||||
break;
|
||||
case 32:
|
||||
sctx->enc = KM_AES_256_ENCRYPT;
|
||||
sctx->dec = KM_AES_256_DECRYPT;
|
||||
break;
|
||||
}
|
||||
|
||||
return aes_set_key(tfm, in_key, key_len);
|
||||
}
|
||||
|
||||
static int ecb_aes_crypt(struct blkcipher_desc *desc, long func, void *param,
|
||||
struct blkcipher_walk *walk)
|
||||
{
|
||||
int ret = blkcipher_walk_virt(desc, walk);
|
||||
unsigned int nbytes;
|
||||
|
||||
while ((nbytes = walk->nbytes)) {
|
||||
/* only use complete blocks */
|
||||
unsigned int n = nbytes & ~(AES_BLOCK_SIZE - 1);
|
||||
u8 *out = walk->dst.virt.addr;
|
||||
u8 *in = walk->src.virt.addr;
|
||||
|
||||
ret = crypt_s390_km(func, param, out, in, n);
|
||||
BUG_ON((ret < 0) || (ret != n));
|
||||
|
||||
nbytes &= AES_BLOCK_SIZE - 1;
|
||||
ret = blkcipher_walk_done(desc, walk, nbytes);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ecb_aes_encrypt(struct blkcipher_desc *desc,
|
||||
struct scatterlist *dst, struct scatterlist *src,
|
||||
unsigned int nbytes)
|
||||
{
|
||||
struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
|
||||
struct blkcipher_walk walk;
|
||||
|
||||
blkcipher_walk_init(&walk, dst, src, nbytes);
|
||||
return ecb_aes_crypt(desc, sctx->enc, sctx->key, &walk);
|
||||
}
|
||||
|
||||
static int ecb_aes_decrypt(struct blkcipher_desc *desc,
|
||||
struct scatterlist *dst, struct scatterlist *src,
|
||||
unsigned int nbytes)
|
||||
{
|
||||
struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
|
||||
struct blkcipher_walk walk;
|
||||
|
||||
blkcipher_walk_init(&walk, dst, src, nbytes);
|
||||
return ecb_aes_crypt(desc, sctx->dec, sctx->key, &walk);
|
||||
}
|
||||
|
||||
static struct crypto_alg ecb_aes_alg = {
|
||||
.cra_name = "ecb(aes)",
|
||||
.cra_driver_name = "ecb-aes-s390",
|
||||
.cra_priority = CRYPT_S390_COMPOSITE_PRIORITY,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
|
||||
.cra_blocksize = AES_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct s390_aes_ctx),
|
||||
.cra_type = &crypto_blkcipher_type,
|
||||
.cra_module = THIS_MODULE,
|
||||
.cra_list = LIST_HEAD_INIT(ecb_aes_alg.cra_list),
|
||||
.cra_u = {
|
||||
.blkcipher = {
|
||||
.min_keysize = AES_MIN_KEY_SIZE,
|
||||
.max_keysize = AES_MAX_KEY_SIZE,
|
||||
.setkey = ecb_aes_set_key,
|
||||
.encrypt = ecb_aes_encrypt,
|
||||
.decrypt = ecb_aes_decrypt,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static int cbc_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
|
||||
unsigned int key_len)
|
||||
{
|
||||
struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
|
||||
|
||||
switch (key_len) {
|
||||
case 16:
|
||||
sctx->enc = KMC_AES_128_ENCRYPT;
|
||||
sctx->dec = KMC_AES_128_DECRYPT;
|
||||
break;
|
||||
case 24:
|
||||
sctx->enc = KMC_AES_192_ENCRYPT;
|
||||
sctx->dec = KMC_AES_192_DECRYPT;
|
||||
break;
|
||||
case 32:
|
||||
sctx->enc = KMC_AES_256_ENCRYPT;
|
||||
sctx->dec = KMC_AES_256_DECRYPT;
|
||||
break;
|
||||
}
|
||||
|
||||
return aes_set_key(tfm, in_key, key_len);
|
||||
}
|
||||
|
||||
static int cbc_aes_crypt(struct blkcipher_desc *desc, long func, void *param,
|
||||
struct blkcipher_walk *walk)
|
||||
{
|
||||
int ret = blkcipher_walk_virt(desc, walk);
|
||||
unsigned int nbytes = walk->nbytes;
|
||||
|
||||
if (!nbytes)
|
||||
goto out;
|
||||
|
||||
memcpy(param, walk->iv, AES_BLOCK_SIZE);
|
||||
do {
|
||||
/* only use complete blocks */
|
||||
unsigned int n = nbytes & ~(AES_BLOCK_SIZE - 1);
|
||||
u8 *out = walk->dst.virt.addr;
|
||||
u8 *in = walk->src.virt.addr;
|
||||
|
||||
ret = crypt_s390_kmc(func, param, out, in, n);
|
||||
BUG_ON((ret < 0) || (ret != n));
|
||||
|
||||
nbytes &= AES_BLOCK_SIZE - 1;
|
||||
ret = blkcipher_walk_done(desc, walk, nbytes);
|
||||
} while ((nbytes = walk->nbytes));
|
||||
memcpy(walk->iv, param, AES_BLOCK_SIZE);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cbc_aes_encrypt(struct blkcipher_desc *desc,
|
||||
struct scatterlist *dst, struct scatterlist *src,
|
||||
unsigned int nbytes)
|
||||
{
|
||||
struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
|
||||
struct blkcipher_walk walk;
|
||||
|
||||
blkcipher_walk_init(&walk, dst, src, nbytes);
|
||||
return cbc_aes_crypt(desc, sctx->enc, sctx->iv, &walk);
|
||||
}
|
||||
|
||||
static int cbc_aes_decrypt(struct blkcipher_desc *desc,
|
||||
struct scatterlist *dst, struct scatterlist *src,
|
||||
unsigned int nbytes)
|
||||
{
|
||||
struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
|
||||
struct blkcipher_walk walk;
|
||||
|
||||
blkcipher_walk_init(&walk, dst, src, nbytes);
|
||||
return cbc_aes_crypt(desc, sctx->dec, sctx->iv, &walk);
|
||||
}
|
||||
|
||||
static struct crypto_alg cbc_aes_alg = {
|
||||
.cra_name = "cbc(aes)",
|
||||
.cra_driver_name = "cbc-aes-s390",
|
||||
.cra_priority = CRYPT_S390_COMPOSITE_PRIORITY,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
|
||||
.cra_blocksize = AES_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct s390_aes_ctx),
|
||||
.cra_type = &crypto_blkcipher_type,
|
||||
.cra_module = THIS_MODULE,
|
||||
.cra_list = LIST_HEAD_INIT(cbc_aes_alg.cra_list),
|
||||
.cra_u = {
|
||||
.blkcipher = {
|
||||
.min_keysize = AES_MIN_KEY_SIZE,
|
||||
.max_keysize = AES_MAX_KEY_SIZE,
|
||||
.ivsize = AES_BLOCK_SIZE,
|
||||
.setkey = cbc_aes_set_key,
|
||||
.encrypt = cbc_aes_encrypt,
|
||||
.decrypt = cbc_aes_decrypt,
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -256,13 +332,40 @@ static int __init aes_init(void)
|
||||
return -ENOSYS;
|
||||
|
||||
ret = crypto_register_alg(&aes_alg);
|
||||
if (ret != 0)
|
||||
printk(KERN_INFO "crypt_s390: aes_s390 couldn't be loaded.\n");
|
||||
if (ret != 0) {
|
||||
printk(KERN_INFO "crypt_s390: aes-s390 couldn't be loaded.\n");
|
||||
goto aes_err;
|
||||
}
|
||||
|
||||
ret = crypto_register_alg(&ecb_aes_alg);
|
||||
if (ret != 0) {
|
||||
printk(KERN_INFO
|
||||
"crypt_s390: ecb-aes-s390 couldn't be loaded.\n");
|
||||
goto ecb_aes_err;
|
||||
}
|
||||
|
||||
ret = crypto_register_alg(&cbc_aes_alg);
|
||||
if (ret != 0) {
|
||||
printk(KERN_INFO
|
||||
"crypt_s390: cbc-aes-s390 couldn't be loaded.\n");
|
||||
goto cbc_aes_err;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
|
||||
cbc_aes_err:
|
||||
crypto_unregister_alg(&ecb_aes_alg);
|
||||
ecb_aes_err:
|
||||
crypto_unregister_alg(&aes_alg);
|
||||
aes_err:
|
||||
goto out;
|
||||
}
|
||||
|
||||
static void __exit aes_fini(void)
|
||||
{
|
||||
crypto_unregister_alg(&cbc_aes_alg);
|
||||
crypto_unregister_alg(&ecb_aes_alg);
|
||||
crypto_unregister_alg(&aes_alg);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
#define CRYPT_S390_OP_MASK 0xFF00
|
||||
#define CRYPT_S390_FUNC_MASK 0x00FF
|
||||
|
||||
#define CRYPT_S390_PRIORITY 300
|
||||
#define CRYPT_S390_COMPOSITE_PRIORITY 400
|
||||
|
||||
/* s930 cryptographic operations */
|
||||
enum crypt_s390_operations {
|
||||
CRYPT_S390_KM = 0x0100,
|
||||
|
||||
+388
-219
File diff suppressed because it is too large
Load Diff
@@ -126,6 +126,8 @@ static void sha1_final(struct crypto_tfm *tfm, u8 *out)
|
||||
|
||||
static struct crypto_alg alg = {
|
||||
.cra_name = "sha1",
|
||||
.cra_driver_name = "sha1-s390",
|
||||
.cra_priority = CRYPT_S390_PRIORITY,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_DIGEST,
|
||||
.cra_blocksize = SHA1_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct crypt_s390_sha1_ctx),
|
||||
|
||||
@@ -127,6 +127,8 @@ static void sha256_final(struct crypto_tfm *tfm, u8 *out)
|
||||
|
||||
static struct crypto_alg alg = {
|
||||
.cra_name = "sha256",
|
||||
.cra_driver_name = "sha256-s390",
|
||||
.cra_priority = CRYPT_S390_PRIORITY,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_DIGEST,
|
||||
.cra_blocksize = SHA256_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct s390_sha256_ctx),
|
||||
|
||||
@@ -5,5 +5,8 @@
|
||||
#
|
||||
|
||||
obj-$(CONFIG_CRYPTO_AES_X86_64) += aes-x86_64.o
|
||||
obj-$(CONFIG_CRYPTO_TWOFISH_X86_64) += twofish-x86_64.o
|
||||
|
||||
aes-x86_64-y := aes-x86_64-asm.o aes.o
|
||||
twofish-x86_64-y := twofish-x86_64-asm.o twofish.o
|
||||
|
||||
|
||||
@@ -228,13 +228,14 @@ static void __init gen_tabs(void)
|
||||
}
|
||||
|
||||
static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
|
||||
unsigned int key_len, u32 *flags)
|
||||
unsigned int key_len)
|
||||
{
|
||||
struct aes_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
const __le32 *key = (const __le32 *)in_key;
|
||||
u32 *flags = &tfm->crt_flags;
|
||||
u32 i, j, t, u, v, w;
|
||||
|
||||
if (key_len != 16 && key_len != 24 && key_len != 32) {
|
||||
if (key_len % 8) {
|
||||
*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,324 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2006 by Joachim Fritschi, <jfritschi@freenet.de> *
|
||||
* *
|
||||
* 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.S"
|
||||
.text
|
||||
|
||||
#include <asm/asm-offsets.h>
|
||||
|
||||
#define a_offset 0
|
||||
#define b_offset 4
|
||||
#define c_offset 8
|
||||
#define d_offset 12
|
||||
|
||||
/* Structure of the crypto context struct*/
|
||||
|
||||
#define s0 0 /* S0 Array 256 Words each */
|
||||
#define s1 1024 /* S1 Array */
|
||||
#define s2 2048 /* S2 Array */
|
||||
#define s3 3072 /* S3 Array */
|
||||
#define w 4096 /* 8 whitening keys (word) */
|
||||
#define k 4128 /* key 1-32 ( word ) */
|
||||
|
||||
/* define a few register aliases to allow macro substitution */
|
||||
|
||||
#define R0 %rax
|
||||
#define R0D %eax
|
||||
#define R0B %al
|
||||
#define R0H %ah
|
||||
|
||||
#define R1 %rbx
|
||||
#define R1D %ebx
|
||||
#define R1B %bl
|
||||
#define R1H %bh
|
||||
|
||||
#define R2 %rcx
|
||||
#define R2D %ecx
|
||||
#define R2B %cl
|
||||
#define R2H %ch
|
||||
|
||||
#define R3 %rdx
|
||||
#define R3D %edx
|
||||
#define R3B %dl
|
||||
#define R3H %dh
|
||||
|
||||
|
||||
/* performs input whitening */
|
||||
#define input_whitening(src,context,offset)\
|
||||
xor w+offset(context), src;
|
||||
|
||||
/* performs input whitening */
|
||||
#define output_whitening(src,context,offset)\
|
||||
xor w+16+offset(context), src;
|
||||
|
||||
|
||||
/*
|
||||
* a input register containing a (rotated 16)
|
||||
* b input register containing b
|
||||
* c input register containing c
|
||||
* d input register containing d (already rol $1)
|
||||
* operations on a and b are interleaved to increase performance
|
||||
*/
|
||||
#define encrypt_round(a,b,c,d,round)\
|
||||
movzx b ## B, %edi;\
|
||||
mov s1(%r11,%rdi,4),%r8d;\
|
||||
movzx a ## B, %edi;\
|
||||
mov s2(%r11,%rdi,4),%r9d;\
|
||||
movzx b ## H, %edi;\
|
||||
ror $16, b ## D;\
|
||||
xor s2(%r11,%rdi,4),%r8d;\
|
||||
movzx a ## H, %edi;\
|
||||
ror $16, a ## D;\
|
||||
xor s3(%r11,%rdi,4),%r9d;\
|
||||
movzx b ## B, %edi;\
|
||||
xor s3(%r11,%rdi,4),%r8d;\
|
||||
movzx a ## B, %edi;\
|
||||
xor (%r11,%rdi,4), %r9d;\
|
||||
movzx b ## H, %edi;\
|
||||
ror $15, b ## D;\
|
||||
xor (%r11,%rdi,4), %r8d;\
|
||||
movzx a ## H, %edi;\
|
||||
xor s1(%r11,%rdi,4),%r9d;\
|
||||
add %r8d, %r9d;\
|
||||
add %r9d, %r8d;\
|
||||
add k+round(%r11), %r9d;\
|
||||
xor %r9d, c ## D;\
|
||||
rol $15, c ## D;\
|
||||
add k+4+round(%r11),%r8d;\
|
||||
xor %r8d, d ## D;
|
||||
|
||||
/*
|
||||
* a input register containing a(rotated 16)
|
||||
* b input register containing b
|
||||
* c input register containing c
|
||||
* d input register containing d (already rol $1)
|
||||
* operations on a and b are interleaved to increase performance
|
||||
* during the round a and b are prepared for the output whitening
|
||||
*/
|
||||
#define encrypt_last_round(a,b,c,d,round)\
|
||||
mov b ## D, %r10d;\
|
||||
shl $32, %r10;\
|
||||
movzx b ## B, %edi;\
|
||||
mov s1(%r11,%rdi,4),%r8d;\
|
||||
movzx a ## B, %edi;\
|
||||
mov s2(%r11,%rdi,4),%r9d;\
|
||||
movzx b ## H, %edi;\
|
||||
ror $16, b ## D;\
|
||||
xor s2(%r11,%rdi,4),%r8d;\
|
||||
movzx a ## H, %edi;\
|
||||
ror $16, a ## D;\
|
||||
xor s3(%r11,%rdi,4),%r9d;\
|
||||
movzx b ## B, %edi;\
|
||||
xor s3(%r11,%rdi,4),%r8d;\
|
||||
movzx a ## B, %edi;\
|
||||
xor (%r11,%rdi,4), %r9d;\
|
||||
xor a, %r10;\
|
||||
movzx b ## H, %edi;\
|
||||
xor (%r11,%rdi,4), %r8d;\
|
||||
movzx a ## H, %edi;\
|
||||
xor s1(%r11,%rdi,4),%r9d;\
|
||||
add %r8d, %r9d;\
|
||||
add %r9d, %r8d;\
|
||||
add k+round(%r11), %r9d;\
|
||||
xor %r9d, c ## D;\
|
||||
ror $1, c ## D;\
|
||||
add k+4+round(%r11),%r8d;\
|
||||
xor %r8d, d ## D
|
||||
|
||||
/*
|
||||
* a input register containing a
|
||||
* b input register containing b (rotated 16)
|
||||
* c input register containing c (already rol $1)
|
||||
* d input register containing d
|
||||
* operations on a and b are interleaved to increase performance
|
||||
*/
|
||||
#define decrypt_round(a,b,c,d,round)\
|
||||
movzx a ## B, %edi;\
|
||||
mov (%r11,%rdi,4), %r9d;\
|
||||
movzx b ## B, %edi;\
|
||||
mov s3(%r11,%rdi,4),%r8d;\
|
||||
movzx a ## H, %edi;\
|
||||
ror $16, a ## D;\
|
||||
xor s1(%r11,%rdi,4),%r9d;\
|
||||
movzx b ## H, %edi;\
|
||||
ror $16, b ## D;\
|
||||
xor (%r11,%rdi,4), %r8d;\
|
||||
movzx a ## B, %edi;\
|
||||
xor s2(%r11,%rdi,4),%r9d;\
|
||||
movzx b ## B, %edi;\
|
||||
xor s1(%r11,%rdi,4),%r8d;\
|
||||
movzx a ## H, %edi;\
|
||||
ror $15, a ## D;\
|
||||
xor s3(%r11,%rdi,4),%r9d;\
|
||||
movzx b ## H, %edi;\
|
||||
xor s2(%r11,%rdi,4),%r8d;\
|
||||
add %r8d, %r9d;\
|
||||
add %r9d, %r8d;\
|
||||
add k+round(%r11), %r9d;\
|
||||
xor %r9d, c ## D;\
|
||||
add k+4+round(%r11),%r8d;\
|
||||
xor %r8d, d ## D;\
|
||||
rol $15, d ## D;
|
||||
|
||||
/*
|
||||
* a input register containing a
|
||||
* b input register containing b
|
||||
* c input register containing c (already rol $1)
|
||||
* d input register containing d
|
||||
* operations on a and b are interleaved to increase performance
|
||||
* during the round a and b are prepared for the output whitening
|
||||
*/
|
||||
#define decrypt_last_round(a,b,c,d,round)\
|
||||
movzx a ## B, %edi;\
|
||||
mov (%r11,%rdi,4), %r9d;\
|
||||
movzx b ## B, %edi;\
|
||||
mov s3(%r11,%rdi,4),%r8d;\
|
||||
movzx b ## H, %edi;\
|
||||
ror $16, b ## D;\
|
||||
xor (%r11,%rdi,4), %r8d;\
|
||||
movzx a ## H, %edi;\
|
||||
mov b ## D, %r10d;\
|
||||
shl $32, %r10;\
|
||||
xor a, %r10;\
|
||||
ror $16, a ## D;\
|
||||
xor s1(%r11,%rdi,4),%r9d;\
|
||||
movzx b ## B, %edi;\
|
||||
xor s1(%r11,%rdi,4),%r8d;\
|
||||
movzx a ## B, %edi;\
|
||||
xor s2(%r11,%rdi,4),%r9d;\
|
||||
movzx b ## H, %edi;\
|
||||
xor s2(%r11,%rdi,4),%r8d;\
|
||||
movzx a ## H, %edi;\
|
||||
xor s3(%r11,%rdi,4),%r9d;\
|
||||
add %r8d, %r9d;\
|
||||
add %r9d, %r8d;\
|
||||
add k+round(%r11), %r9d;\
|
||||
xor %r9d, c ## D;\
|
||||
add k+4+round(%r11),%r8d;\
|
||||
xor %r8d, d ## D;\
|
||||
ror $1, d ## D;
|
||||
|
||||
.align 8
|
||||
.global twofish_enc_blk
|
||||
.global twofish_dec_blk
|
||||
|
||||
twofish_enc_blk:
|
||||
pushq R1
|
||||
|
||||
/* %rdi contains the crypto tfm adress */
|
||||
/* %rsi contains the output adress */
|
||||
/* %rdx contains the input adress */
|
||||
add $crypto_tfm_ctx_offset, %rdi /* set ctx adress */
|
||||
/* ctx adress is moved to free one non-rex register
|
||||
as target for the 8bit high operations */
|
||||
mov %rdi, %r11
|
||||
|
||||
movq (R3), R1
|
||||
movq 8(R3), R3
|
||||
input_whitening(R1,%r11,a_offset)
|
||||
input_whitening(R3,%r11,c_offset)
|
||||
mov R1D, R0D
|
||||
rol $16, R0D
|
||||
shr $32, R1
|
||||
mov R3D, R2D
|
||||
shr $32, R3
|
||||
rol $1, R3D
|
||||
|
||||
encrypt_round(R0,R1,R2,R3,0);
|
||||
encrypt_round(R2,R3,R0,R1,8);
|
||||
encrypt_round(R0,R1,R2,R3,2*8);
|
||||
encrypt_round(R2,R3,R0,R1,3*8);
|
||||
encrypt_round(R0,R1,R2,R3,4*8);
|
||||
encrypt_round(R2,R3,R0,R1,5*8);
|
||||
encrypt_round(R0,R1,R2,R3,6*8);
|
||||
encrypt_round(R2,R3,R0,R1,7*8);
|
||||
encrypt_round(R0,R1,R2,R3,8*8);
|
||||
encrypt_round(R2,R3,R0,R1,9*8);
|
||||
encrypt_round(R0,R1,R2,R3,10*8);
|
||||
encrypt_round(R2,R3,R0,R1,11*8);
|
||||
encrypt_round(R0,R1,R2,R3,12*8);
|
||||
encrypt_round(R2,R3,R0,R1,13*8);
|
||||
encrypt_round(R0,R1,R2,R3,14*8);
|
||||
encrypt_last_round(R2,R3,R0,R1,15*8);
|
||||
|
||||
|
||||
output_whitening(%r10,%r11,a_offset)
|
||||
movq %r10, (%rsi)
|
||||
|
||||
shl $32, R1
|
||||
xor R0, R1
|
||||
|
||||
output_whitening(R1,%r11,c_offset)
|
||||
movq R1, 8(%rsi)
|
||||
|
||||
popq R1
|
||||
movq $1,%rax
|
||||
ret
|
||||
|
||||
twofish_dec_blk:
|
||||
pushq R1
|
||||
|
||||
/* %rdi contains the crypto tfm adress */
|
||||
/* %rsi contains the output adress */
|
||||
/* %rdx contains the input adress */
|
||||
add $crypto_tfm_ctx_offset, %rdi /* set ctx adress */
|
||||
/* ctx adress is moved to free one non-rex register
|
||||
as target for the 8bit high operations */
|
||||
mov %rdi, %r11
|
||||
|
||||
movq (R3), R1
|
||||
movq 8(R3), R3
|
||||
output_whitening(R1,%r11,a_offset)
|
||||
output_whitening(R3,%r11,c_offset)
|
||||
mov R1D, R0D
|
||||
shr $32, R1
|
||||
rol $16, R1D
|
||||
mov R3D, R2D
|
||||
shr $32, R3
|
||||
rol $1, R2D
|
||||
|
||||
decrypt_round(R0,R1,R2,R3,15*8);
|
||||
decrypt_round(R2,R3,R0,R1,14*8);
|
||||
decrypt_round(R0,R1,R2,R3,13*8);
|
||||
decrypt_round(R2,R3,R0,R1,12*8);
|
||||
decrypt_round(R0,R1,R2,R3,11*8);
|
||||
decrypt_round(R2,R3,R0,R1,10*8);
|
||||
decrypt_round(R0,R1,R2,R3,9*8);
|
||||
decrypt_round(R2,R3,R0,R1,8*8);
|
||||
decrypt_round(R0,R1,R2,R3,7*8);
|
||||
decrypt_round(R2,R3,R0,R1,6*8);
|
||||
decrypt_round(R0,R1,R2,R3,5*8);
|
||||
decrypt_round(R2,R3,R0,R1,4*8);
|
||||
decrypt_round(R0,R1,R2,R3,3*8);
|
||||
decrypt_round(R2,R3,R0,R1,2*8);
|
||||
decrypt_round(R0,R1,R2,R3,1*8);
|
||||
decrypt_last_round(R2,R3,R0,R1,0);
|
||||
|
||||
input_whitening(%r10,%r11,a_offset)
|
||||
movq %r10, (%rsi)
|
||||
|
||||
shl $32, R1
|
||||
xor R0, R1
|
||||
|
||||
input_whitening(R1,%r11,c_offset)
|
||||
movq R1, 8(%rsi)
|
||||
|
||||
popq R1
|
||||
movq $1,%rax
|
||||
ret
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Glue Code for optimized x86_64 assembler version of TWOFISH
|
||||
*
|
||||
* Originally Twofish for GPG
|
||||
* By Matthew Skala <mskala@ansuz.sooke.bc.ca>, July 26, 1998
|
||||
* 256-bit key length added March 20, 1999
|
||||
* Some modifications to reduce the text size by Werner Koch, April, 1998
|
||||
* Ported to the kerneli patch by Marc Mutz <Marc@Mutz.com>
|
||||
* Ported to CryptoAPI by Colin Slater <hoho@tacomeat.net>
|
||||
*
|
||||
* The original author has disclaimed all copyright interest in this
|
||||
* code and thus put it in the public domain. The subsequent authors
|
||||
* have put this under the GNU General Public License.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* This code is a "clean room" implementation, written from the paper
|
||||
* _Twofish: A 128-Bit Block Cipher_ by Bruce Schneier, John Kelsey,
|
||||
* Doug Whiting, David Wagner, Chris Hall, and Niels Ferguson, available
|
||||
* through http://www.counterpane.com/twofish.html
|
||||
*
|
||||
* For background information on multiplication in finite fields, used for
|
||||
* the matrix operations in the key schedule, see the book _Contemporary
|
||||
* Abstract Algebra_ by Joseph A. Gallian, especially chapter 22 in the
|
||||
* Third Edition.
|
||||
*/
|
||||
|
||||
#include <crypto/twofish.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#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);
|
||||
|
||||
static void twofish_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
|
||||
{
|
||||
twofish_enc_blk(tfm, dst, src);
|
||||
}
|
||||
|
||||
static void twofish_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
|
||||
{
|
||||
twofish_dec_blk(tfm, dst, src);
|
||||
}
|
||||
|
||||
static struct crypto_alg alg = {
|
||||
.cra_name = "twofish",
|
||||
.cra_driver_name = "twofish-x86_64",
|
||||
.cra_priority = 200,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
|
||||
.cra_blocksize = TF_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct twofish_ctx),
|
||||
.cra_alignmask = 3,
|
||||
.cra_module = THIS_MODULE,
|
||||
.cra_list = LIST_HEAD_INIT(alg.cra_list),
|
||||
.cra_u = {
|
||||
.cipher = {
|
||||
.cia_min_keysize = TF_MIN_KEY_SIZE,
|
||||
.cia_max_keysize = TF_MAX_KEY_SIZE,
|
||||
.cia_setkey = twofish_setkey,
|
||||
.cia_encrypt = twofish_encrypt,
|
||||
.cia_decrypt = twofish_decrypt
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static int __init init(void)
|
||||
{
|
||||
return crypto_register_alg(&alg);
|
||||
}
|
||||
|
||||
static void __exit fini(void)
|
||||
{
|
||||
crypto_unregister_alg(&alg);
|
||||
}
|
||||
|
||||
module_init(init);
|
||||
module_exit(fini);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION ("Twofish Cipher Algorithm, x86_64 asm optimized");
|
||||
MODULE_ALIAS("twofish");
|
||||
+122
-32
@@ -9,47 +9,71 @@ config CRYPTO
|
||||
help
|
||||
This option provides the core Cryptographic API.
|
||||
|
||||
if CRYPTO
|
||||
|
||||
config CRYPTO_ALGAPI
|
||||
tristate
|
||||
help
|
||||
This option provides the API for cryptographic algorithms.
|
||||
|
||||
config CRYPTO_BLKCIPHER
|
||||
tristate
|
||||
select CRYPTO_ALGAPI
|
||||
|
||||
config CRYPTO_HASH
|
||||
tristate
|
||||
select CRYPTO_ALGAPI
|
||||
|
||||
config CRYPTO_MANAGER
|
||||
tristate "Cryptographic algorithm manager"
|
||||
select CRYPTO_ALGAPI
|
||||
default m
|
||||
help
|
||||
Create default cryptographic template instantiations such as
|
||||
cbc(aes).
|
||||
|
||||
config CRYPTO_HMAC
|
||||
bool "HMAC support"
|
||||
depends on CRYPTO
|
||||
tristate "HMAC support"
|
||||
select CRYPTO_HASH
|
||||
help
|
||||
HMAC: Keyed-Hashing for Message Authentication (RFC2104).
|
||||
This is required for IPSec.
|
||||
|
||||
config CRYPTO_NULL
|
||||
tristate "Null algorithms"
|
||||
depends on CRYPTO
|
||||
select CRYPTO_ALGAPI
|
||||
help
|
||||
These are 'Null' algorithms, used by IPsec, which do nothing.
|
||||
|
||||
config CRYPTO_MD4
|
||||
tristate "MD4 digest algorithm"
|
||||
depends on CRYPTO
|
||||
select CRYPTO_ALGAPI
|
||||
help
|
||||
MD4 message digest algorithm (RFC1320).
|
||||
|
||||
config CRYPTO_MD5
|
||||
tristate "MD5 digest algorithm"
|
||||
depends on CRYPTO
|
||||
select CRYPTO_ALGAPI
|
||||
help
|
||||
MD5 message digest algorithm (RFC1321).
|
||||
|
||||
config CRYPTO_SHA1
|
||||
tristate "SHA1 digest algorithm"
|
||||
depends on CRYPTO
|
||||
select CRYPTO_ALGAPI
|
||||
help
|
||||
SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2).
|
||||
|
||||
config CRYPTO_SHA1_S390
|
||||
tristate "SHA1 digest algorithm (s390)"
|
||||
depends on CRYPTO && S390
|
||||
depends on S390
|
||||
select CRYPTO_ALGAPI
|
||||
help
|
||||
This is the s390 hardware accelerated implementation of the
|
||||
SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2).
|
||||
|
||||
config CRYPTO_SHA256
|
||||
tristate "SHA256 digest algorithm"
|
||||
depends on CRYPTO
|
||||
select CRYPTO_ALGAPI
|
||||
help
|
||||
SHA256 secure hash standard (DFIPS 180-2).
|
||||
|
||||
@@ -58,7 +82,8 @@ config CRYPTO_SHA256
|
||||
|
||||
config CRYPTO_SHA256_S390
|
||||
tristate "SHA256 digest algorithm (s390)"
|
||||
depends on CRYPTO && S390
|
||||
depends on S390
|
||||
select CRYPTO_ALGAPI
|
||||
help
|
||||
This is the s390 hardware accelerated implementation of the
|
||||
SHA256 secure hash standard (DFIPS 180-2).
|
||||
@@ -68,7 +93,7 @@ config CRYPTO_SHA256_S390
|
||||
|
||||
config CRYPTO_SHA512
|
||||
tristate "SHA384 and SHA512 digest algorithms"
|
||||
depends on CRYPTO
|
||||
select CRYPTO_ALGAPI
|
||||
help
|
||||
SHA512 secure hash standard (DFIPS 180-2).
|
||||
|
||||
@@ -80,7 +105,7 @@ config CRYPTO_SHA512
|
||||
|
||||
config CRYPTO_WP512
|
||||
tristate "Whirlpool digest algorithms"
|
||||
depends on CRYPTO
|
||||
select CRYPTO_ALGAPI
|
||||
help
|
||||
Whirlpool hash algorithm 512, 384 and 256-bit hashes
|
||||
|
||||
@@ -92,7 +117,7 @@ config CRYPTO_WP512
|
||||
|
||||
config CRYPTO_TGR192
|
||||
tristate "Tiger digest algorithms"
|
||||
depends on CRYPTO
|
||||
select CRYPTO_ALGAPI
|
||||
help
|
||||
Tiger hash algorithm 192, 160 and 128-bit hashes
|
||||
|
||||
@@ -103,21 +128,40 @@ config CRYPTO_TGR192
|
||||
See also:
|
||||
<http://www.cs.technion.ac.il/~biham/Reports/Tiger/>.
|
||||
|
||||
config CRYPTO_ECB
|
||||
tristate "ECB support"
|
||||
select CRYPTO_BLKCIPHER
|
||||
default m
|
||||
help
|
||||
ECB: Electronic CodeBook mode
|
||||
This is the simplest block cipher algorithm. It simply encrypts
|
||||
the input block by block.
|
||||
|
||||
config CRYPTO_CBC
|
||||
tristate "CBC support"
|
||||
select CRYPTO_BLKCIPHER
|
||||
default m
|
||||
help
|
||||
CBC: Cipher Block Chaining mode
|
||||
This block cipher algorithm is required for IPSec.
|
||||
|
||||
config CRYPTO_DES
|
||||
tristate "DES and Triple DES EDE cipher algorithms"
|
||||
depends on CRYPTO
|
||||
select CRYPTO_ALGAPI
|
||||
help
|
||||
DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3).
|
||||
|
||||
config CRYPTO_DES_S390
|
||||
tristate "DES and Triple DES cipher algorithms (s390)"
|
||||
depends on CRYPTO && S390
|
||||
depends on S390
|
||||
select CRYPTO_ALGAPI
|
||||
select CRYPTO_BLKCIPHER
|
||||
help
|
||||
DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3).
|
||||
|
||||
config CRYPTO_BLOWFISH
|
||||
tristate "Blowfish cipher algorithm"
|
||||
depends on CRYPTO
|
||||
select CRYPTO_ALGAPI
|
||||
help
|
||||
Blowfish cipher algorithm, by Bruce Schneier.
|
||||
|
||||
@@ -130,7 +174,8 @@ config CRYPTO_BLOWFISH
|
||||
|
||||
config CRYPTO_TWOFISH
|
||||
tristate "Twofish cipher algorithm"
|
||||
depends on CRYPTO
|
||||
select CRYPTO_ALGAPI
|
||||
select CRYPTO_TWOFISH_COMMON
|
||||
help
|
||||
Twofish cipher algorithm.
|
||||
|
||||
@@ -142,9 +187,47 @@ config CRYPTO_TWOFISH
|
||||
See also:
|
||||
<http://www.schneier.com/twofish.html>
|
||||
|
||||
config CRYPTO_TWOFISH_COMMON
|
||||
tristate
|
||||
help
|
||||
Common parts of the Twofish cipher algorithm shared by the
|
||||
generic c and the assembler implementations.
|
||||
|
||||
config CRYPTO_TWOFISH_586
|
||||
tristate "Twofish cipher algorithms (i586)"
|
||||
depends on (X86 || UML_X86) && !64BIT
|
||||
select CRYPTO_ALGAPI
|
||||
select CRYPTO_TWOFISH_COMMON
|
||||
help
|
||||
Twofish cipher algorithm.
|
||||
|
||||
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.
|
||||
|
||||
See also:
|
||||
<http://www.schneier.com/twofish.html>
|
||||
|
||||
config CRYPTO_TWOFISH_X86_64
|
||||
tristate "Twofish cipher algorithm (x86_64)"
|
||||
depends on (X86 || UML_X86) && 64BIT
|
||||
select CRYPTO_ALGAPI
|
||||
select CRYPTO_TWOFISH_COMMON
|
||||
help
|
||||
Twofish cipher algorithm (x86_64).
|
||||
|
||||
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.
|
||||
|
||||
See also:
|
||||
<http://www.schneier.com/twofish.html>
|
||||
|
||||
config CRYPTO_SERPENT
|
||||
tristate "Serpent cipher algorithm"
|
||||
depends on CRYPTO
|
||||
select CRYPTO_ALGAPI
|
||||
help
|
||||
Serpent cipher algorithm, by Anderson, Biham & Knudsen.
|
||||
|
||||
@@ -157,7 +240,7 @@ config CRYPTO_SERPENT
|
||||
|
||||
config CRYPTO_AES
|
||||
tristate "AES cipher algorithms"
|
||||
depends on CRYPTO
|
||||
select CRYPTO_ALGAPI
|
||||
help
|
||||
AES cipher algorithms (FIPS-197). AES uses the Rijndael
|
||||
algorithm.
|
||||
@@ -177,7 +260,8 @@ config CRYPTO_AES
|
||||
|
||||
config CRYPTO_AES_586
|
||||
tristate "AES cipher algorithms (i586)"
|
||||
depends on CRYPTO && ((X86 || UML_X86) && !64BIT)
|
||||
depends on (X86 || UML_X86) && !64BIT
|
||||
select CRYPTO_ALGAPI
|
||||
help
|
||||
AES cipher algorithms (FIPS-197). AES uses the Rijndael
|
||||
algorithm.
|
||||
@@ -197,7 +281,8 @@ config CRYPTO_AES_586
|
||||
|
||||
config CRYPTO_AES_X86_64
|
||||
tristate "AES cipher algorithms (x86_64)"
|
||||
depends on CRYPTO && ((X86 || UML_X86) && 64BIT)
|
||||
depends on (X86 || UML_X86) && 64BIT
|
||||
select CRYPTO_ALGAPI
|
||||
help
|
||||
AES cipher algorithms (FIPS-197). AES uses the Rijndael
|
||||
algorithm.
|
||||
@@ -217,7 +302,9 @@ config CRYPTO_AES_X86_64
|
||||
|
||||
config CRYPTO_AES_S390
|
||||
tristate "AES cipher algorithms (s390)"
|
||||
depends on CRYPTO && S390
|
||||
depends on S390
|
||||
select CRYPTO_ALGAPI
|
||||
select CRYPTO_BLKCIPHER
|
||||
help
|
||||
This is the s390 hardware accelerated implementation of the
|
||||
AES cipher algorithms (FIPS-197). AES uses the Rijndael
|
||||
@@ -237,21 +324,21 @@ config CRYPTO_AES_S390
|
||||
|
||||
config CRYPTO_CAST5
|
||||
tristate "CAST5 (CAST-128) cipher algorithm"
|
||||
depends on CRYPTO
|
||||
select CRYPTO_ALGAPI
|
||||
help
|
||||
The CAST5 encryption algorithm (synonymous with CAST-128) is
|
||||
described in RFC2144.
|
||||
|
||||
config CRYPTO_CAST6
|
||||
tristate "CAST6 (CAST-256) cipher algorithm"
|
||||
depends on CRYPTO
|
||||
select CRYPTO_ALGAPI
|
||||
help
|
||||
The CAST6 encryption algorithm (synonymous with CAST-256) is
|
||||
described in RFC2612.
|
||||
|
||||
config CRYPTO_TEA
|
||||
tristate "TEA, XTEA and XETA cipher algorithms"
|
||||
depends on CRYPTO
|
||||
select CRYPTO_ALGAPI
|
||||
help
|
||||
TEA cipher algorithm.
|
||||
|
||||
@@ -268,7 +355,7 @@ config CRYPTO_TEA
|
||||
|
||||
config CRYPTO_ARC4
|
||||
tristate "ARC4 cipher algorithm"
|
||||
depends on CRYPTO
|
||||
select CRYPTO_ALGAPI
|
||||
help
|
||||
ARC4 cipher algorithm.
|
||||
|
||||
@@ -279,7 +366,7 @@ config CRYPTO_ARC4
|
||||
|
||||
config CRYPTO_KHAZAD
|
||||
tristate "Khazad cipher algorithm"
|
||||
depends on CRYPTO
|
||||
select CRYPTO_ALGAPI
|
||||
help
|
||||
Khazad cipher algorithm.
|
||||
|
||||
@@ -292,7 +379,7 @@ config CRYPTO_KHAZAD
|
||||
|
||||
config CRYPTO_ANUBIS
|
||||
tristate "Anubis cipher algorithm"
|
||||
depends on CRYPTO
|
||||
select CRYPTO_ALGAPI
|
||||
help
|
||||
Anubis cipher algorithm.
|
||||
|
||||
@@ -307,7 +394,7 @@ config CRYPTO_ANUBIS
|
||||
|
||||
config CRYPTO_DEFLATE
|
||||
tristate "Deflate compression algorithm"
|
||||
depends on CRYPTO
|
||||
select CRYPTO_ALGAPI
|
||||
select ZLIB_INFLATE
|
||||
select ZLIB_DEFLATE
|
||||
help
|
||||
@@ -318,7 +405,7 @@ config CRYPTO_DEFLATE
|
||||
|
||||
config CRYPTO_MICHAEL_MIC
|
||||
tristate "Michael MIC keyed digest algorithm"
|
||||
depends on CRYPTO
|
||||
select CRYPTO_ALGAPI
|
||||
help
|
||||
Michael MIC is used for message integrity protection in TKIP
|
||||
(IEEE 802.11i). This algorithm is required for TKIP, but it
|
||||
@@ -327,7 +414,7 @@ config CRYPTO_MICHAEL_MIC
|
||||
|
||||
config CRYPTO_CRC32C
|
||||
tristate "CRC32c CRC algorithm"
|
||||
depends on CRYPTO
|
||||
select CRYPTO_ALGAPI
|
||||
select LIBCRC32C
|
||||
help
|
||||
Castagnoli, et al Cyclic Redundancy-Check Algorithm. Used
|
||||
@@ -337,10 +424,13 @@ config CRYPTO_CRC32C
|
||||
|
||||
config CRYPTO_TEST
|
||||
tristate "Testing module"
|
||||
depends on CRYPTO && m
|
||||
depends on m
|
||||
select CRYPTO_ALGAPI
|
||||
help
|
||||
Quick & dirty crypto test module.
|
||||
|
||||
source "drivers/crypto/Kconfig"
|
||||
endmenu
|
||||
|
||||
endif # if CRYPTO
|
||||
|
||||
endmenu
|
||||
|
||||
+13
-3
@@ -2,11 +2,18 @@
|
||||
# Cryptographic API
|
||||
#
|
||||
|
||||
proc-crypto-$(CONFIG_PROC_FS) = proc.o
|
||||
obj-$(CONFIG_CRYPTO) += api.o scatterwalk.o cipher.o digest.o compress.o
|
||||
|
||||
obj-$(CONFIG_CRYPTO) += api.o scatterwalk.o cipher.o digest.o compress.o \
|
||||
$(proc-crypto-y)
|
||||
crypto_algapi-$(CONFIG_PROC_FS) += proc.o
|
||||
crypto_algapi-objs := algapi.o $(crypto_algapi-y)
|
||||
obj-$(CONFIG_CRYPTO_ALGAPI) += crypto_algapi.o
|
||||
|
||||
obj-$(CONFIG_CRYPTO_BLKCIPHER) += blkcipher.o
|
||||
|
||||
crypto_hash-objs := hash.o
|
||||
obj-$(CONFIG_CRYPTO_HASH) += crypto_hash.o
|
||||
|
||||
obj-$(CONFIG_CRYPTO_MANAGER) += cryptomgr.o
|
||||
obj-$(CONFIG_CRYPTO_HMAC) += hmac.o
|
||||
obj-$(CONFIG_CRYPTO_NULL) += crypto_null.o
|
||||
obj-$(CONFIG_CRYPTO_MD4) += md4.o
|
||||
@@ -16,9 +23,12 @@ obj-$(CONFIG_CRYPTO_SHA256) += sha256.o
|
||||
obj-$(CONFIG_CRYPTO_SHA512) += sha512.o
|
||||
obj-$(CONFIG_CRYPTO_WP512) += wp512.o
|
||||
obj-$(CONFIG_CRYPTO_TGR192) += tgr192.o
|
||||
obj-$(CONFIG_CRYPTO_ECB) += ecb.o
|
||||
obj-$(CONFIG_CRYPTO_CBC) += cbc.o
|
||||
obj-$(CONFIG_CRYPTO_DES) += des.o
|
||||
obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish.o
|
||||
obj-$(CONFIG_CRYPTO_TWOFISH) += twofish.o
|
||||
obj-$(CONFIG_CRYPTO_TWOFISH_COMMON) += twofish_common.o
|
||||
obj-$(CONFIG_CRYPTO_SERPENT) += serpent.o
|
||||
obj-$(CONFIG_CRYPTO_AES) += aes.o
|
||||
obj-$(CONFIG_CRYPTO_CAST5) += cast5.o
|
||||
|
||||
+3
-2
@@ -249,13 +249,14 @@ gen_tabs (void)
|
||||
}
|
||||
|
||||
static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
|
||||
unsigned int key_len, u32 *flags)
|
||||
unsigned int key_len)
|
||||
{
|
||||
struct aes_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
const __le32 *key = (const __le32 *)in_key;
|
||||
u32 *flags = &tfm->crt_flags;
|
||||
u32 i, t, u, v, w;
|
||||
|
||||
if (key_len != 16 && key_len != 24 && key_len != 32) {
|
||||
if (key_len % 8) {
|
||||
*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
+486
@@ -0,0 +1,486 @@
|
||||
/*
|
||||
* Cryptographic API for algorithms (i.e., low-level API).
|
||||
*
|
||||
* Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.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/err.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
static LIST_HEAD(crypto_template_list);
|
||||
|
||||
void crypto_larval_error(const char *name, u32 type, u32 mask)
|
||||
{
|
||||
struct crypto_alg *alg;
|
||||
|
||||
down_read(&crypto_alg_sem);
|
||||
alg = __crypto_alg_lookup(name, type, mask);
|
||||
up_read(&crypto_alg_sem);
|
||||
|
||||
if (alg) {
|
||||
if (crypto_is_larval(alg)) {
|
||||
struct crypto_larval *larval = (void *)alg;
|
||||
complete(&larval->completion);
|
||||
}
|
||||
crypto_mod_put(alg);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_larval_error);
|
||||
|
||||
static inline int crypto_set_driver_name(struct crypto_alg *alg)
|
||||
{
|
||||
static const char suffix[] = "-generic";
|
||||
char *driver_name = alg->cra_driver_name;
|
||||
int len;
|
||||
|
||||
if (*driver_name)
|
||||
return 0;
|
||||
|
||||
len = strlcpy(driver_name, alg->cra_name, CRYPTO_MAX_ALG_NAME);
|
||||
if (len + sizeof(suffix) > CRYPTO_MAX_ALG_NAME)
|
||||
return -ENAMETOOLONG;
|
||||
|
||||
memcpy(driver_name + len, suffix, sizeof(suffix));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int crypto_check_alg(struct crypto_alg *alg)
|
||||
{
|
||||
if (alg->cra_alignmask & (alg->cra_alignmask + 1))
|
||||
return -EINVAL;
|
||||
|
||||
if (alg->cra_alignmask & alg->cra_blocksize)
|
||||
return -EINVAL;
|
||||
|
||||
if (alg->cra_blocksize > PAGE_SIZE / 8)
|
||||
return -EINVAL;
|
||||
|
||||
if (alg->cra_priority < 0)
|
||||
return -EINVAL;
|
||||
|
||||
return crypto_set_driver_name(alg);
|
||||
}
|
||||
|
||||
static void crypto_destroy_instance(struct crypto_alg *alg)
|
||||
{
|
||||
struct crypto_instance *inst = (void *)alg;
|
||||
struct crypto_template *tmpl = inst->tmpl;
|
||||
|
||||
tmpl->free(inst);
|
||||
crypto_tmpl_put(tmpl);
|
||||
}
|
||||
|
||||
static void crypto_remove_spawns(struct list_head *spawns,
|
||||
struct list_head *list)
|
||||
{
|
||||
struct crypto_spawn *spawn, *n;
|
||||
|
||||
list_for_each_entry_safe(spawn, n, spawns, list) {
|
||||
struct crypto_instance *inst = spawn->inst;
|
||||
struct crypto_template *tmpl = inst->tmpl;
|
||||
|
||||
list_del_init(&spawn->list);
|
||||
spawn->alg = NULL;
|
||||
|
||||
if (crypto_is_dead(&inst->alg))
|
||||
continue;
|
||||
|
||||
inst->alg.cra_flags |= CRYPTO_ALG_DEAD;
|
||||
if (!tmpl || !crypto_tmpl_get(tmpl))
|
||||
continue;
|
||||
|
||||
crypto_notify(CRYPTO_MSG_ALG_UNREGISTER, &inst->alg);
|
||||
list_move(&inst->alg.cra_list, list);
|
||||
hlist_del(&inst->list);
|
||||
inst->alg.cra_destroy = crypto_destroy_instance;
|
||||
|
||||
if (!list_empty(&inst->alg.cra_users)) {
|
||||
if (&n->list == spawns)
|
||||
n = list_entry(inst->alg.cra_users.next,
|
||||
typeof(*n), list);
|
||||
__list_splice(&inst->alg.cra_users, spawns->prev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int __crypto_register_alg(struct crypto_alg *alg,
|
||||
struct list_head *list)
|
||||
{
|
||||
struct crypto_alg *q;
|
||||
int ret = -EAGAIN;
|
||||
|
||||
if (crypto_is_dead(alg))
|
||||
goto out;
|
||||
|
||||
INIT_LIST_HEAD(&alg->cra_users);
|
||||
|
||||
ret = -EEXIST;
|
||||
|
||||
atomic_set(&alg->cra_refcnt, 1);
|
||||
list_for_each_entry(q, &crypto_alg_list, cra_list) {
|
||||
if (q == alg)
|
||||
goto out;
|
||||
|
||||
if (crypto_is_moribund(q))
|
||||
continue;
|
||||
|
||||
if (crypto_is_larval(q)) {
|
||||
struct crypto_larval *larval = (void *)q;
|
||||
|
||||
if (strcmp(alg->cra_name, q->cra_name) &&
|
||||
strcmp(alg->cra_driver_name, q->cra_name))
|
||||
continue;
|
||||
|
||||
if (larval->adult)
|
||||
continue;
|
||||
if ((q->cra_flags ^ alg->cra_flags) & larval->mask)
|
||||
continue;
|
||||
if (!crypto_mod_get(alg))
|
||||
continue;
|
||||
|
||||
larval->adult = alg;
|
||||
complete(&larval->completion);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(alg->cra_name, q->cra_name))
|
||||
continue;
|
||||
|
||||
if (strcmp(alg->cra_driver_name, q->cra_driver_name) &&
|
||||
q->cra_priority > alg->cra_priority)
|
||||
continue;
|
||||
|
||||
crypto_remove_spawns(&q->cra_users, list);
|
||||
}
|
||||
|
||||
list_add(&alg->cra_list, &crypto_alg_list);
|
||||
|
||||
crypto_notify(CRYPTO_MSG_ALG_REGISTER, alg);
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void crypto_remove_final(struct list_head *list)
|
||||
{
|
||||
struct crypto_alg *alg;
|
||||
struct crypto_alg *n;
|
||||
|
||||
list_for_each_entry_safe(alg, n, list, cra_list) {
|
||||
list_del_init(&alg->cra_list);
|
||||
crypto_alg_put(alg);
|
||||
}
|
||||
}
|
||||
|
||||
int crypto_register_alg(struct crypto_alg *alg)
|
||||
{
|
||||
LIST_HEAD(list);
|
||||
int err;
|
||||
|
||||
err = crypto_check_alg(alg);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
down_write(&crypto_alg_sem);
|
||||
err = __crypto_register_alg(alg, &list);
|
||||
up_write(&crypto_alg_sem);
|
||||
|
||||
crypto_remove_final(&list);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_register_alg);
|
||||
|
||||
static int crypto_remove_alg(struct crypto_alg *alg, struct list_head *list)
|
||||
{
|
||||
if (unlikely(list_empty(&alg->cra_list)))
|
||||
return -ENOENT;
|
||||
|
||||
alg->cra_flags |= CRYPTO_ALG_DEAD;
|
||||
|
||||
crypto_notify(CRYPTO_MSG_ALG_UNREGISTER, alg);
|
||||
list_del_init(&alg->cra_list);
|
||||
crypto_remove_spawns(&alg->cra_users, list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypto_unregister_alg(struct crypto_alg *alg)
|
||||
{
|
||||
int ret;
|
||||
LIST_HEAD(list);
|
||||
|
||||
down_write(&crypto_alg_sem);
|
||||
ret = crypto_remove_alg(alg, &list);
|
||||
up_write(&crypto_alg_sem);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
BUG_ON(atomic_read(&alg->cra_refcnt) != 1);
|
||||
if (alg->cra_destroy)
|
||||
alg->cra_destroy(alg);
|
||||
|
||||
crypto_remove_final(&list);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_unregister_alg);
|
||||
|
||||
int crypto_register_template(struct crypto_template *tmpl)
|
||||
{
|
||||
struct crypto_template *q;
|
||||
int err = -EEXIST;
|
||||
|
||||
down_write(&crypto_alg_sem);
|
||||
|
||||
list_for_each_entry(q, &crypto_template_list, list) {
|
||||
if (q == tmpl)
|
||||
goto out;
|
||||
}
|
||||
|
||||
list_add(&tmpl->list, &crypto_template_list);
|
||||
crypto_notify(CRYPTO_MSG_TMPL_REGISTER, tmpl);
|
||||
err = 0;
|
||||
out:
|
||||
up_write(&crypto_alg_sem);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_register_template);
|
||||
|
||||
void crypto_unregister_template(struct crypto_template *tmpl)
|
||||
{
|
||||
struct crypto_instance *inst;
|
||||
struct hlist_node *p, *n;
|
||||
struct hlist_head *list;
|
||||
LIST_HEAD(users);
|
||||
|
||||
down_write(&crypto_alg_sem);
|
||||
|
||||
BUG_ON(list_empty(&tmpl->list));
|
||||
list_del_init(&tmpl->list);
|
||||
|
||||
list = &tmpl->instances;
|
||||
hlist_for_each_entry(inst, p, list, list) {
|
||||
int err = crypto_remove_alg(&inst->alg, &users);
|
||||
BUG_ON(err);
|
||||
}
|
||||
|
||||
crypto_notify(CRYPTO_MSG_TMPL_UNREGISTER, tmpl);
|
||||
|
||||
up_write(&crypto_alg_sem);
|
||||
|
||||
hlist_for_each_entry_safe(inst, p, n, list, list) {
|
||||
BUG_ON(atomic_read(&inst->alg.cra_refcnt) != 1);
|
||||
tmpl->free(inst);
|
||||
}
|
||||
crypto_remove_final(&users);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_unregister_template);
|
||||
|
||||
static struct crypto_template *__crypto_lookup_template(const char *name)
|
||||
{
|
||||
struct crypto_template *q, *tmpl = NULL;
|
||||
|
||||
down_read(&crypto_alg_sem);
|
||||
list_for_each_entry(q, &crypto_template_list, list) {
|
||||
if (strcmp(q->name, name))
|
||||
continue;
|
||||
if (unlikely(!crypto_tmpl_get(q)))
|
||||
continue;
|
||||
|
||||
tmpl = q;
|
||||
break;
|
||||
}
|
||||
up_read(&crypto_alg_sem);
|
||||
|
||||
return tmpl;
|
||||
}
|
||||
|
||||
struct crypto_template *crypto_lookup_template(const char *name)
|
||||
{
|
||||
return try_then_request_module(__crypto_lookup_template(name), name);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_lookup_template);
|
||||
|
||||
int crypto_register_instance(struct crypto_template *tmpl,
|
||||
struct crypto_instance *inst)
|
||||
{
|
||||
LIST_HEAD(list);
|
||||
int err = -EINVAL;
|
||||
|
||||
if (inst->alg.cra_destroy)
|
||||
goto err;
|
||||
|
||||
err = crypto_check_alg(&inst->alg);
|
||||
if (err)
|
||||
goto err;
|
||||
|
||||
inst->alg.cra_module = tmpl->module;
|
||||
|
||||
down_write(&crypto_alg_sem);
|
||||
|
||||
err = __crypto_register_alg(&inst->alg, &list);
|
||||
if (err)
|
||||
goto unlock;
|
||||
|
||||
hlist_add_head(&inst->list, &tmpl->instances);
|
||||
inst->tmpl = tmpl;
|
||||
|
||||
unlock:
|
||||
up_write(&crypto_alg_sem);
|
||||
|
||||
crypto_remove_final(&list);
|
||||
|
||||
err:
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_register_instance);
|
||||
|
||||
int crypto_init_spawn(struct crypto_spawn *spawn, struct crypto_alg *alg,
|
||||
struct crypto_instance *inst)
|
||||
{
|
||||
int err = -EAGAIN;
|
||||
|
||||
spawn->inst = inst;
|
||||
|
||||
down_write(&crypto_alg_sem);
|
||||
if (!crypto_is_moribund(alg)) {
|
||||
list_add(&spawn->list, &alg->cra_users);
|
||||
spawn->alg = alg;
|
||||
err = 0;
|
||||
}
|
||||
up_write(&crypto_alg_sem);
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_init_spawn);
|
||||
|
||||
void crypto_drop_spawn(struct crypto_spawn *spawn)
|
||||
{
|
||||
down_write(&crypto_alg_sem);
|
||||
list_del(&spawn->list);
|
||||
up_write(&crypto_alg_sem);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_drop_spawn);
|
||||
|
||||
struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn)
|
||||
{
|
||||
struct crypto_alg *alg;
|
||||
struct crypto_alg *alg2;
|
||||
struct crypto_tfm *tfm;
|
||||
|
||||
down_read(&crypto_alg_sem);
|
||||
alg = spawn->alg;
|
||||
alg2 = alg;
|
||||
if (alg2)
|
||||
alg2 = crypto_mod_get(alg2);
|
||||
up_read(&crypto_alg_sem);
|
||||
|
||||
if (!alg2) {
|
||||
if (alg)
|
||||
crypto_shoot_alg(alg);
|
||||
return ERR_PTR(-EAGAIN);
|
||||
}
|
||||
|
||||
tfm = __crypto_alloc_tfm(alg, 0);
|
||||
if (IS_ERR(tfm))
|
||||
crypto_mod_put(alg);
|
||||
|
||||
return tfm;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_spawn_tfm);
|
||||
|
||||
int crypto_register_notifier(struct notifier_block *nb)
|
||||
{
|
||||
return blocking_notifier_chain_register(&crypto_chain, nb);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_register_notifier);
|
||||
|
||||
int crypto_unregister_notifier(struct notifier_block *nb)
|
||||
{
|
||||
return blocking_notifier_chain_unregister(&crypto_chain, nb);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_unregister_notifier);
|
||||
|
||||
struct crypto_alg *crypto_get_attr_alg(void *param, unsigned int len,
|
||||
u32 type, u32 mask)
|
||||
{
|
||||
struct rtattr *rta = param;
|
||||
struct crypto_attr_alg *alga;
|
||||
|
||||
if (!RTA_OK(rta, len))
|
||||
return ERR_PTR(-EBADR);
|
||||
if (rta->rta_type != CRYPTOA_ALG || RTA_PAYLOAD(rta) < sizeof(*alga))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
alga = RTA_DATA(rta);
|
||||
alga->name[CRYPTO_MAX_ALG_NAME - 1] = 0;
|
||||
|
||||
return crypto_alg_mod_lookup(alga->name, type, mask);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_get_attr_alg);
|
||||
|
||||
struct crypto_instance *crypto_alloc_instance(const char *name,
|
||||
struct crypto_alg *alg)
|
||||
{
|
||||
struct crypto_instance *inst;
|
||||
struct crypto_spawn *spawn;
|
||||
int err;
|
||||
|
||||
inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
|
||||
if (!inst)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
err = -ENAMETOOLONG;
|
||||
if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME, "%s(%s)", name,
|
||||
alg->cra_name) >= CRYPTO_MAX_ALG_NAME)
|
||||
goto err_free_inst;
|
||||
|
||||
if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s(%s)",
|
||||
name, alg->cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
|
||||
goto err_free_inst;
|
||||
|
||||
spawn = crypto_instance_ctx(inst);
|
||||
err = crypto_init_spawn(spawn, alg, inst);
|
||||
|
||||
if (err)
|
||||
goto err_free_inst;
|
||||
|
||||
return inst;
|
||||
|
||||
err_free_inst:
|
||||
kfree(inst);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(crypto_alloc_instance);
|
||||
|
||||
static int __init crypto_algapi_init(void)
|
||||
{
|
||||
crypto_init_proc();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit crypto_algapi_exit(void)
|
||||
{
|
||||
crypto_exit_proc();
|
||||
}
|
||||
|
||||
module_init(crypto_algapi_init);
|
||||
module_exit(crypto_algapi_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Cryptographic algorithms API");
|
||||
+2
-1
@@ -461,10 +461,11 @@ static const u32 rc[] = {
|
||||
};
|
||||
|
||||
static int anubis_setkey(struct crypto_tfm *tfm, const u8 *in_key,
|
||||
unsigned int key_len, u32 *flags)
|
||||
unsigned int key_len)
|
||||
{
|
||||
struct anubis_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
const __be32 *key = (const __be32 *)in_key;
|
||||
u32 *flags = &tfm->crt_flags;
|
||||
int N, R, i, r;
|
||||
u32 kappa[ANUBIS_MAX_N];
|
||||
u32 inter[ANUBIS_MAX_N];
|
||||
|
||||
+303
-133
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user