提交 f049274b 编写于 作者: L Linus Torvalds

Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6

* master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6: (79 commits)
  [IPX]: Fix NULL pointer dereference on ipx unload
  [ATM]: atmarp.h needs to always include linux/types.h
  [NET]: Fix net/socket.c warnings.
  [NET]: cleanup sock_from_file()
  [NET]: change layout of ehash table
  [S390]: Add AF_IUCV socket support
  [S390]: Adapt special message interface to new IUCV API
  [S390]: Adapt netiucv driver to new IUCV API
  [S390]: Adapt vmlogrdr driver to new IUCV API
  [S390]: Adapt monreader driver to new IUCV API
  [S390]: Rewrite of the IUCV base code, part 2
  [S390]: Rewrite of the IUCV base code, part 1
  [X.25]: Adds /proc/net/x25/forward to view active forwarded calls.
  [X.25]: Adds /proc/sys/net/x25/x25_forward to control forwarding.
  [X.25]: Add call forwarding
  [XFRM]: xfrm_migrate() needs exporting to modules.
  [PFKEYV2]: CONFIG_NET_KEY_MIGRATE option
  [PFKEYV2]: Extension for dynamic update of endpoint address(es)
  [XFRM]: CONFIG_XFRM_MIGRATE option
  [XFRM]: User interface for handling XFRM_MSG_MIGRATE
  ...
......@@ -193,6 +193,7 @@ Original developers of the crypto algorithms:
Kartikey Mahendra Bhatt (CAST6)
Jon Oberheide (ARC4)
Jouni Malinen (Michael MIC)
NTT(Nippon Telegraph and Telephone Corporation) (Camellia)
SHA1 algorithm contributors:
Jean-Francois Dive
......@@ -246,6 +247,9 @@ Tiger algorithm contributors:
VIA PadLock contributors:
Michal Ludvig
Camellia algorithm contributors:
NTT(Nippon Telegraph and Telephone Corporation) (Camellia)
Generic scatterwalk code by Adam J. Richter <adam@yggdrasil.com>
Please send any credits updates or corrections to:
......
......@@ -179,6 +179,8 @@ CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
# CONFIG_XFRM_SUB_POLICY is not set
CONFIG_NET_KEY=y
CONFIG_IUCV=m
CONFIG_AFIUCV=m
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
# CONFIG_IP_ADVANCED_ROUTER is not set
......@@ -508,7 +510,6 @@ CONFIG_NET_ETHERNET=y
#
CONFIG_LCS=m
CONFIG_CTC=m
CONFIG_IUCV=m
# CONFIG_NETIUCV is not set
# CONFIG_SMSGIUCV is not set
# CONFIG_CLAW is not set
......
......@@ -149,6 +149,15 @@ config CRYPTO_CBC
CBC: Cipher Block Chaining mode
This block cipher algorithm is required for IPSec.
config CRYPTO_PCBC
tristate "PCBC support"
select CRYPTO_BLKCIPHER
select CRYPTO_MANAGER
default m
help
PCBC: Propagating Cipher Block Chaining mode
This block cipher algorithm is required for RxRPC.
config CRYPTO_LRW
tristate "LRW support (EXPERIMENTAL)"
depends on EXPERIMENTAL
......@@ -168,6 +177,13 @@ config CRYPTO_DES
help
DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3).
config CRYPTO_FCRYPT
tristate "FCrypt cipher algorithm"
select CRYPTO_ALGAPI
select CRYPTO_BLKCIPHER
help
FCrypt algorithm used by RxRPC.
config CRYPTO_BLOWFISH
tristate "Blowfish cipher algorithm"
select CRYPTO_ALGAPI
......@@ -409,6 +425,21 @@ config CRYPTO_CRC32C
See Castagnoli93. This implementation uses lib/libcrc32c.
Module will be crc32c.
config CRYPTO_CAMELLIA
tristate "Camellia cipher algorithms"
depends on CRYPTO
select CRYPTO_ALGAPI
help
Camellia cipher algorithms module.
Camellia is a symmetric key block cipher developed jointly
at NTT and Mitsubishi Electric Corporation.
The Camellia specifies three key sizes: 128, 192 and 256 bits.
See also:
<https://info.isl.ntt.co.jp/crypt/eng/camellia/index_s.html>
config CRYPTO_TEST
tristate "Testing module"
depends on m
......
......@@ -27,13 +27,16 @@ obj-$(CONFIG_CRYPTO_TGR192) += tgr192.o
obj-$(CONFIG_CRYPTO_GF128MUL) += gf128mul.o
obj-$(CONFIG_CRYPTO_ECB) += ecb.o
obj-$(CONFIG_CRYPTO_CBC) += cbc.o
obj-$(CONFIG_CRYPTO_PCBC) += pcbc.o
obj-$(CONFIG_CRYPTO_LRW) += lrw.o
obj-$(CONFIG_CRYPTO_DES) += des.o
obj-$(CONFIG_CRYPTO_FCRYPT) += fcrypt.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_CAMELLIA) += camellia.o
obj-$(CONFIG_CRYPTO_CAST5) += cast5.o
obj-$(CONFIG_CRYPTO_CAST6) += cast6.o
obj-$(CONFIG_CRYPTO_ARC4) += arc4.o
......
......@@ -377,7 +377,8 @@ void crypto_drop_spawn(struct crypto_spawn *spawn)
}
EXPORT_SYMBOL_GPL(crypto_drop_spawn);
struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn)
struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn, u32 type,
u32 mask)
{
struct crypto_alg *alg;
struct crypto_alg *alg2;
......@@ -396,10 +397,18 @@ struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn)
return ERR_PTR(-EAGAIN);
}
tfm = __crypto_alloc_tfm(alg, 0);
tfm = ERR_PTR(-EINVAL);
if (unlikely((alg->cra_flags ^ type) & mask))
goto out_put_alg;
tfm = __crypto_alloc_tfm(alg, type, mask);
if (IS_ERR(tfm))
crypto_mod_put(alg);
goto out_put_alg;
return tfm;
out_put_alg:
crypto_mod_put(alg);
return tfm;
}
EXPORT_SYMBOL_GPL(crypto_spawn_tfm);
......
......@@ -212,31 +212,12 @@ struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask)
}
EXPORT_SYMBOL_GPL(crypto_alg_mod_lookup);
static int crypto_init_flags(struct crypto_tfm *tfm, u32 flags)
static int crypto_init_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
{
tfm->crt_flags = flags & CRYPTO_TFM_REQ_MASK;
flags &= ~CRYPTO_TFM_REQ_MASK;
switch (crypto_tfm_alg_type(tfm)) {
case CRYPTO_ALG_TYPE_CIPHER:
return crypto_init_cipher_flags(tfm, flags);
case CRYPTO_ALG_TYPE_DIGEST:
return crypto_init_digest_flags(tfm, flags);
case CRYPTO_ALG_TYPE_COMPRESS:
return crypto_init_compress_flags(tfm, flags);
}
return 0;
}
const struct crypto_type *type_obj = tfm->__crt_alg->cra_type;
static int crypto_init_ops(struct crypto_tfm *tfm)
{
const struct crypto_type *type = tfm->__crt_alg->cra_type;
if (type)
return type->init(tfm);
if (type_obj)
return type_obj->init(tfm, type, mask);
switch (crypto_tfm_alg_type(tfm)) {
case CRYPTO_ALG_TYPE_CIPHER:
......@@ -285,29 +266,29 @@ static void crypto_exit_ops(struct crypto_tfm *tfm)
}
}
static unsigned int crypto_ctxsize(struct crypto_alg *alg, int flags)
static unsigned int crypto_ctxsize(struct crypto_alg *alg, u32 type, u32 mask)
{
const struct crypto_type *type = alg->cra_type;
const struct crypto_type *type_obj = alg->cra_type;
unsigned int len;
len = alg->cra_alignmask & ~(crypto_tfm_ctx_alignment() - 1);
if (type)
return len + type->ctxsize(alg);
if (type_obj)
return len + type_obj->ctxsize(alg, type, mask);
switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) {
default:
BUG();
case CRYPTO_ALG_TYPE_CIPHER:
len += crypto_cipher_ctxsize(alg, flags);
len += crypto_cipher_ctxsize(alg);
break;
case CRYPTO_ALG_TYPE_DIGEST:
len += crypto_digest_ctxsize(alg, flags);
len += crypto_digest_ctxsize(alg);
break;
case CRYPTO_ALG_TYPE_COMPRESS:
len += crypto_compress_ctxsize(alg, flags);
len += crypto_compress_ctxsize(alg);
break;
}
......@@ -322,24 +303,21 @@ void crypto_shoot_alg(struct crypto_alg *alg)
}
EXPORT_SYMBOL_GPL(crypto_shoot_alg);
struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 flags)
struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type,
u32 mask)
{
struct crypto_tfm *tfm = NULL;
unsigned int tfm_size;
int err = -ENOMEM;
tfm_size = sizeof(*tfm) + crypto_ctxsize(alg, flags);
tfm_size = sizeof(*tfm) + crypto_ctxsize(alg, type, mask);
tfm = kzalloc(tfm_size, GFP_KERNEL);
if (tfm == NULL)
goto out_err;
tfm->__crt_alg = alg;
err = crypto_init_flags(tfm, flags);
if (err)
goto out_free_tfm;
err = crypto_init_ops(tfm);
err = crypto_init_ops(tfm, type, mask);
if (err)
goto out_free_tfm;
......@@ -362,31 +340,6 @@ struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 flags)
}
EXPORT_SYMBOL_GPL(__crypto_alloc_tfm);
struct crypto_tfm *crypto_alloc_tfm(const char *name, u32 flags)
{
struct crypto_tfm *tfm = NULL;
int err;
do {
struct crypto_alg *alg;
alg = crypto_alg_mod_lookup(name, 0, CRYPTO_ALG_ASYNC);
err = PTR_ERR(alg);
if (IS_ERR(alg))
continue;
tfm = __crypto_alloc_tfm(alg, flags);
err = 0;
if (IS_ERR(tfm)) {
crypto_mod_put(alg);
err = PTR_ERR(tfm);
tfm = NULL;
}
} while (err == -EAGAIN && !signal_pending(current));
return tfm;
}
/*
* crypto_alloc_base - Locate algorithm and allocate transform
* @alg_name: Name of algorithm
......@@ -420,7 +373,7 @@ struct crypto_tfm *crypto_alloc_base(const char *alg_name, u32 type, u32 mask)
goto err;
}
tfm = __crypto_alloc_tfm(alg, 0);
tfm = __crypto_alloc_tfm(alg, type, mask);
if (!IS_ERR(tfm))
return tfm;
......@@ -466,7 +419,6 @@ void crypto_free_tfm(struct crypto_tfm *tfm)
kfree(tfm);
}
EXPORT_SYMBOL_GPL(crypto_alloc_tfm);
EXPORT_SYMBOL_GPL(crypto_free_tfm);
int crypto_has_alg(const char *name, u32 type, u32 mask)
......
......@@ -16,6 +16,7 @@
#include <linux/crypto.h>
#include <linux/errno.h>
#include <linux/hardirq.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/scatterlist.h>
......@@ -313,6 +314,9 @@ static int blkcipher_walk_first(struct blkcipher_desc *desc,
struct crypto_blkcipher *tfm = desc->tfm;
unsigned int alignmask = crypto_blkcipher_alignmask(tfm);
if (WARN_ON_ONCE(in_irq()))
return -EDEADLK;
walk->nbytes = walk->total;
if (unlikely(!walk->total))
return 0;
......@@ -345,7 +349,8 @@ static int setkey(struct crypto_tfm *tfm, const u8 *key,
return cipher->setkey(tfm, key, keylen);
}
static unsigned int crypto_blkcipher_ctxsize(struct crypto_alg *alg)
static unsigned int crypto_blkcipher_ctxsize(struct crypto_alg *alg, u32 type,
u32 mask)
{
struct blkcipher_alg *cipher = &alg->cra_blkcipher;
unsigned int len = alg->cra_ctxsize;
......@@ -358,7 +363,7 @@ static unsigned int crypto_blkcipher_ctxsize(struct crypto_alg *alg)
return len;
}
static int crypto_init_blkcipher_ops(struct crypto_tfm *tfm)
static int crypto_init_blkcipher_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
{
struct blkcipher_tfm *crt = &tfm->crt_blkcipher;
struct blkcipher_alg *alg = &tfm->__crt_alg->cra_blkcipher;
......
此差异已折叠。
......@@ -243,6 +243,7 @@ static int crypto_cbc_init_tfm(struct crypto_tfm *tfm)
struct crypto_instance *inst = (void *)tfm->__crt_alg;
struct crypto_spawn *spawn = crypto_instance_ctx(inst);
struct crypto_cbc_ctx *ctx = crypto_tfm_ctx(tfm);
struct crypto_cipher *cipher;
switch (crypto_tfm_alg_blocksize(tfm)) {
case 8:
......@@ -260,11 +261,11 @@ static int crypto_cbc_init_tfm(struct crypto_tfm *tfm)
ctx->xor = xor_quad;
}
tfm = crypto_spawn_tfm(spawn);
if (IS_ERR(tfm))
return PTR_ERR(tfm);
cipher = crypto_spawn_cipher(spawn);
if (IS_ERR(cipher))
return PTR_ERR(cipher);
ctx->child = crypto_cipher_cast(tfm);
ctx->child = cipher;
return 0;
}
......
......@@ -12,274 +12,13 @@
* any later version.
*
*/
#include <linux/compiler.h>
#include <linux/kernel.h>
#include <linux/crypto.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/scatterlist.h>
#include <linux/string.h>
#include <asm/scatterlist.h>
#include "internal.h"
#include "scatterwalk.h"
struct cipher_alg_compat {
unsigned int cia_min_keysize;
unsigned int cia_max_keysize;
int (*cia_setkey)(struct crypto_tfm *tfm, const u8 *key,
unsigned int keylen);
void (*cia_encrypt)(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
void (*cia_decrypt)(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
unsigned int (*cia_encrypt_ecb)(const struct cipher_desc *desc,
u8 *dst, const u8 *src,
unsigned int nbytes);
unsigned int (*cia_decrypt_ecb)(const struct cipher_desc *desc,
u8 *dst, const u8 *src,
unsigned int nbytes);
unsigned int (*cia_encrypt_cbc)(const struct cipher_desc *desc,
u8 *dst, const u8 *src,
unsigned int nbytes);
unsigned int (*cia_decrypt_cbc)(const struct cipher_desc *desc,
u8 *dst, const u8 *src,
unsigned int nbytes);
};
static inline void xor_64(u8 *a, const u8 *b)
{
((u32 *)a)[0] ^= ((u32 *)b)[0];
((u32 *)a)[1] ^= ((u32 *)b)[1];
}
static inline void xor_128(u8 *a, const u8 *b)
{
((u32 *)a)[0] ^= ((u32 *)b)[0];
((u32 *)a)[1] ^= ((u32 *)b)[1];
((u32 *)a)[2] ^= ((u32 *)b)[2];
((u32 *)a)[3] ^= ((u32 *)b)[3];
}
static unsigned int crypt_slow(const struct cipher_desc *desc,
struct scatter_walk *in,
struct scatter_walk *out, unsigned int bsize)
{
unsigned long alignmask = crypto_tfm_alg_alignmask(desc->tfm);
u8 buffer[bsize * 2 + alignmask];
u8 *src = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
u8 *dst = src + bsize;
scatterwalk_copychunks(src, in, bsize, 0);
desc->prfn(desc, dst, src, bsize);
scatterwalk_copychunks(dst, out, bsize, 1);
return bsize;
}
static inline unsigned int crypt_fast(const struct cipher_desc *desc,
struct scatter_walk *in,
struct scatter_walk *out,
unsigned int nbytes, u8 *tmp)
{
u8 *src, *dst;
u8 *real_src, *real_dst;
real_src = scatterwalk_map(in, 0);
real_dst = scatterwalk_map(out, 1);
src = real_src;
dst = scatterwalk_samebuf(in, out) ? src : real_dst;
if (tmp) {
memcpy(tmp, src, nbytes);
src = tmp;
dst = tmp;
}
nbytes = desc->prfn(desc, dst, src, nbytes);
if (tmp)
memcpy(real_dst, tmp, nbytes);
scatterwalk_unmap(real_src, 0);
scatterwalk_unmap(real_dst, 1);
scatterwalk_advance(in, nbytes);
scatterwalk_advance(out, nbytes);
return nbytes;
}
/*
* Generic encrypt/decrypt wrapper for ciphers, handles operations across
* multiple page boundaries by using temporary blocks. In user context,
* the kernel is given a chance to schedule us once per page.
*/
static int crypt(const struct cipher_desc *desc,
struct scatterlist *dst,
struct scatterlist *src,
unsigned int nbytes)
{
struct scatter_walk walk_in, walk_out;
struct crypto_tfm *tfm = desc->tfm;
const unsigned int bsize = crypto_tfm_alg_blocksize(tfm);
unsigned int alignmask = crypto_tfm_alg_alignmask(tfm);
unsigned long buffer = 0;
if (!nbytes)
return 0;
if (nbytes % bsize) {
tfm->crt_flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;
return -EINVAL;
}
scatterwalk_start(&walk_in, src);
scatterwalk_start(&walk_out, dst);
for(;;) {
unsigned int n = nbytes;
u8 *tmp = NULL;
if (!scatterwalk_aligned(&walk_in, alignmask) ||
!scatterwalk_aligned(&walk_out, alignmask)) {
if (!buffer) {
buffer = __get_free_page(GFP_ATOMIC);
if (!buffer)
n = 0;
}
tmp = (u8 *)buffer;
}
n = scatterwalk_clamp(&walk_in, n);
n = scatterwalk_clamp(&walk_out, n);
if (likely(n >= bsize))
n = crypt_fast(desc, &walk_in, &walk_out, n, tmp);
else
n = crypt_slow(desc, &walk_in, &walk_out, bsize);
nbytes -= n;
scatterwalk_done(&walk_in, 0, nbytes);
scatterwalk_done(&walk_out, 1, nbytes);
if (!nbytes)
break;
crypto_yield(tfm->crt_flags);
}
if (buffer)
free_page(buffer);
return 0;
}
static int crypt_iv_unaligned(struct cipher_desc *desc,
struct scatterlist *dst,
struct scatterlist *src,
unsigned int nbytes)
{
struct crypto_tfm *tfm = desc->tfm;
unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);
u8 *iv = desc->info;
if (unlikely(((unsigned long)iv & alignmask))) {
unsigned int ivsize = tfm->crt_cipher.cit_ivsize;
u8 buffer[ivsize + alignmask];
u8 *tmp = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
int err;
desc->info = memcpy(tmp, iv, ivsize);
err = crypt(desc, dst, src, nbytes);
memcpy(iv, tmp, ivsize);
return err;
}
return crypt(desc, dst, src, nbytes);
}
static unsigned int cbc_process_encrypt(const struct cipher_desc *desc,
u8 *dst, const u8 *src,
unsigned int nbytes)
{
struct crypto_tfm *tfm = desc->tfm;
void (*xor)(u8 *, const u8 *) = tfm->crt_u.cipher.cit_xor_block;
int bsize = crypto_tfm_alg_blocksize(tfm);
void (*fn)(struct crypto_tfm *, u8 *, const u8 *) = desc->crfn;
u8 *iv = desc->info;
unsigned int done = 0;
nbytes -= bsize;
do {
xor(iv, src);
fn(tfm, dst, iv);
memcpy(iv, dst, bsize);
src += bsize;
dst += bsize;
} while ((done += bsize) <= nbytes);
return done;
}
static unsigned int cbc_process_decrypt(const struct cipher_desc *desc,
u8 *dst, const u8 *src,
unsigned int nbytes)
{
struct crypto_tfm *tfm = desc->tfm;
void (*xor)(u8 *, const u8 *) = tfm->crt_u.cipher.cit_xor_block;
int bsize = crypto_tfm_alg_blocksize(tfm);
unsigned long alignmask = crypto_tfm_alg_alignmask(desc->tfm);
u8 stack[src == dst ? bsize + alignmask : 0];
u8 *buf = (u8 *)ALIGN((unsigned long)stack, alignmask + 1);
u8 **dst_p = src == dst ? &buf : &dst;
void (*fn)(struct crypto_tfm *, u8 *, const u8 *) = desc->crfn;
u8 *iv = desc->info;
unsigned int done = 0;
nbytes -= bsize;
do {
u8 *tmp_dst = *dst_p;
fn(tfm, tmp_dst, src);
xor(tmp_dst, iv);
memcpy(iv, src, bsize);
if (tmp_dst != dst)
memcpy(dst, tmp_dst, bsize);
src += bsize;
dst += bsize;
} while ((done += bsize) <= nbytes);
return done;
}
static unsigned int ecb_process(const struct cipher_desc *desc, u8 *dst,
const u8 *src, unsigned int nbytes)
{
struct crypto_tfm *tfm = desc->tfm;
int bsize = crypto_tfm_alg_blocksize(tfm);
void (*fn)(struct crypto_tfm *, u8 *, const u8 *) = desc->crfn;
unsigned int done = 0;
nbytes -= bsize;
do {
fn(tfm, dst, src);
src += bsize;
dst += bsize;
} while ((done += bsize) <= nbytes);
return done;
}
static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
{
......@@ -293,122 +32,6 @@ static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
return cia->cia_setkey(tfm, key, keylen);
}
static int ecb_encrypt(struct crypto_tfm *tfm,
struct scatterlist *dst,
struct scatterlist *src, unsigned int nbytes)
{
struct cipher_desc desc;
struct cipher_alg_compat *cipher = (void *)&tfm->__crt_alg->cra_cipher;
desc.tfm = tfm;
desc.crfn = cipher->cia_encrypt;
desc.prfn = cipher->cia_encrypt_ecb ?: ecb_process;
return crypt(&desc, dst, src, nbytes);
}
static int ecb_decrypt(struct crypto_tfm *tfm,
struct scatterlist *dst,
struct scatterlist *src,
unsigned int nbytes)
{
struct cipher_desc desc;
struct cipher_alg_compat *cipher = (void *)&tfm->__crt_alg->cra_cipher;
desc.tfm = tfm;
desc.crfn = cipher->cia_decrypt;
desc.prfn = cipher->cia_decrypt_ecb ?: ecb_process;
return crypt(&desc, dst, src, nbytes);
}
static int cbc_encrypt(struct crypto_tfm *tfm,
struct scatterlist *dst,
struct scatterlist *src,
unsigned int nbytes)
{
struct cipher_desc desc;
struct cipher_alg_compat *cipher = (void *)&tfm->__crt_alg->cra_cipher;
desc.tfm = tfm;
desc.crfn = cipher->cia_encrypt;
desc.prfn = cipher->cia_encrypt_cbc ?: cbc_process_encrypt;
desc.info = tfm->crt_cipher.cit_iv;
return crypt(&desc, dst, src, nbytes);
}
static int cbc_encrypt_iv(struct crypto_tfm *tfm,
struct scatterlist *dst,
struct scatterlist *src,
unsigned int nbytes, u8 *iv)
{
struct cipher_desc desc;
struct cipher_alg_compat *cipher = (void *)&tfm->__crt_alg->cra_cipher;
desc.tfm = tfm;
desc.crfn = cipher->cia_encrypt;
desc.prfn = cipher->cia_encrypt_cbc ?: cbc_process_encrypt;
desc.info = iv;
return crypt_iv_unaligned(&desc, dst, src, nbytes);
}
static int cbc_decrypt(struct crypto_tfm *tfm,
struct scatterlist *dst,
struct scatterlist *src,
unsigned int nbytes)
{
struct cipher_desc desc;
struct cipher_alg_compat *cipher = (void *)&tfm->__crt_alg->cra_cipher;
desc.tfm = tfm;
desc.crfn = cipher->cia_decrypt;
desc.prfn = cipher->cia_decrypt_cbc ?: cbc_process_decrypt;
desc.info = tfm->crt_cipher.cit_iv;
return crypt(&desc, dst, src, nbytes);
}
static int cbc_decrypt_iv(struct crypto_tfm *tfm,
struct scatterlist *dst,
struct scatterlist *src,
unsigned int nbytes, u8 *iv)
{
struct cipher_desc desc;
struct cipher_alg_compat *cipher = (void *)&tfm->__crt_alg->cra_cipher;
desc.tfm = tfm;
desc.crfn = cipher->cia_decrypt;
desc.prfn = cipher->cia_decrypt_cbc ?: cbc_process_decrypt;
desc.info = iv;
return crypt_iv_unaligned(&desc, dst, src, nbytes);
}
static int nocrypt(struct crypto_tfm *tfm,
struct scatterlist *dst,
struct scatterlist *src,
unsigned int nbytes)
{
return -ENOSYS;
}
static int nocrypt_iv(struct crypto_tfm *tfm,
struct scatterlist *dst,
struct scatterlist *src,
unsigned int nbytes, u8 *iv)
{
return -ENOSYS;
}
int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags)
{
u32 mode = flags & CRYPTO_TFM_MODE_MASK;
tfm->crt_cipher.cit_mode = mode ? mode : CRYPTO_TFM_MODE_ECB;
return 0;
}
static void cipher_crypt_unaligned(void (*fn)(struct crypto_tfm *, u8 *,
const u8 *),
struct crypto_tfm *tfm,
......@@ -454,7 +77,6 @@ static void cipher_decrypt_unaligned(struct crypto_tfm *tfm,
int crypto_init_cipher_ops(struct crypto_tfm *tfm)
{
int ret = 0;
struct cipher_tfm *ops = &tfm->crt_cipher;
struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher;
......@@ -464,70 +86,7 @@ int crypto_init_cipher_ops(struct crypto_tfm *tfm)
ops->cit_decrypt_one = crypto_tfm_alg_alignmask(tfm) ?
cipher_decrypt_unaligned : cipher->cia_decrypt;
switch (tfm->crt_cipher.cit_mode) {
case CRYPTO_TFM_MODE_ECB:
ops->cit_encrypt = ecb_encrypt;
ops->cit_decrypt = ecb_decrypt;
ops->cit_encrypt_iv = nocrypt_iv;
ops->cit_decrypt_iv = nocrypt_iv;
break;
case CRYPTO_TFM_MODE_CBC:
ops->cit_encrypt = cbc_encrypt;
ops->cit_decrypt = cbc_decrypt;
ops->cit_encrypt_iv = cbc_encrypt_iv;
ops->cit_decrypt_iv = cbc_decrypt_iv;
break;
case CRYPTO_TFM_MODE_CFB:
ops->cit_encrypt = nocrypt;
ops->cit_decrypt = nocrypt;
ops->cit_encrypt_iv = nocrypt_iv;
ops->cit_decrypt_iv = nocrypt_iv;
break;
case CRYPTO_TFM_MODE_CTR:
ops->cit_encrypt = nocrypt;
ops->cit_decrypt = nocrypt;
ops->cit_encrypt_iv = nocrypt_iv;
ops->cit_decrypt_iv = nocrypt_iv;
break;
default:
BUG();
}
if (ops->cit_mode == CRYPTO_TFM_MODE_CBC) {
unsigned long align;
unsigned long addr;
switch (crypto_tfm_alg_blocksize(tfm)) {
case 8:
ops->cit_xor_block = xor_64;
break;
case 16:
ops->cit_xor_block = xor_128;
break;
default:
printk(KERN_WARNING "%s: block size %u not supported\n",
crypto_tfm_alg_name(tfm),
crypto_tfm_alg_blocksize(tfm));
ret = -EINVAL;
goto out;
}
ops->cit_ivsize = crypto_tfm_alg_blocksize(tfm);
align = crypto_tfm_alg_alignmask(tfm) + 1;
addr = (unsigned long)crypto_tfm_ctx(tfm);
addr = ALIGN(addr, align);
addr += ALIGN(tfm->__crt_alg->cra_ctxsize, align);
ops->cit_iv = (void *)addr;
}
out:
return ret;
return 0;
}
void crypto_exit_cipher_ops(struct crypto_tfm *tfm)
......
......@@ -34,11 +34,6 @@ static int crypto_decompress(struct crypto_tfm *tfm,
dlen);
}
int crypto_init_compress_flags(struct crypto_tfm *tfm, u32 flags)
{
return flags ? -EINVAL : 0;
}
int crypto_init_compress_ops(struct crypto_tfm *tfm)
{
struct compress_tfm *ops = &tfm->crt_compress;
......
......@@ -14,7 +14,9 @@
#include <linux/mm.h>
#include <linux/errno.h>
#include <linux/hardirq.h>
#include <linux/highmem.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/scatterlist.h>
......@@ -29,8 +31,8 @@ static int init(struct hash_desc *desc)
return 0;
}
static int update(struct hash_desc *desc,
struct scatterlist *sg, unsigned int nbytes)
static int update2(struct hash_desc *desc,
struct scatterlist *sg, unsigned int nbytes)
{
struct crypto_tfm *tfm = crypto_hash_tfm(desc->tfm);
unsigned int alignmask = crypto_tfm_alg_alignmask(tfm);
......@@ -81,6 +83,14 @@ static int update(struct hash_desc *desc,
return 0;
}
static int update(struct hash_desc *desc,
struct scatterlist *sg, unsigned int nbytes)
{
if (WARN_ON_ONCE(in_irq()))
return -EDEADLK;
return update2(desc, sg, nbytes);
}
static int final(struct hash_desc *desc, u8 *out)
{
struct crypto_tfm *tfm = crypto_hash_tfm(desc->tfm);
......@@ -118,16 +128,14 @@ static int setkey(struct crypto_hash *hash, const u8 *key, unsigned int keylen)
static int digest(struct hash_desc *desc,
struct scatterlist *sg, unsigned int nbytes, u8 *out)
{
if (WARN_ON_ONCE(in_irq()))
return -EDEADLK;
init(desc);
update(desc, sg, nbytes);
update2(desc, sg, nbytes);
return final(desc, out);
}
int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags)
{
return flags ? -EINVAL : 0;
}
int crypto_init_digest_ops(struct crypto_tfm *tfm)
{
struct hash_tfm *ops = &tfm->crt_hash;
......
......@@ -99,12 +99,13 @@ static int crypto_ecb_init_tfm(struct crypto_tfm *tfm)
struct crypto_instance *inst = (void *)tfm->__crt_alg;
struct crypto_spawn *spawn = crypto_instance_ctx(inst);
struct crypto_ecb_ctx *ctx = crypto_tfm_ctx(tfm);
struct crypto_cipher *cipher;
tfm = crypto_spawn_tfm(spawn);
if (IS_ERR(tfm))
return PTR_ERR(tfm);
cipher = crypto_spawn_cipher(spawn);
if (IS_ERR(cipher))
return PTR_ERR(cipher);
ctx->child = crypto_cipher_cast(tfm);
ctx->child = cipher;
return 0;
}
......
/* FCrypt encryption algorithm
*
* Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.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.
*
* Based on code:
*
* Copyright (c) 1995 - 2000 Kungliga Tekniska Hgskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <asm/byteorder.h>
#include <linux/bitops.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/crypto.h>
#define ROUNDS 16
struct fcrypt_ctx {
u32 sched[ROUNDS];
};
/* Rotate right two 32 bit numbers as a 56 bit number */
#define ror56(hi, lo, n) \
do { \
u32 t = lo & ((1 << n) - 1); \
lo = (lo >> n) | ((hi & ((1 << n) - 1)) << (32 - n)); \
hi = (hi >> n) | (t << (24-n)); \
} while(0)
/* Rotate right one 64 bit number as a 56 bit number */
#define ror56_64(k, n) \
do { \
k = (k >> n) | ((k & ((1 << n) - 1)) << (56 - n)); \
} while(0)
/*
* Sboxes for Feistel network derived from
* /afs/transarc.com/public/afsps/afs.rel31b.export-src/rxkad/sboxes.h
*/
#undef Z
#define Z(x) __constant_be32_to_cpu(x << 3)
static const u32 sbox0[256] = {
Z(0xea), Z(0x7f), Z(0xb2), Z(0x64), Z(0x9d), Z(0xb0), Z(0xd9), Z(0x11),
Z(0xcd), Z(0x86), Z(0x86), Z(0x91), Z(0x0a), Z(0xb2), Z(0x93), Z(0x06),
Z(0x0e), Z(0x06), Z(0xd2), Z(0x65), Z(0x73), Z(0xc5), Z(0x28), Z(0x60),
Z(0xf2), Z(0x20), Z(0xb5), Z(0x38), Z(0x7e), Z(0xda), Z(0x9f), Z(0xe3),
Z(0xd2), Z(0xcf), Z(0xc4), Z(0x3c), Z(0x61), Z(0xff), Z(0x4a), Z(0x4a),
Z(0x35), Z(0xac), Z(0xaa), Z(0x5f), Z(0x2b), Z(0xbb), Z(0xbc), Z(0x53),
Z(0x4e), Z(0x9d), Z(0x78), Z(0xa3), Z(0xdc), Z(0x09), Z(0x32), Z(0x10),
Z(0xc6), Z(0x6f), Z(0x66), Z(0xd6), Z(0xab), Z(0xa9), Z(0xaf), Z(0xfd),
Z(0x3b), Z(0x95), Z(0xe8), Z(0x34), Z(0x9a), Z(0x81), Z(0x72), Z(0x80),
Z(0x9c), Z(0xf3), Z(0xec), Z(0xda), Z(0x9f), Z(0x26), Z(0x76), Z(0x15),
Z(0x3e), Z(0x55), Z(0x4d), Z(0xde), Z(0x84), Z(0xee), Z(0xad), Z(0xc7),
Z(0xf1), Z(0x6b), Z(0x3d), Z(0xd3), Z(0x04), Z(0x49), Z(0xaa), Z(0x24),
Z(0x0b), Z(0x8a), Z(0x83), Z(0xba), Z(0xfa), Z(0x85), Z(0xa0), Z(0xa8),
Z(0xb1), Z(0xd4), Z(0x01), Z(0xd8), Z(0x70), Z(0x64), Z(0xf0), Z(0x51),
Z(0xd2), Z(0xc3), Z(0xa7), Z(0x75), Z(0x8c), Z(0xa5), Z(0x64), Z(0xef),
Z(0x10), Z(0x4e), Z(0xb7), Z(0xc6), Z(0x61), Z(0x03), Z(0xeb), Z(0x44),
Z(0x3d), Z(0xe5), Z(0xb3), Z(0x5b), Z(0xae), Z(0xd5), Z(0xad), Z(0x1d),
Z(0xfa), Z(0x5a), Z(0x1e), Z(0x33), Z(0xab), Z(0x93), Z(0xa2), Z(0xb7),
Z(0xe7), Z(0xa8), Z(0x45), Z(0xa4), Z(0xcd), Z(0x29), Z(0x63), Z(0x44),
Z(0xb6), Z(0x69), Z(0x7e), Z(0x2e), Z(0x62), Z(0x03), Z(0xc8), Z(0xe0),
Z(0x17), Z(0xbb), Z(0xc7), Z(0xf3), Z(0x3f), Z(0x36), Z(0xba), Z(0x71),
Z(0x8e), Z(0x97), Z(0x65), Z(0x60), Z(0x69), Z(0xb6), Z(0xf6), Z(0xe6),
Z(0x6e), Z(0xe0), Z(0x81), Z(0x59), Z(0xe8), Z(0xaf), Z(0xdd), Z(0x95),
Z(0x22), Z(0x99), Z(0xfd), Z(0x63), Z(0x19), Z(0x74), Z(0x61), Z(0xb1),
Z(0xb6), Z(0x5b), Z(0xae), Z(0x54), Z(0xb3), Z(0x70), Z(0xff), Z(0xc6),
Z(0x3b), Z(0x3e), Z(0xc1), Z(0xd7), Z(0xe1), Z(0x0e), Z(0x76), Z(0xe5),
Z(0x36), Z(0x4f), Z(0x59), Z(0xc7), Z(0x08), Z(0x6e), Z(0x82), Z(0xa6),
Z(0x93), Z(0xc4), Z(0xaa), Z(0x26), Z(0x49), Z(0xe0), Z(0x21), Z(0x64),
Z(0x07), Z(0x9f), Z(0x64), Z(0x81), Z(0x9c), Z(0xbf), Z(0xf9), Z(0xd1),
Z(0x43), Z(0xf8), Z(0xb6), Z(0xb9), Z(0xf1), Z(0x24), Z(0x75), Z(0x03),
Z(0xe4), Z(0xb0), Z(0x99), Z(0x46), Z(0x3d), Z(0xf5), Z(0xd1), Z(0x39),
Z(0x72), Z(0x12), Z(0xf6), Z(0xba), Z(0x0c), Z(0x0d), Z(0x42), Z(0x2e)
};
#undef Z
#define Z(x) __constant_be32_to_cpu((x << 27) | (x >> 5))
static const u32 sbox1[256] = {
Z(0x77), Z(0x14), Z(0xa6), Z(0xfe), Z(0xb2), Z(0x5e), Z(0x8c), Z(0x3e),
Z(0x67), Z(0x6c), Z(0xa1), Z(0x0d), Z(0xc2), Z(0xa2), Z(0xc1), Z(0x85),
Z(0x6c), Z(0x7b), Z(0x67), Z(0xc6), Z(0x23), Z(0xe3), Z(0xf2), Z(0x89),
Z(0x50), Z(0x9c), Z(0x03), Z(0xb7), Z(0x73), Z(0xe6), Z(0xe1), Z(0x39),
Z(0x31), Z(0x2c), Z(0x27), Z(0x9f), Z(0xa5), Z(0x69), Z(0x44), Z(0xd6),
Z(0x23), Z(0x83), Z(0x98), Z(0x7d), Z(0x3c), Z(0xb4), Z(0x2d), Z(0x99),
Z(0x1c), Z(0x1f), Z(0x8c), Z(0x20), Z(0x03), Z(0x7c), Z(0x5f), Z(0xad),
Z(0xf4), Z(0xfa), Z(0x95), Z(0xca), Z(0x76), Z(0x44), Z(0xcd), Z(0xb6),
Z(0xb8), Z(0xa1), Z(0xa1), Z(0xbe), Z(0x9e), Z(0x54), Z(0x8f), Z(0x0b),
Z(0x16), Z(0x74), Z(0x31), Z(0x8a), Z(0x23), Z(0x17), Z(0x04), Z(0xfa),
Z(0x79), Z(0x84), Z(0xb1), Z(0xf5), Z(0x13), Z(0xab), Z(0xb5), Z(0x2e),
Z(0xaa), Z(0x0c), Z(0x60), Z(0x6b), Z(0x5b), Z(0xc4), Z(0x4b), Z(0xbc),
Z(0xe2), Z(0xaf), Z(0x45), Z(0x73), Z(0xfa), Z(0xc9), Z(0x49), Z(0xcd),
Z(0x00), Z(0x92), Z(0x7d), Z(0x97), Z(0x7a), Z(0x18), Z(0x60), Z(0x3d),
Z(0xcf), Z(0x5b), Z(0xde), Z(0xc6), Z(0xe2), Z(0xe6), Z(0xbb), Z(0x8b),
Z(0x06), Z(0xda), Z(0x08), Z(0x15), Z(0x1b), Z(0x88), Z(0x6a), Z(0x17),
Z(0x89), Z(0xd0), Z(0xa9), Z(0xc1), Z(0xc9), Z(0x70), Z(0x6b), Z(0xe5),
Z(0x43), Z(0xf4), Z(0x68), Z(0xc8), Z(0xd3), Z(0x84), Z(0x28), Z(0x0a),
Z(0x52), Z(0x66), Z(0xa3), Z(0xca), Z(0xf2), Z(0xe3), Z(0x7f), Z(0x7a),
Z(0x31), Z(0xf7), Z(0x88), Z(0x94), Z(0x5e), Z(0x9c), Z(0x63), Z(0xd5),
Z(0x24), Z(0x66), Z(0xfc), Z(0xb3), Z(0x57), Z(0x25), Z(0xbe), Z(0x89),
Z(0x44), Z(0xc4), Z(0xe0), Z(0x8f), Z(0x23), Z(0x3c), Z(0x12), Z(0x52),
Z(0xf5), Z(0x1e), Z(0xf4), Z(0xcb), Z(0x18), Z(0x33), Z(0x1f), Z(0xf8),
Z(0x69), Z(0x10), Z(0x9d), Z(0xd3), Z(0xf7), Z(0x28), Z(0xf8), Z(0x30),
Z(0x05), Z(0x5e), Z(0x32), Z(0xc0), Z(0xd5), Z(0x19), Z(0xbd), Z(0x45),
Z(0x8b), Z(0x5b), Z(0xfd), Z(0xbc), Z(0xe2), Z(0x5c), Z(0xa9), Z(0x96),
Z(0xef), Z(0x70), Z(0xcf), Z(0xc2), Z(0x2a), Z(0xb3), Z(0x61), Z(0xad),
Z(0x80), Z(0x48), Z(0x81), Z(0xb7), Z(0x1d), Z(0x43), Z(0xd9), Z(0xd7),
Z(0x45), Z(0xf0), Z(0xd8), Z(0x8a), Z(0x59), Z(0x7c), Z(0x57), Z(0xc1),
Z(0x79), Z(0xc7), Z(0x34), Z(0xd6), Z(0x43), Z(0xdf), Z(0xe4), Z(0x78),
Z(0x16), Z(0x06), Z(0xda), Z(0x92), Z(0x76), Z(0x51), Z(0xe1), Z(0xd4),
Z(0x70), Z(0x03), Z(0xe0), Z(0x2f), Z(0x96), Z(0x91), Z(0x82), Z(0x80)
};
#undef Z
#define Z(x) __constant_be32_to_cpu(x << 11)
static const u32 sbox2[256] = {
Z(0xf0), Z(0x37), Z(0x24), Z(0x53), Z(0x2a), Z(0x03), Z(0x83), Z(0x86),
Z(0xd1), Z(0xec), Z(0x50), Z(0xf0), Z(0x42), Z(0x78), Z(0x2f), Z(0x6d),
Z(0xbf), Z(0x80), Z(0x87), Z(0x27), Z(0x95), Z(0xe2), Z(0xc5), Z(0x5d),
Z(0xf9), Z(0x6f), Z(0xdb), Z(0xb4), Z(0x65), Z(0x6e), Z(0xe7), Z(0x24),
Z(0xc8), Z(0x1a), Z(0xbb), Z(0x49), Z(0xb5), Z(0x0a), Z(0x7d), Z(0xb9),
Z(0xe8), Z(0xdc), Z(0xb7), Z(0xd9), Z(0x45), Z(0x20), Z(0x1b), Z(0xce),
Z(0x59), Z(0x9d), Z(0x6b), Z(0xbd), Z(0x0e), Z(0x8f), Z(0xa3), Z(0xa9),
Z(0xbc), Z(0x74), Z(0xa6), Z(0xf6), Z(0x7f), Z(0x5f), Z(0xb1), Z(0x68),
Z(0x84), Z(0xbc), Z(0xa9), Z(0xfd), Z(0x55), Z(0x50), Z(0xe9), Z(0xb6),
Z(0x13), Z(0x5e), Z(0x07), Z(0xb8), Z(0x95), Z(0x02), Z(0xc0), Z(0xd0),
Z(0x6a), Z(0x1a), Z(0x85), Z(0xbd), Z(0xb6), Z(0xfd), Z(0xfe), Z(0x17),
Z(0x3f), Z(0x09), Z(0xa3), Z(0x8d), Z(0xfb), Z(0xed), Z(0xda), Z(0x1d),
Z(0x6d), Z(0x1c), Z(0x6c), Z(0x01), Z(0x5a), Z(0xe5), Z(0x71), Z(0x3e),
Z(0x8b), Z(0x6b), Z(0xbe), Z(0x29), Z(0xeb), Z(0x12), Z(0x19), Z(0x34),
Z(0xcd), Z(0xb3), Z(0xbd), Z(0x35), Z(0xea), Z(0x4b), Z(0xd5), Z(0xae),
Z(0x2a), Z(0x79), Z(0x5a), Z(0xa5), Z(0x32), Z(0x12), Z(0x7b), Z(0xdc),
Z(0x2c), Z(0xd0), Z(0x22), Z(0x4b), Z(0xb1), Z(0x85), Z(0x59), Z(0x80),
Z(0xc0), Z(0x30), Z(0x9f), Z(0x73), Z(0xd3), Z(0x14), Z(0x48), Z(0x40),
Z(0x07), Z(0x2d), Z(0x8f), Z(0x80), Z(0x0f), Z(0xce), Z(0x0b), Z(0x5e),
Z(0xb7), Z(0x5e), Z(0xac), Z(0x24), Z(0x94), Z(0x4a), Z(0x18), Z(0x15),
Z(0x05), Z(0xe8), Z(0x02), Z(0x77), Z(0xa9), Z(0xc7), Z(0x40), Z(0x45),
Z(0x89), Z(0xd1), Z(0xea), Z(0xde), Z(0x0c), Z(0x79), Z(0x2a), Z(0x99),
Z(0x6c), Z(0x3e), Z(0x95), Z(0xdd), Z(0x8c), Z(0x7d), Z(0xad), Z(0x6f),
Z(0xdc), Z(0xff), Z(0xfd), Z(0x62), Z(0x47), Z(0xb3), Z(0x21), Z(0x8a),
Z(0xec), Z(0x8e), Z(0x19), Z(0x18), Z(0xb4), Z(0x6e), Z(0x3d), Z(0xfd),
Z(0x74), Z(0x54), Z(0x1e), Z(0x04), Z(0x85), Z(0xd8), Z(0xbc), Z(0x1f),
Z(0x56), Z(0xe7), Z(0x3a), Z(0x56), Z(0x67), Z(0xd6), Z(0xc8), Z(0xa5),
Z(0xf3), Z(0x8e), Z(0xde), Z(0xae), Z(0x37), Z(0x49), Z(0xb7), Z(0xfa),
Z(0xc8), Z(0xf4), Z(0x1f), Z(0xe0), Z(0x2a), Z(0x9b), Z(0x15), Z(0xd1),
Z(0x34), Z(0x0e), Z(0xb5), Z(0xe0), Z(0x44), Z(0x78), Z(0x84), Z(0x59),
Z(0x56), Z(0x68), Z(0x77), Z(0xa5), Z(0x14), Z(0x06), Z(0xf5), Z(0x2f),
Z(0x8c), Z(0x8a), Z(0x73), Z(0x80), Z(0x76), Z(0xb4), Z(0x10), Z(0x86)
};
#undef Z
#define Z(x) __constant_be32_to_cpu(x << 19)
static const u32 sbox3[256] = {
Z(0xa9), Z(0x2a), Z(0x48), Z(0x51), Z(0x84), Z(0x7e), Z(0x49), Z(0xe2),
Z(0xb5), Z(0xb7), Z(0x42), Z(0x33), Z(0x7d), Z(0x5d), Z(0xa6), Z(0x12),
Z(0x44), Z(0x48), Z(0x6d), Z(0x28), Z(0xaa), Z(0x20), Z(0x6d), Z(0x57),
Z(0xd6), Z(0x6b), Z(0x5d), Z(0x72), Z(0xf0), Z(0x92), Z(0x5a), Z(0x1b),
Z(0x53), Z(0x80), Z(0x24), Z(0x70), Z(0x9a), Z(0xcc), Z(0xa7), Z(0x66),
Z(0xa1), Z(0x01), Z(0xa5), Z(0x41), Z(0x97), Z(0x41), Z(0x31), Z(0x82),
Z(0xf1), Z(0x14), Z(0xcf), Z(0x53), Z(0x0d), Z(0xa0), Z(0x10), Z(0xcc),
Z(0x2a), Z(0x7d), Z(0xd2), Z(0xbf), Z(0x4b), Z(0x1a), Z(0xdb), Z(0x16),
Z(0x47), Z(0xf6), Z(0x51), Z(0x36), Z(0xed), Z(0xf3), Z(0xb9), Z(0x1a),
Z(0xa7), Z(0xdf), Z(0x29), Z(0x43), Z(0x01), Z(0x54), Z(0x70), Z(0xa4),
Z(0xbf), Z(0xd4), Z(0x0b), Z(0x53), Z(0x44), Z(0x60), Z(0x9e), Z(0x23),
Z(0xa1), Z(0x18), Z(0x68), Z(0x4f), Z(0xf0), Z(0x2f), Z(0x82), Z(0xc2),
Z(0x2a), Z(0x41), Z(0xb2), Z(0x42), Z(0x0c), Z(0xed), Z(0x0c), Z(0x1d),
Z(0x13), Z(0x3a), Z(0x3c), Z(0x6e), Z(0x35), Z(0xdc), Z(0x60), Z(0x65),
Z(0x85), Z(0xe9), Z(0x64), Z(0x02), Z(0x9a), Z(0x3f), Z(0x9f), Z(0x87),
Z(0x96), Z(0xdf), Z(0xbe), Z(0xf2), Z(0xcb), Z(0xe5), Z(0x6c), Z(0xd4),
Z(0x5a), Z(0x83), Z(0xbf), Z(0x92), Z(0x1b), Z(0x94), Z(0x00), Z(0x42),
Z(0xcf), Z(0x4b), Z(0x00), Z(0x75), Z(0xba), Z(0x8f), Z(0x76), Z(0x5f),
Z(0x5d), Z(0x3a), Z(0x4d), Z(0x09), Z(0x12), Z(0x08), Z(0x38), Z(0x95),
Z(0x17), Z(0xe4), Z(0x01), Z(0x1d), Z(0x4c), Z(0xa9), Z(0xcc), Z(0x85),
Z(0x82), Z(0x4c), Z(0x9d), Z(0x2f), Z(0x3b), Z(0x66), Z(0xa1), Z(0x34),
Z(0x10), Z(0xcd), Z(0x59), Z(0x89), Z(0xa5), Z(0x31), Z(0xcf), Z(0x05),
Z(0xc8), Z(0x84), Z(0xfa), Z(0xc7), Z(0xba), Z(0x4e), Z(0x8b), Z(0x1a),
Z(0x19), Z(0xf1), Z(0xa1), Z(0x3b), Z(0x18), Z(0x12), Z(0x17), Z(0xb0),
Z(0x98), Z(0x8d), Z(0x0b), Z(0x23), Z(0xc3), Z(0x3a), Z(0x2d), Z(0x20),
Z(0xdf), Z(0x13), Z(0xa0), Z(0xa8), Z(0x4c), Z(0x0d), Z(0x6c), Z(0x2f),
Z(0x47), Z(0x13), Z(0x13), Z(0x52), Z(0x1f), Z(0x2d), Z(0xf5), Z(0x79),
Z(0x3d), Z(0xa2), Z(0x54), Z(0xbd), Z(0x69), Z(0xc8), Z(0x6b), Z(0xf3),
Z(0x05), Z(0x28), Z(0xf1), Z(0x16), Z(0x46), Z(0x40), Z(0xb0), Z(0x11),
Z(0xd3), Z(0xb7), Z(0x95), Z(0x49), Z(0xcf), Z(0xc3), Z(0x1d), Z(0x8f),
Z(0xd8), Z(0xe1), Z(0x73), Z(0xdb), Z(0xad), Z(0xc8), Z(0xc9), Z(0xa9),
Z(0xa1), Z(0xc2), Z(0xc5), Z(0xe3), Z(0xba), Z(0xfc), Z(0x0e), Z(0x25)
};
/*
* This is a 16 round Feistel network with permutation F_ENCRYPT
*/
#define F_ENCRYPT(R, L, sched) \
do { \
union lc4 { u32 l; u8 c[4]; } u; \
u.l = sched ^ R; \
L ^= sbox0[u.c[0]] ^ sbox1[u.c[1]] ^ sbox2[u.c[2]] ^ sbox3[u.c[3]]; \
} while(0)
/*
* encryptor
*/
static void fcrypt_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
{
const struct fcrypt_ctx *ctx = crypto_tfm_ctx(tfm);
struct {
u32 l, r;
} X;
memcpy(&X, src, sizeof(X));
F_ENCRYPT(X.r, X.l, ctx->sched[0x0]);
F_ENCRYPT(X.l, X.r, ctx->sched[0x1]);
F_ENCRYPT(X.r, X.l, ctx->sched[0x2]);
F_ENCRYPT(X.l, X.r, ctx->sched[0x3]);
F_ENCRYPT(X.r, X.l, ctx->sched[0x4]);
F_ENCRYPT(X.l, X.r, ctx->sched[0x5]);
F_ENCRYPT(X.r, X.l, ctx->sched[0x6]);
F_ENCRYPT(X.l, X.r, ctx->sched[0x7]);
F_ENCRYPT(X.r, X.l, ctx->sched[0x8]);
F_ENCRYPT(X.l, X.r, ctx->sched[0x9]);
F_ENCRYPT(X.r, X.l, ctx->sched[0xa]);
F_ENCRYPT(X.l, X.r, ctx->sched[0xb]);
F_ENCRYPT(X.r, X.l, ctx->sched[0xc]);
F_ENCRYPT(X.l, X.r, ctx->sched[0xd]);
F_ENCRYPT(X.r, X.l, ctx->sched[0xe]);
F_ENCRYPT(X.l, X.r, ctx->sched[0xf]);
memcpy(dst, &X, sizeof(X));
}
/*
* decryptor
*/
static void fcrypt_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
{
const struct fcrypt_ctx *ctx = crypto_tfm_ctx(tfm);
struct {
u32 l, r;
} X;
memcpy(&X, src, sizeof(X));
F_ENCRYPT(X.l, X.r, ctx->sched[0xf]);
F_ENCRYPT(X.r, X.l, ctx->sched[0xe]);
F_ENCRYPT(X.l, X.r, ctx->sched[0xd]);
F_ENCRYPT(X.r, X.l, ctx->sched[0xc]);
F_ENCRYPT(X.l, X.r, ctx->sched[0xb]);
F_ENCRYPT(X.r, X.l, ctx->sched[0xa]);
F_ENCRYPT(X.l, X.r, ctx->sched[0x9]);
F_ENCRYPT(X.r, X.l, ctx->sched[0x8]);
F_ENCRYPT(X.l, X.r, ctx->sched[0x7]);
F_ENCRYPT(X.r, X.l, ctx->sched[0x6]);
F_ENCRYPT(X.l, X.r, ctx->sched[0x5]);
F_ENCRYPT(X.r, X.l, ctx->sched[0x4]);
F_ENCRYPT(X.l, X.r, ctx->sched[0x3]);
F_ENCRYPT(X.r, X.l, ctx->sched[0x2]);
F_ENCRYPT(X.l, X.r, ctx->sched[0x1]);
F_ENCRYPT(X.r, X.l, ctx->sched[0x0]);
memcpy(dst, &X, sizeof(X));
}
/*
* Generate a key schedule from key, the least significant bit in each key byte
* is parity and shall be ignored. This leaves 56 significant bits in the key
* to scatter over the 16 key schedules. For each schedule extract the low
* order 32 bits and use as schedule, then rotate right by 11 bits.
*/
static int fcrypt_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
{
struct fcrypt_ctx *ctx = crypto_tfm_ctx(tfm);
#if BITS_PER_LONG == 64 /* the 64-bit version can also be used for 32-bit
* kernels - it seems to be faster but the code is
* larger */
u64 k; /* k holds all 56 non-parity bits */
/* discard the parity bits */
k = (*key++) >> 1;
k <<= 7;
k |= (*key++) >> 1;
k <<= 7;
k |= (*key++) >> 1;
k <<= 7;
k |= (*key++) >> 1;
k <<= 7;
k |= (*key++) >> 1;
k <<= 7;
k |= (*key++) >> 1;
k <<= 7;
k |= (*key++) >> 1;
k <<= 7;
k |= (*key) >> 1;
/* Use lower 32 bits for schedule, rotate by 11 each round (16 times) */
ctx->sched[0x0] = be32_to_cpu(k); ror56_64(k, 11);
ctx->sched[0x1] = be32_to_cpu(k); ror56_64(k, 11);
ctx->sched[0x2] = be32_to_cpu(k); ror56_64(k, 11);
ctx->sched[0x3] = be32_to_cpu(k); ror56_64(k, 11);
ctx->sched[0x4] = be32_to_cpu(k); ror56_64(k, 11);
ctx->sched[0x5] = be32_to_cpu(k); ror56_64(k, 11);
ctx->sched[0x6] = be32_to_cpu(k); ror56_64(k, 11);
ctx->sched[0x7] = be32_to_cpu(k); ror56_64(k, 11);
ctx->sched[0x8] = be32_to_cpu(k); ror56_64(k, 11);
ctx->sched[0x9] = be32_to_cpu(k); ror56_64(k, 11);
ctx->sched[0xa] = be32_to_cpu(k); ror56_64(k, 11);
ctx->sched[0xb] = be32_to_cpu(k); ror56_64(k, 11);
ctx->sched[0xc] = be32_to_cpu(k); ror56_64(k, 11);
ctx->sched[0xd] = be32_to_cpu(k); ror56_64(k, 11);
ctx->sched[0xe] = be32_to_cpu(k); ror56_64(k, 11);
ctx->sched[0xf] = be32_to_cpu(k);
return 0;
#else
u32 hi, lo; /* hi is upper 24 bits and lo lower 32, total 56 */
/* discard the parity bits */
lo = (*key++) >> 1;
lo <<= 7;
lo |= (*key++) >> 1;
lo <<= 7;
lo |= (*key++) >> 1;
lo <<= 7;
lo |= (*key++) >> 1;
hi = lo >> 4;
lo &= 0xf;
lo <<= 7;
lo |= (*key++) >> 1;
lo <<= 7;
lo |= (*key++) >> 1;
lo <<= 7;
lo |= (*key++) >> 1;
lo <<= 7;
lo |= (*key) >> 1;
/* Use lower 32 bits for schedule, rotate by 11 each round (16 times) */
ctx->sched[0x0] = be32_to_cpu(lo); ror56(hi, lo, 11);
ctx->sched[0x1] = be32_to_cpu(lo); ror56(hi, lo, 11);
ctx->sched[0x2] = be32_to_cpu(lo); ror56(hi, lo, 11);
ctx->sched[0x3] = be32_to_cpu(lo); ror56(hi, lo, 11);
ctx->sched[0x4] = be32_to_cpu(lo); ror56(hi, lo, 11);
ctx->sched[0x5] = be32_to_cpu(lo); ror56(hi, lo, 11);
ctx->sched[0x6] = be32_to_cpu(lo); ror56(hi, lo, 11);
ctx->sched[0x7] = be32_to_cpu(lo); ror56(hi, lo, 11);
ctx->sched[0x8] = be32_to_cpu(lo); ror56(hi, lo, 11);
ctx->sched[0x9] = be32_to_cpu(lo); ror56(hi, lo, 11);
ctx->sched[0xa] = be32_to_cpu(lo); ror56(hi, lo, 11);
ctx->sched[0xb] = be32_to_cpu(lo); ror56(hi, lo, 11);
ctx->sched[0xc] = be32_to_cpu(lo); ror56(hi, lo, 11);
ctx->sched[0xd] = be32_to_cpu(lo); ror56(hi, lo, 11);
ctx->sched[0xe] = be32_to_cpu(lo); ror56(hi, lo, 11);
ctx->sched[0xf] = be32_to_cpu(lo);
return 0;
#endif
}
static struct crypto_alg fcrypt_alg = {
.cra_name = "fcrypt",
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
.cra_blocksize = 8,
.cra_ctxsize = sizeof(struct fcrypt_ctx),
.cra_module = THIS_MODULE,
.cra_alignmask = 3,
.cra_list = LIST_HEAD_INIT(fcrypt_alg.cra_list),
.cra_u = { .cipher = {
.cia_min_keysize = 8,
.cia_max_keysize = 8,
.cia_setkey = fcrypt_setkey,
.cia_encrypt = fcrypt_encrypt,
.cia_decrypt = fcrypt_decrypt } }
};
static int __init init(void)
{
return crypto_register_alg(&fcrypt_alg);
}
static void __exit fini(void)
{
crypto_unregister_alg(&fcrypt_alg);
}
module_init(init);
module_exit(fini);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("FCrypt Cipher Algorithm");
MODULE_AUTHOR("David Howells <dhowells@redhat.com>");
......@@ -16,12 +16,13 @@
#include "internal.h"
static unsigned int crypto_hash_ctxsize(struct crypto_alg *alg)
static unsigned int crypto_hash_ctxsize(struct crypto_alg *alg, u32 type,
u32 mask)
{
return alg->cra_ctxsize;
}
static int crypto_init_hash_ops(struct crypto_tfm *tfm)
static int crypto_init_hash_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
{
struct hash_tfm *crt = &tfm->crt_hash;
struct hash_alg *alg = &tfm->__crt_alg->cra_hash;
......
......@@ -172,15 +172,16 @@ static int hmac_digest(struct hash_desc *pdesc, struct scatterlist *sg,
static int hmac_init_tfm(struct crypto_tfm *tfm)
{
struct crypto_hash *hash;
struct crypto_instance *inst = (void *)tfm->__crt_alg;
struct crypto_spawn *spawn = crypto_instance_ctx(inst);
struct hmac_ctx *ctx = hmac_ctx(__crypto_hash_cast(tfm));
tfm = crypto_spawn_tfm(spawn);
if (IS_ERR(tfm))
return PTR_ERR(tfm);
hash = crypto_spawn_hash(spawn);
if (IS_ERR(hash))
return PTR_ERR(hash);
ctx->child = crypto_hash_cast(tfm);
ctx->child = hash;
return 0;
}
......
......@@ -83,8 +83,7 @@ static inline void crypto_exit_proc(void)
{ }
#endif
static inline unsigned int crypto_digest_ctxsize(struct crypto_alg *alg,
int flags)
static inline unsigned int crypto_digest_ctxsize(struct crypto_alg *alg)
{
unsigned int len = alg->cra_ctxsize;
......@@ -96,23 +95,12 @@ static inline unsigned int crypto_digest_ctxsize(struct crypto_alg *alg,
return len;
}
static inline unsigned int crypto_cipher_ctxsize(struct crypto_alg *alg,
int flags)
static inline unsigned int crypto_cipher_ctxsize(struct crypto_alg *alg)
{
unsigned int len = alg->cra_ctxsize;
switch (flags & CRYPTO_TFM_MODE_MASK) {
case CRYPTO_TFM_MODE_CBC:
len = ALIGN(len, (unsigned long)alg->cra_alignmask + 1);
len += alg->cra_blocksize;
break;
}
return len;
return alg->cra_ctxsize;
}
static inline unsigned int crypto_compress_ctxsize(struct crypto_alg *alg,
int flags)
static inline unsigned int crypto_compress_ctxsize(struct crypto_alg *alg)
{
return alg->cra_ctxsize;
}
......@@ -121,10 +109,6 @@ struct crypto_alg *crypto_mod_get(struct crypto_alg *alg);
struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type, u32 mask);
struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask);
int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags);
int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags);
int crypto_init_compress_flags(struct crypto_tfm *tfm, u32 flags);
int crypto_init_digest_ops(struct crypto_tfm *tfm);
int crypto_init_cipher_ops(struct crypto_tfm *tfm);
int crypto_init_compress_ops(struct crypto_tfm *tfm);
......@@ -136,7 +120,8 @@ void crypto_exit_compress_ops(struct crypto_tfm *tfm);
void crypto_larval_error(const char *name, u32 type, u32 mask);
void crypto_shoot_alg(struct crypto_alg *alg);
struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 flags);
struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type,
u32 mask);
int crypto_register_instance(struct crypto_template *tmpl,
struct crypto_instance *inst);
......
......@@ -201,21 +201,22 @@ static int decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
static int init_tfm(struct crypto_tfm *tfm)
{
struct crypto_cipher *cipher;
struct crypto_instance *inst = (void *)tfm->__crt_alg;
struct crypto_spawn *spawn = crypto_instance_ctx(inst);
struct priv *ctx = crypto_tfm_ctx(tfm);
u32 *flags = &tfm->crt_flags;
tfm = crypto_spawn_tfm(spawn);
if (IS_ERR(tfm))
return PTR_ERR(tfm);
cipher = crypto_spawn_cipher(spawn);
if (IS_ERR(cipher))
return PTR_ERR(cipher);
if (crypto_tfm_alg_blocksize(tfm) != 16) {
if (crypto_cipher_blocksize(cipher) != 16) {
*flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;
return -EINVAL;
}
ctx->child = crypto_cipher_cast(tfm);
ctx->child = cipher;
return 0;
}
......
/*
* PCBC: Propagating Cipher Block Chaining mode
*
* Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* Derived from cbc.c
* - 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 <crypto/algapi.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/scatterlist.h>
#include <linux/slab.h>
struct crypto_pcbc_ctx {
struct crypto_cipher *child;
void (*xor)(u8 *dst, const u8 *src, unsigned int bs);
};
static int crypto_pcbc_setkey(struct crypto_tfm *parent, const u8 *key,
unsigned int keylen)
{
struct crypto_pcbc_ctx *ctx = crypto_tfm_ctx(parent);
struct crypto_cipher *child = ctx->child;
int err;
crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
crypto_cipher_set_flags(child, crypto_tfm_get_flags(parent) &
CRYPTO_TFM_REQ_MASK);
err = crypto_cipher_setkey(child, key, keylen);
crypto_tfm_set_flags(parent, crypto_cipher_get_flags(child) &
CRYPTO_TFM_RES_MASK);
return err;
}
static int crypto_pcbc_encrypt_segment(struct blkcipher_desc *desc,
struct blkcipher_walk *walk,
struct crypto_cipher *tfm,
void (*xor)(u8 *, const u8 *,
unsigned int))
{
void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
crypto_cipher_alg(tfm)->cia_encrypt;
int bsize = crypto_cipher_blocksize(tfm);
unsigned int nbytes = walk->nbytes;
u8 *src = walk->src.virt.addr;
u8 *dst = walk->dst.virt.addr;
u8 *iv = walk->iv;
do {
xor(iv, src, bsize);
fn(crypto_cipher_tfm(tfm), dst, iv);
memcpy(iv, dst, bsize);
xor(iv, src, bsize);
src += bsize;
dst += bsize;
} while ((nbytes -= bsize) >= bsize);
return nbytes;
}
static int crypto_pcbc_encrypt_inplace(struct blkcipher_desc *desc,
struct blkcipher_walk *walk,
struct crypto_cipher *tfm,
void (*xor)(u8 *, const u8 *,
unsigned int))
{
void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
crypto_cipher_alg(tfm)->cia_encrypt;
int bsize = crypto_cipher_blocksize(tfm);
unsigned int nbytes = walk->nbytes;
u8 *src = walk->src.virt.addr;
u8 *iv = walk->iv;
u8 tmpbuf[bsize];
do {
memcpy(tmpbuf, src, bsize);
xor(iv, tmpbuf, bsize);
fn(crypto_cipher_tfm(tfm), src, iv);
memcpy(iv, src, bsize);
xor(iv, tmpbuf, bsize);
src += bsize;
} while ((nbytes -= bsize) >= bsize);
memcpy(walk->iv, iv, bsize);
return nbytes;
}
static int crypto_pcbc_encrypt(struct blkcipher_desc *desc,
struct scatterlist *dst, struct scatterlist *src,
unsigned int nbytes)
{
struct blkcipher_walk walk;
struct crypto_blkcipher *tfm = desc->tfm;
struct crypto_pcbc_ctx *ctx = crypto_blkcipher_ctx(tfm);
struct crypto_cipher *child = ctx->child;
void (*xor)(u8 *, const u8 *, unsigned int bs) = ctx->xor;
int err;
blkcipher_walk_init(&walk, dst, src, nbytes);
err = blkcipher_walk_virt(desc, &walk);
while ((nbytes = walk.nbytes)) {
if (walk.src.virt.addr == walk.dst.virt.addr)
nbytes = crypto_pcbc_encrypt_inplace(desc, &walk, child,
xor);
else
nbytes = crypto_pcbc_encrypt_segment(desc, &walk, child,
xor);
err = blkcipher_walk_done(desc, &walk, nbytes);
}
return err;
}
static int crypto_pcbc_decrypt_segment(struct blkcipher_desc *desc,
struct blkcipher_walk *walk,
struct crypto_cipher *tfm,
void (*xor)(u8 *, const u8 *,
unsigned int))
{
void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
crypto_cipher_alg(tfm)->cia_decrypt;
int bsize = crypto_cipher_blocksize(tfm);
unsigned int nbytes = walk->nbytes;
u8 *src = walk->src.virt.addr;
u8 *dst = walk->dst.virt.addr;
u8 *iv = walk->iv;
do {
fn(crypto_cipher_tfm(tfm), dst, src);
xor(dst, iv, bsize);
memcpy(iv, src, bsize);
xor(iv, dst, bsize);
src += bsize;
dst += bsize;
} while ((nbytes -= bsize) >= bsize);
memcpy(walk->iv, iv, bsize);
return nbytes;
}
static int crypto_pcbc_decrypt_inplace(struct blkcipher_desc *desc,
struct blkcipher_walk *walk,
struct crypto_cipher *tfm,
void (*xor)(u8 *, const u8 *,
unsigned int))
{
void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
crypto_cipher_alg(tfm)->cia_decrypt;
int bsize = crypto_cipher_blocksize(tfm);
unsigned int nbytes = walk->nbytes;
u8 *src = walk->src.virt.addr;
u8 *iv = walk->iv;
u8 tmpbuf[bsize];
do {
memcpy(tmpbuf, src, bsize);
fn(crypto_cipher_tfm(tfm), src, src);
xor(src, iv, bsize);
memcpy(iv, tmpbuf, bsize);
xor(iv, src, bsize);
src += bsize;
} while ((nbytes -= bsize) >= bsize);
memcpy(walk->iv, iv, bsize);
return nbytes;
}
static int crypto_pcbc_decrypt(struct blkcipher_desc *desc,
struct scatterlist *dst, struct scatterlist *src,
unsigned int nbytes)
{
struct blkcipher_walk walk;
struct crypto_blkcipher *tfm = desc->tfm;
struct crypto_pcbc_ctx *ctx = crypto_blkcipher_ctx(tfm);
struct crypto_cipher *child = ctx->child;
void (*xor)(u8 *, const u8 *, unsigned int bs) = ctx->xor;
int err;
blkcipher_walk_init(&walk, dst, src, nbytes);
err = blkcipher_walk_virt(desc, &walk);
while ((nbytes = walk.nbytes)) {
if (walk.src.virt.addr == walk.dst.virt.addr)
nbytes = crypto_pcbc_decrypt_inplace(desc, &walk, child,
xor);
else
nbytes = crypto_pcbc_decrypt_segment(desc, &walk, child,
xor);
err = blkcipher_walk_done(desc, &walk, nbytes);
}
return err;
}
static void xor_byte(u8 *a, const u8 *b, unsigned int bs)
{
do {
*a++ ^= *b++;
} while (--bs);
}
static void xor_quad(u8 *dst, const u8 *src, unsigned int bs)
{
u32 *a = (u32 *)dst;
u32 *b = (u32 *)src;
do {
*a++ ^= *b++;
} while ((bs -= 4));
}
static void xor_64(u8 *a, const u8 *b, unsigned int bs)
{
((u32 *)a)[0] ^= ((u32 *)b)[0];
((u32 *)a)[1] ^= ((u32 *)b)[1];
}
static void xor_128(u8 *a, const u8 *b, unsigned int bs)
{
((u32 *)a)[0] ^= ((u32 *)b)[0];
((u32 *)a)[1] ^= ((u32 *)b)[1];
((u32 *)a)[2] ^= ((u32 *)b)[2];
((u32 *)a)[3] ^= ((u32 *)b)[3];
}
static int crypto_pcbc_init_tfm(struct crypto_tfm *tfm)
{
struct crypto_instance *inst = (void *)tfm->__crt_alg;
struct crypto_spawn *spawn = crypto_instance_ctx(inst);
struct crypto_pcbc_ctx *ctx = crypto_tfm_ctx(tfm);
struct crypto_cipher *cipher;
switch (crypto_tfm_alg_blocksize(tfm)) {
case 8:
ctx->xor = xor_64;
break;
case 16:
ctx->xor = xor_128;
break;
default:
if (crypto_tfm_alg_blocksize(tfm) % 4)
ctx->xor = xor_byte;
else
ctx->xor = xor_quad;
}
cipher = crypto_spawn_cipher(spawn);
if (IS_ERR(cipher))
return PTR_ERR(cipher);
ctx->child = cipher;
return 0;
}
static void crypto_pcbc_exit_tfm(struct crypto_tfm *tfm)
{
struct crypto_pcbc_ctx *ctx = crypto_tfm_ctx(tfm);
crypto_free_cipher(ctx->child);
}
static struct crypto_instance *crypto_pcbc_alloc(void *param, unsigned int len)
{
struct crypto_instance *inst;
struct crypto_alg *alg;
alg = crypto_get_attr_alg(param, len, CRYPTO_ALG_TYPE_CIPHER,
CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
if (IS_ERR(alg))
return ERR_PTR(PTR_ERR(alg));
inst = crypto_alloc_instance("pcbc", alg);
if (IS_ERR(inst))
goto out_put_alg;
inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER;
inst->alg.cra_priority = alg->cra_priority;
inst->alg.cra_blocksize = alg->cra_blocksize;
inst->alg.cra_alignmask = alg->cra_alignmask;
inst->alg.cra_type = &crypto_blkcipher_type;
if (!(alg->cra_blocksize % 4))
inst->alg.cra_alignmask |= 3;
inst->alg.cra_blkcipher.ivsize = alg->cra_blocksize;
inst->alg.cra_blkcipher.min_keysize = alg->cra_cipher.cia_min_keysize;
inst->alg.cra_blkcipher.max_keysize = alg->cra_cipher.cia_max_keysize;
inst->alg.cra_ctxsize = sizeof(struct crypto_pcbc_ctx);
inst->alg.cra_init = crypto_pcbc_init_tfm;
inst->alg.cra_exit = crypto_pcbc_exit_tfm;
inst->alg.cra_blkcipher.setkey = crypto_pcbc_setkey;
inst->alg.cra_blkcipher.encrypt = crypto_pcbc_encrypt;
inst->alg.cra_blkcipher.decrypt = crypto_pcbc_decrypt;
out_put_alg:
crypto_mod_put(alg);
return inst;
}
static void crypto_pcbc_free(struct crypto_instance *inst)
{
crypto_drop_spawn(crypto_instance_ctx(inst));
kfree(inst);
}
static struct crypto_template crypto_pcbc_tmpl = {
.name = "pcbc",
.alloc = crypto_pcbc_alloc,
.free = crypto_pcbc_free,
.module = THIS_MODULE,
};
static int __init crypto_pcbc_module_init(void)
{
return crypto_register_template(&crypto_pcbc_tmpl);
}
static void __exit crypto_pcbc_module_exit(void)
{
crypto_unregister_template(&crypto_pcbc_tmpl);
}
module_init(crypto_pcbc_module_init);
module_exit(crypto_pcbc_module_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("PCBC block cipher algorithm");
......@@ -12,6 +12,7 @@
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* 2006-12-07 Added SHA384 HMAC and SHA512 HMAC tests
* 2004-08-09 Added cipher speed tests (Reyk Floeter <reyk@vantronix.net>)
* 2003-09-14 Rewritten by Kartikey Mahendra Bhatt
*
......@@ -71,7 +72,8 @@ static char *check[] = {
"des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish",
"twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6",
"arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea",
"khazad", "wp512", "wp384", "wp256", "tnepres", "xeta", NULL
"khazad", "wp512", "wp384", "wp256", "tnepres", "xeta", "fcrypt",
"camellia", NULL
};
static void hexdump(unsigned char *buf, unsigned int len)
......@@ -765,7 +767,7 @@ static void test_deflate(void)
memcpy(tvmem, deflate_comp_tv_template, tsize);
tv = (void *)tvmem;
tfm = crypto_alloc_tfm("deflate", 0);
tfm = crypto_alloc_comp("deflate", 0, CRYPTO_ALG_ASYNC);
if (tfm == NULL) {
printk("failed to load transform for deflate\n");
return;
......@@ -964,6 +966,26 @@ static void do_test(void)
test_cipher("ecb(xeta)", DECRYPT, xeta_dec_tv_template,
XETA_DEC_TEST_VECTORS);
//FCrypt
test_cipher("pcbc(fcrypt)", ENCRYPT, fcrypt_pcbc_enc_tv_template,
FCRYPT_ENC_TEST_VECTORS);
test_cipher("pcbc(fcrypt)", DECRYPT, fcrypt_pcbc_dec_tv_template,
FCRYPT_DEC_TEST_VECTORS);
//CAMELLIA
test_cipher("ecb(camellia)", ENCRYPT,
camellia_enc_tv_template,
CAMELLIA_ENC_TEST_VECTORS);
test_cipher("ecb(camellia)", DECRYPT,
camellia_dec_tv_template,
CAMELLIA_DEC_TEST_VECTORS);
test_cipher("cbc(camellia)", ENCRYPT,
camellia_cbc_enc_tv_template,
CAMELLIA_CBC_ENC_TEST_VECTORS);
test_cipher("cbc(camellia)", DECRYPT,
camellia_cbc_dec_tv_template,
CAMELLIA_CBC_DEC_TEST_VECTORS);
test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS);
test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS);
test_hash("wp512", wp512_tv_template, WP512_TEST_VECTORS);
......@@ -980,6 +1002,10 @@ static void do_test(void)
HMAC_SHA1_TEST_VECTORS);
test_hash("hmac(sha256)", hmac_sha256_tv_template,
HMAC_SHA256_TEST_VECTORS);
test_hash("hmac(sha384)", hmac_sha384_tv_template,
HMAC_SHA384_TEST_VECTORS);
test_hash("hmac(sha512)", hmac_sha512_tv_template,
HMAC_SHA512_TEST_VECTORS);
test_hash("xcbc(aes)", aes_xcbc128_tv_template,
XCBC_AES_TEST_VECTORS);
......@@ -1177,6 +1203,28 @@ static void do_test(void)
XETA_DEC_TEST_VECTORS);
break;
case 31:
test_cipher("pcbc(fcrypt)", ENCRYPT, fcrypt_pcbc_enc_tv_template,
FCRYPT_ENC_TEST_VECTORS);
test_cipher("pcbc(fcrypt)", DECRYPT, fcrypt_pcbc_dec_tv_template,
FCRYPT_DEC_TEST_VECTORS);
break;
case 32:
test_cipher("ecb(camellia)", ENCRYPT,
camellia_enc_tv_template,
CAMELLIA_ENC_TEST_VECTORS);
test_cipher("ecb(camellia)", DECRYPT,
camellia_dec_tv_template,
CAMELLIA_DEC_TEST_VECTORS);
test_cipher("cbc(camellia)", ENCRYPT,
camellia_cbc_enc_tv_template,
CAMELLIA_CBC_ENC_TEST_VECTORS);
test_cipher("cbc(camellia)", DECRYPT,
camellia_cbc_dec_tv_template,
CAMELLIA_CBC_DEC_TEST_VECTORS);
break;
case 100:
test_hash("hmac(md5)", hmac_md5_tv_template,
HMAC_MD5_TEST_VECTORS);
......@@ -1192,6 +1240,16 @@ static void do_test(void)
HMAC_SHA256_TEST_VECTORS);
break;
case 103:
test_hash("hmac(sha384)", hmac_sha384_tv_template,
HMAC_SHA384_TEST_VECTORS);
break;
case 104:
test_hash("hmac(sha512)", hmac_sha512_tv_template,
HMAC_SHA512_TEST_VECTORS);
break;
case 200:
test_cipher_speed("ecb(aes)", ENCRYPT, sec, NULL, 0,
......@@ -1260,6 +1318,17 @@ static void do_test(void)
des_speed_template);
break;
case 205:
test_cipher_speed("ecb(camellia)", ENCRYPT, sec, NULL, 0,
camellia_speed_template);
test_cipher_speed("ecb(camellia)", DECRYPT, sec, NULL, 0,
camellia_speed_template);
test_cipher_speed("cbc(camellia)", ENCRYPT, sec, NULL, 0,
camellia_speed_template);
test_cipher_speed("cbc(camellia)", DECRYPT, sec, NULL, 0,
camellia_speed_template);
break;
case 300:
/* fall through */
......
此差异已折叠。
......@@ -21,6 +21,7 @@
#include <linux/crypto.h>
#include <linux/err.h>
#include <linux/hardirq.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/rtnetlink.h>
......@@ -47,7 +48,7 @@ static u_int32_t ks[12] = {0x01010101, 0x01010101, 0x01010101, 0x01010101,
* +------------------------
*/
struct crypto_xcbc_ctx {
struct crypto_tfm *child;
struct crypto_cipher *child;
u8 *odds;
u8 *prev;
u8 *key;
......@@ -75,8 +76,7 @@ static int _crypto_xcbc_digest_setkey(struct crypto_hash *parent,
if ((err = crypto_cipher_setkey(ctx->child, ctx->key, ctx->keylen)))
return err;
ctx->child->__crt_alg->cra_cipher.cia_encrypt(ctx->child, key1,
ctx->consts);
crypto_cipher_encrypt_one(ctx->child, key1, ctx->consts);
return crypto_cipher_setkey(ctx->child, key1, bs);
}
......@@ -86,7 +86,7 @@ static int crypto_xcbc_digest_setkey(struct crypto_hash *parent,
{
struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(parent);
if (keylen != crypto_tfm_alg_blocksize(ctx->child))
if (keylen != crypto_cipher_blocksize(ctx->child))
return -EINVAL;
ctx->keylen = keylen;
......@@ -108,13 +108,13 @@ static int crypto_xcbc_digest_init(struct hash_desc *pdesc)
return 0;
}
static int crypto_xcbc_digest_update(struct hash_desc *pdesc,
struct scatterlist *sg,
unsigned int nbytes)
static int crypto_xcbc_digest_update2(struct hash_desc *pdesc,
struct scatterlist *sg,
unsigned int nbytes)
{
struct crypto_hash *parent = pdesc->tfm;
struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(parent);
struct crypto_tfm *tfm = ctx->child;
struct crypto_cipher *tfm = ctx->child;
int bs = crypto_hash_blocksize(parent);
unsigned int i = 0;
......@@ -142,7 +142,7 @@ static int crypto_xcbc_digest_update(struct hash_desc *pdesc,
offset += len;
crypto_kunmap(p, 0);
crypto_yield(tfm->crt_flags);
crypto_yield(pdesc->flags);
continue;
}
......@@ -152,7 +152,7 @@ static int crypto_xcbc_digest_update(struct hash_desc *pdesc,
p += bs - ctx->len;
ctx->xor(ctx->prev, ctx->odds, bs);
tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, ctx->prev, ctx->prev);
crypto_cipher_encrypt_one(tfm, ctx->prev, ctx->prev);
/* clearing the length */
ctx->len = 0;
......@@ -160,7 +160,8 @@ static int crypto_xcbc_digest_update(struct hash_desc *pdesc,
/* encrypting the rest of data */
while (len > bs) {
ctx->xor(ctx->prev, p, bs);
tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, ctx->prev, ctx->prev);
crypto_cipher_encrypt_one(tfm, ctx->prev,
ctx->prev);
p += bs;
len -= bs;
}
......@@ -171,7 +172,7 @@ static int crypto_xcbc_digest_update(struct hash_desc *pdesc,
ctx->len = len;
}
crypto_kunmap(p, 0);
crypto_yield(tfm->crt_flags);
crypto_yield(pdesc->flags);
slen -= min(slen, ((unsigned int)(PAGE_SIZE)) - offset);
offset = 0;
pg++;
......@@ -183,11 +184,20 @@ static int crypto_xcbc_digest_update(struct hash_desc *pdesc,
return 0;
}
static int crypto_xcbc_digest_update(struct hash_desc *pdesc,
struct scatterlist *sg,
unsigned int nbytes)
{
if (WARN_ON_ONCE(in_irq()))
return -EDEADLK;
return crypto_xcbc_digest_update2(pdesc, sg, nbytes);
}
static int crypto_xcbc_digest_final(struct hash_desc *pdesc, u8 *out)
{
struct crypto_hash *parent = pdesc->tfm;
struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(parent);
struct crypto_tfm *tfm = ctx->child;
struct crypto_cipher *tfm = ctx->child;
int bs = crypto_hash_blocksize(parent);
int err = 0;
......@@ -197,13 +207,14 @@ static int crypto_xcbc_digest_final(struct hash_desc *pdesc, u8 *out)
if ((err = crypto_cipher_setkey(tfm, ctx->key, ctx->keylen)) != 0)
return err;
tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, key2, (const u8*)(ctx->consts+bs));
crypto_cipher_encrypt_one(tfm, key2,
(u8 *)(ctx->consts + bs));
ctx->xor(ctx->prev, ctx->odds, bs);
ctx->xor(ctx->prev, key2, bs);
_crypto_xcbc_digest_setkey(parent, ctx);
tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, out, ctx->prev);
crypto_cipher_encrypt_one(tfm, out, ctx->prev);
} else {
u8 key3[bs];
unsigned int rlen;
......@@ -218,14 +229,15 @@ static int crypto_xcbc_digest_final(struct hash_desc *pdesc, u8 *out)
if ((err = crypto_cipher_setkey(tfm, ctx->key, ctx->keylen)) != 0)
return err;
tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, key3, (const u8*)(ctx->consts+bs*2));
crypto_cipher_encrypt_one(tfm, key3,
(u8 *)(ctx->consts + bs * 2));
ctx->xor(ctx->prev, ctx->odds, bs);
ctx->xor(ctx->prev, key3, bs);
_crypto_xcbc_digest_setkey(parent, ctx);
tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, out, ctx->prev);
crypto_cipher_encrypt_one(tfm, out, ctx->prev);
}
return 0;
......@@ -234,21 +246,25 @@ static int crypto_xcbc_digest_final(struct hash_desc *pdesc, u8 *out)
static int crypto_xcbc_digest(struct hash_desc *pdesc,
struct scatterlist *sg, unsigned int nbytes, u8 *out)
{
if (WARN_ON_ONCE(in_irq()))
return -EDEADLK;
crypto_xcbc_digest_init(pdesc);
crypto_xcbc_digest_update(pdesc, sg, nbytes);
crypto_xcbc_digest_update2(pdesc, sg, nbytes);
return crypto_xcbc_digest_final(pdesc, out);
}
static int xcbc_init_tfm(struct crypto_tfm *tfm)
{
struct crypto_cipher *cipher;
struct crypto_instance *inst = (void *)tfm->__crt_alg;
struct crypto_spawn *spawn = crypto_instance_ctx(inst);
struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(__crypto_hash_cast(tfm));
int bs = crypto_hash_blocksize(__crypto_hash_cast(tfm));
tfm = crypto_spawn_tfm(spawn);
if (IS_ERR(tfm))
return PTR_ERR(tfm);
cipher = crypto_spawn_cipher(spawn);
if (IS_ERR(cipher))
return PTR_ERR(cipher);
switch(bs) {
case 16:
......@@ -258,7 +274,7 @@ static int xcbc_init_tfm(struct crypto_tfm *tfm)
return -EINVAL;
}
ctx->child = crypto_cipher_cast(tfm);
ctx->child = cipher;
ctx->odds = (u8*)(ctx+1);
ctx->prev = ctx->odds + bs;
ctx->key = ctx->prev + bs;
......
......@@ -457,7 +457,7 @@ static struct pci_driver geode_aes_driver = {
static int __init
geode_aes_init(void)
{
return pci_module_init(&geode_aes_driver);
return pci_register_driver(&geode_aes_driver);
}
static void __exit
......
......@@ -184,7 +184,7 @@ static int tlb_initialize(struct bonding *bond)
spin_lock_init(&(bond_info->tx_hashtbl_lock));
new_hashtbl = kmalloc(size, GFP_KERNEL);
new_hashtbl = kzalloc(size, GFP_KERNEL);
if (!new_hashtbl) {
printk(KERN_ERR DRV_NAME
": %s: Error: Failed to allocate TLB hash table\n",
......@@ -195,8 +195,6 @@ static int tlb_initialize(struct bonding *bond)
bond_info->tx_hashtbl = new_hashtbl;
memset(bond_info->tx_hashtbl, 0, size);
for (i = 0; i < TLB_HASH_TABLE_SIZE; i++) {
tlb_init_table_entry(&bond_info->tx_hashtbl[i], 1);
}
......
......@@ -1343,14 +1343,12 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
"inaccurate.\n", bond_dev->name, slave_dev->name);
}
new_slave = kmalloc(sizeof(struct slave), GFP_KERNEL);
new_slave = kzalloc(sizeof(struct slave), GFP_KERNEL);
if (!new_slave) {
res = -ENOMEM;
goto err_undo_flags;
}
memset(new_slave, 0, sizeof(struct slave));
/* save slave's original flags before calling
* netdev_set_master and dev_open
*/
......
......@@ -1343,15 +1343,12 @@ static int __init slip_init(void)
printk(KERN_INFO "SLIP linefill/keepalive option.\n");
#endif
slip_devs = kmalloc(sizeof(struct net_device *)*slip_maxdev, GFP_KERNEL);
slip_devs = kzalloc(sizeof(struct net_device *)*slip_maxdev, GFP_KERNEL);
if (!slip_devs) {
printk(KERN_ERR "SLIP: Can't allocate slip devices array! Uaargh! (-> No SLIP available)\n");
return -ENOMEM;
}
/* Clear the pointer array, we allocate devices when we need them */
memset(slip_devs, 0, sizeof(struct net_device *)*slip_maxdev);
/* Fill in our line protocol discipline, and register it */
if ((status = tty_register_ldisc(N_SLIP, &sl_ldisc)) != 0) {
printk(KERN_ERR "SLIP: can't register line discipline (err = %d)\n", status);
......
......@@ -3380,7 +3380,7 @@ static int tg3_rx(struct tg3 *tp, int budget)
}
next_pkt_nopost:
sw_idx++;
sw_idx %= TG3_RX_RCB_RING_SIZE(tp);
sw_idx &= (TG3_RX_RCB_RING_SIZE(tp) - 1);
/* Refresh hw_idx to see if there is new work */
if (sw_idx == hw_idx) {
......
......@@ -3,7 +3,7 @@
*
* Character device driver for reading z/VM *MONITOR service records.
*
* Copyright (C) 2004 IBM Corporation, IBM Deutschland Entwicklung GmbH.
* Copyright 2004 IBM Corporation, IBM Deutschland Entwicklung GmbH.
*
* Author: Gerald Schaefer <geraldsc@de.ibm.com>
*/
......@@ -22,7 +22,7 @@
#include <asm/ebcdic.h>
#include <asm/extmem.h>
#include <linux/poll.h>
#include "../net/iucv.h"
#include <net/iucv/iucv.h>
//#define MON_DEBUG /* Debug messages on/off */
......@@ -50,14 +50,13 @@ static char mon_dcss_name[9] = "MONDCSS\0";
struct mon_msg {
u32 pos;
u32 mca_offset;
iucv_MessagePending local_eib;
struct iucv_message msg;
char msglim_reached;
char replied_msglim;
};
struct mon_private {
u16 pathid;
iucv_handle_t iucv_handle;
struct iucv_path *path;
struct mon_msg *msg_array[MON_MSGLIM];
unsigned int write_index;
unsigned int read_index;
......@@ -75,8 +74,6 @@ static unsigned long mon_dcss_end;
static DECLARE_WAIT_QUEUE_HEAD(mon_read_wait_queue);
static DECLARE_WAIT_QUEUE_HEAD(mon_conn_wait_queue);
static u8 iucv_host[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static u8 user_data_connect[16] = {
/* Version code, must be 0x01 for shared mode */
0x01,
......@@ -100,8 +97,7 @@ static u8 user_data_sever[16] = {
* Create the 8 bytes EBCDIC DCSS segment name from
* an ASCII name, incl. padding
*/
static inline void
dcss_mkname(char *ascii_name, char *ebcdic_name)
static inline void dcss_mkname(char *ascii_name, char *ebcdic_name)
{
int i;
......@@ -119,8 +115,7 @@ dcss_mkname(char *ascii_name, char *ebcdic_name)
* print appropriate error message for segment_load()/segment_type()
* return code
*/
static void
mon_segment_warn(int rc, char* seg_name)
static void mon_segment_warn(int rc, char* seg_name)
{
switch (rc) {
case -ENOENT:
......@@ -166,44 +161,37 @@ mon_segment_warn(int rc, char* seg_name)
}
}
static inline unsigned long
mon_mca_start(struct mon_msg *monmsg)
static inline unsigned long mon_mca_start(struct mon_msg *monmsg)
{
return monmsg->local_eib.ln1msg1.iprmmsg1_u32;
return *(u32 *) &monmsg->msg.rmmsg;
}
static inline unsigned long
mon_mca_end(struct mon_msg *monmsg)
static inline unsigned long mon_mca_end(struct mon_msg *monmsg)
{
return monmsg->local_eib.ln1msg2.ipbfln1f;
return *(u32 *) &monmsg->msg.rmmsg[4];
}
static inline u8
mon_mca_type(struct mon_msg *monmsg, u8 index)
static inline u8 mon_mca_type(struct mon_msg *monmsg, u8 index)
{
return *((u8 *) mon_mca_start(monmsg) + monmsg->mca_offset + index);
}
static inline u32
mon_mca_size(struct mon_msg *monmsg)
static inline u32 mon_mca_size(struct mon_msg *monmsg)
{
return mon_mca_end(monmsg) - mon_mca_start(monmsg) + 1;
}
static inline u32
mon_rec_start(struct mon_msg *monmsg)
static inline u32 mon_rec_start(struct mon_msg *monmsg)
{
return *((u32 *) (mon_mca_start(monmsg) + monmsg->mca_offset + 4));
}
static inline u32
mon_rec_end(struct mon_msg *monmsg)
static inline u32 mon_rec_end(struct mon_msg *monmsg)
{
return *((u32 *) (mon_mca_start(monmsg) + monmsg->mca_offset + 8));
}
static inline int
mon_check_mca(struct mon_msg *monmsg)
static inline int mon_check_mca(struct mon_msg *monmsg)
{
if ((mon_rec_end(monmsg) <= mon_rec_start(monmsg)) ||
(mon_rec_start(monmsg) < mon_dcss_start) ||
......@@ -221,20 +209,17 @@ mon_check_mca(struct mon_msg *monmsg)
return 0;
}
static inline int
mon_send_reply(struct mon_msg *monmsg, struct mon_private *monpriv)
static inline int mon_send_reply(struct mon_msg *monmsg,
struct mon_private *monpriv)
{
u8 prmmsg[8];
int rc;
P_DEBUG("read, REPLY: pathid = 0x%04X, msgid = 0x%08X, trgcls = "
"0x%08X\n\n",
monmsg->local_eib.ippathid, monmsg->local_eib.ipmsgid,
monmsg->local_eib.iptrgcls);
rc = iucv_reply_prmmsg(monmsg->local_eib.ippathid,
monmsg->local_eib.ipmsgid,
monmsg->local_eib.iptrgcls,
0, prmmsg);
monpriv->path->pathid, monmsg->msg.id, monmsg->msg.class);
rc = iucv_message_reply(monpriv->path, &monmsg->msg,
IUCV_IPRMDATA, NULL, 0);
atomic_dec(&monpriv->msglim_count);
if (likely(!monmsg->msglim_reached)) {
monmsg->pos = 0;
......@@ -251,10 +236,19 @@ mon_send_reply(struct mon_msg *monmsg, struct mon_private *monpriv)
return 0;
}
static inline struct mon_private *
mon_alloc_mem(void)
static inline void mon_free_mem(struct mon_private *monpriv)
{
int i;
for (i = 0; i < MON_MSGLIM; i++)
if (monpriv->msg_array[i])
kfree(monpriv->msg_array[i]);
kfree(monpriv);
}
static inline struct mon_private *mon_alloc_mem(void)
{
int i,j;
int i;
struct mon_private *monpriv;
monpriv = kzalloc(sizeof(struct mon_private), GFP_KERNEL);
......@@ -267,16 +261,15 @@ mon_alloc_mem(void)
GFP_KERNEL);
if (!monpriv->msg_array[i]) {
P_ERROR("open, no memory for msg_array\n");
for (j = 0; j < i; j++)
kfree(monpriv->msg_array[j]);
mon_free_mem(monpriv);
return NULL;
}
}
return monpriv;
}
static inline void
mon_read_debug(struct mon_msg *monmsg, struct mon_private *monpriv)
static inline void mon_read_debug(struct mon_msg *monmsg,
struct mon_private *monpriv)
{
#ifdef MON_DEBUG
u8 msg_type[2], mca_type;
......@@ -284,7 +277,7 @@ mon_read_debug(struct mon_msg *monmsg, struct mon_private *monpriv)
records_len = mon_rec_end(monmsg) - mon_rec_start(monmsg) + 1;
memcpy(msg_type, &monmsg->local_eib.iptrgcls, 2);
memcpy(msg_type, &monmsg->msg.class, 2);
EBCASC(msg_type, 2);
mca_type = mon_mca_type(monmsg, 0);
EBCASC(&mca_type, 1);
......@@ -292,8 +285,7 @@ mon_read_debug(struct mon_msg *monmsg, struct mon_private *monpriv)
P_DEBUG("read, mon_read_index = %i, mon_write_index = %i\n",
monpriv->read_index, monpriv->write_index);
P_DEBUG("read, pathid = 0x%04X, msgid = 0x%08X, trgcls = 0x%08X\n",
monmsg->local_eib.ippathid, monmsg->local_eib.ipmsgid,
monmsg->local_eib.iptrgcls);
monpriv->path->pathid, monmsg->msg.id, monmsg->msg.class);
P_DEBUG("read, msg_type = '%c%c', mca_type = '%c' / 0x%X / 0x%X\n",
msg_type[0], msg_type[1], mca_type ? mca_type : 'X',
mon_mca_type(monmsg, 1), mon_mca_type(monmsg, 2));
......@@ -306,8 +298,7 @@ mon_read_debug(struct mon_msg *monmsg, struct mon_private *monpriv)
#endif
}
static inline void
mon_next_mca(struct mon_msg *monmsg)
static inline void mon_next_mca(struct mon_msg *monmsg)
{
if (likely((mon_mca_size(monmsg) - monmsg->mca_offset) == 12))
return;
......@@ -316,8 +307,7 @@ mon_next_mca(struct mon_msg *monmsg)
monmsg->pos = 0;
}
static inline struct mon_msg *
mon_next_message(struct mon_private *monpriv)
static inline struct mon_msg *mon_next_message(struct mon_private *monpriv)
{
struct mon_msg *monmsg;
......@@ -342,39 +332,37 @@ mon_next_message(struct mon_private *monpriv)
/******************************************************************************
* IUCV handler *
*****************************************************************************/
static void
mon_iucv_ConnectionComplete(iucv_ConnectionComplete *eib, void *pgm_data)
static void mon_iucv_path_complete(struct iucv_path *path, u8 ipuser[16])
{
struct mon_private *monpriv = (struct mon_private *) pgm_data;
struct mon_private *monpriv = path->private;
P_DEBUG("IUCV connection completed\n");
P_DEBUG("IUCV ACCEPT (from *MONITOR): Version = 0x%02X, Event = "
"0x%02X, Sample = 0x%02X\n",
eib->ipuser[0], eib->ipuser[1], eib->ipuser[2]);
ipuser[0], ipuser[1], ipuser[2]);
atomic_set(&monpriv->iucv_connected, 1);
wake_up(&mon_conn_wait_queue);
}
static void
mon_iucv_ConnectionSevered(iucv_ConnectionSevered *eib, void *pgm_data)
static void mon_iucv_path_severed(struct iucv_path *path, u8 ipuser[16])
{
struct mon_private *monpriv = (struct mon_private *) pgm_data;
struct mon_private *monpriv = path->private;
P_ERROR("IUCV connection severed with rc = 0x%X\n",
(u8) eib->ipuser[0]);
P_ERROR("IUCV connection severed with rc = 0x%X\n", ipuser[0]);
iucv_path_sever(path, NULL);
atomic_set(&monpriv->iucv_severed, 1);
wake_up(&mon_conn_wait_queue);
wake_up_interruptible(&mon_read_wait_queue);
}
static void
mon_iucv_MessagePending(iucv_MessagePending *eib, void *pgm_data)
static void mon_iucv_message_pending(struct iucv_path *path,
struct iucv_message *msg)
{
struct mon_private *monpriv = (struct mon_private *) pgm_data;
struct mon_private *monpriv = path->private;
P_DEBUG("IUCV message pending\n");
memcpy(&monpriv->msg_array[monpriv->write_index]->local_eib, eib,
sizeof(iucv_MessagePending));
memcpy(&monpriv->msg_array[monpriv->write_index]->msg,
msg, sizeof(*msg));
if (atomic_inc_return(&monpriv->msglim_count) == MON_MSGLIM) {
P_WARNING("IUCV message pending, message limit (%i) reached\n",
MON_MSGLIM);
......@@ -385,54 +373,45 @@ mon_iucv_MessagePending(iucv_MessagePending *eib, void *pgm_data)
wake_up_interruptible(&mon_read_wait_queue);
}
static iucv_interrupt_ops_t mon_iucvops = {
.ConnectionComplete = mon_iucv_ConnectionComplete,
.ConnectionSevered = mon_iucv_ConnectionSevered,
.MessagePending = mon_iucv_MessagePending,
static struct iucv_handler monreader_iucv_handler = {
.path_complete = mon_iucv_path_complete,
.path_severed = mon_iucv_path_severed,
.message_pending = mon_iucv_message_pending,
};
/******************************************************************************
* file operations *
*****************************************************************************/
static int
mon_open(struct inode *inode, struct file *filp)
static int mon_open(struct inode *inode, struct file *filp)
{
int rc, i;
struct mon_private *monpriv;
int rc;
/*
* only one user allowed
*/
rc = -EBUSY;
if (test_and_set_bit(MON_IN_USE, &mon_in_use))
return -EBUSY;
goto out;
rc = -ENOMEM;
monpriv = mon_alloc_mem();
if (!monpriv)
return -ENOMEM;
goto out_use;
/*
* Register with IUCV and connect to *MONITOR service
* Connect to *MONITOR service
*/
monpriv->iucv_handle = iucv_register_program("my_monreader ",
MON_SERVICE,
NULL,
&mon_iucvops,
monpriv);
if (!monpriv->iucv_handle) {
P_ERROR("failed to register with iucv driver\n");
rc = -EIO;
goto out_error;
}
P_INFO("open, registered with IUCV\n");
rc = iucv_connect(&monpriv->pathid, MON_MSGLIM, user_data_connect,
MON_SERVICE, iucv_host, IPRMDATA, NULL, NULL,
monpriv->iucv_handle, NULL);
monpriv->path = iucv_path_alloc(MON_MSGLIM, IUCV_IPRMDATA, GFP_KERNEL);
if (!monpriv->path)
goto out_priv;
rc = iucv_path_connect(monpriv->path, &monreader_iucv_handler,
MON_SERVICE, NULL, user_data_connect, monpriv);
if (rc) {
P_ERROR("iucv connection to *MONITOR failed with "
"IPUSER SEVER code = %i\n", rc);
rc = -EIO;
goto out_unregister;
goto out_path;
}
/*
* Wait for connection confirmation
......@@ -444,24 +423,23 @@ mon_open(struct inode *inode, struct file *filp)
atomic_set(&monpriv->iucv_severed, 0);
atomic_set(&monpriv->iucv_connected, 0);
rc = -EIO;
goto out_unregister;
goto out_path;
}
P_INFO("open, established connection to *MONITOR service\n\n");
filp->private_data = monpriv;
return nonseekable_open(inode, filp);
out_unregister:
iucv_unregister_program(monpriv->iucv_handle);
out_error:
for (i = 0; i < MON_MSGLIM; i++)
kfree(monpriv->msg_array[i]);
kfree(monpriv);
out_path:
kfree(monpriv->path);
out_priv:
mon_free_mem(monpriv);
out_use:
clear_bit(MON_IN_USE, &mon_in_use);
out:
return rc;
}
static int
mon_close(struct inode *inode, struct file *filp)
static int mon_close(struct inode *inode, struct file *filp)
{
int rc, i;
struct mon_private *monpriv = filp->private_data;
......@@ -469,18 +447,12 @@ mon_close(struct inode *inode, struct file *filp)
/*
* Close IUCV connection and unregister
*/
rc = iucv_sever(monpriv->pathid, user_data_sever);
rc = iucv_path_sever(monpriv->path, user_data_sever);
if (rc)
P_ERROR("close, iucv_sever failed with rc = %i\n", rc);
else
P_INFO("close, terminated connection to *MONITOR service\n");
rc = iucv_unregister_program(monpriv->iucv_handle);
if (rc)
P_ERROR("close, iucv_unregister failed with rc = %i\n", rc);
else
P_INFO("close, unregistered with IUCV\n");
atomic_set(&monpriv->iucv_severed, 0);
atomic_set(&monpriv->iucv_connected, 0);
atomic_set(&monpriv->read_ready, 0);
......@@ -495,8 +467,8 @@ mon_close(struct inode *inode, struct file *filp)
return 0;
}
static ssize_t
mon_read(struct file *filp, char __user *data, size_t count, loff_t *ppos)
static ssize_t mon_read(struct file *filp, char __user *data,
size_t count, loff_t *ppos)
{
struct mon_private *monpriv = filp->private_data;
struct mon_msg *monmsg;
......@@ -563,8 +535,7 @@ mon_read(struct file *filp, char __user *data, size_t count, loff_t *ppos)
return count;
}
static unsigned int
mon_poll(struct file *filp, struct poll_table_struct *p)
static unsigned int mon_poll(struct file *filp, struct poll_table_struct *p)
{
struct mon_private *monpriv = filp->private_data;
......@@ -593,8 +564,7 @@ static struct miscdevice mon_dev = {
/******************************************************************************
* module init/exit *
*****************************************************************************/
static int __init
mon_init(void)
static int __init mon_init(void)
{
int rc;
......@@ -603,22 +573,34 @@ mon_init(void)
return -ENODEV;
}
/*
* Register with IUCV and connect to *MONITOR service
*/
rc = iucv_register(&monreader_iucv_handler, 1);
if (rc) {
P_ERROR("failed to register with iucv driver\n");
return rc;
}
P_INFO("open, registered with IUCV\n");
rc = segment_type(mon_dcss_name);
if (rc < 0) {
mon_segment_warn(rc, mon_dcss_name);
return rc;
goto out_iucv;
}
if (rc != SEG_TYPE_SC) {
P_ERROR("segment %s has unsupported type, should be SC\n",
mon_dcss_name);
return -EINVAL;
rc = -EINVAL;
goto out_iucv;
}
rc = segment_load(mon_dcss_name, SEGMENT_SHARED,
&mon_dcss_start, &mon_dcss_end);
if (rc < 0) {
mon_segment_warn(rc, mon_dcss_name);
return -EINVAL;
rc = -EINVAL;
goto out_iucv;
}
dcss_mkname(mon_dcss_name, &user_data_connect[8]);
......@@ -634,14 +616,16 @@ mon_init(void)
out:
segment_unload(mon_dcss_name);
out_iucv:
iucv_unregister(&monreader_iucv_handler, 1);
return rc;
}
static void __exit
mon_exit(void)
static void __exit mon_exit(void)
{
segment_unload(mon_dcss_name);
WARN_ON(misc_deregister(&mon_dev) != 0);
iucv_unregister(&monreader_iucv_handler, 1);
return;
}
......
此差异已折叠。
......@@ -22,13 +22,6 @@ config CTC
available. This option is also available as a module which will be
called ctc.ko. If you do not know what it is, it's safe to say "Y".
config IUCV
tristate "IUCV support (VM only)"
help
Select this option if you want to use inter-user communication
under VM or VIF. If unsure, say "Y" to enable a fast communication
link between VM guests.
config NETIUCV
tristate "IUCV network device support (VM only)"
depends on IUCV && NETDEVICES
......
......@@ -4,7 +4,6 @@
ctc-objs := ctcmain.o ctcdbug.o
obj-$(CONFIG_IUCV) += iucv.o
obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o
obj-$(CONFIG_SMSGIUCV) += smsgiucv.o
obj-$(CONFIG_CTC) += ctc.o fsm.o cu3088.o
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -828,9 +828,7 @@ int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat)
mutex_unlock(&crypt_stat->cs_tfm_mutex);
goto out;
}
crypto_blkcipher_set_flags(crypt_stat->tfm,
(ECRYPTFS_DEFAULT_CHAINING_MODE
| CRYPTO_TFM_REQ_WEAK_KEY));
crypto_blkcipher_set_flags(crypt_stat->tfm, CRYPTO_TFM_REQ_WEAK_KEY);
mutex_unlock(&crypt_stat->cs_tfm_mutex);
rc = 0;
out:
......
......@@ -176,7 +176,6 @@ ecryptfs_get_key_payload_data(struct key *key)
#define ECRYPTFS_FILE_SIZE_BYTES 8
#define ECRYPTFS_DEFAULT_CIPHER "aes"
#define ECRYPTFS_DEFAULT_KEY_BYTES 16
#define ECRYPTFS_DEFAULT_CHAINING_MODE CRYPTO_TFM_MODE_CBC
#define ECRYPTFS_DEFAULT_HASH "md5"
#define ECRYPTFS_TAG_3_PACKET_TYPE 0x8C
#define ECRYPTFS_TAG_11_PACKET_TYPE 0xED
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册