aboutsummaryrefslogtreecommitdiff
path: root/arch/s390
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/Kconfig17
-rw-r--r--arch/s390/appldata/appldata.h16
-rw-r--r--arch/s390/appldata/appldata_base.c81
-rw-r--r--arch/s390/appldata/appldata_os.c1
-rw-r--r--arch/s390/crypto/aes_s390.c285
-rw-r--r--arch/s390/crypto/crypt_s390.h3
-rw-r--r--arch/s390/crypto/des_s390.c559
-rw-r--r--arch/s390/crypto/sha1_s390.c2
-rw-r--r--arch/s390/crypto/sha256_s390.c2
-rw-r--r--arch/s390/defconfig1
-rw-r--r--arch/s390/hypfs/hypfs.h2
-rw-r--r--arch/s390/hypfs/hypfs_diag.c16
-rw-r--r--arch/s390/hypfs/hypfs_diag.h2
-rw-r--r--arch/s390/hypfs/inode.c12
-rw-r--r--arch/s390/kernel/Makefile3
-rw-r--r--arch/s390/kernel/entry.S12
-rw-r--r--arch/s390/kernel/entry64.S16
-rw-r--r--arch/s390/kernel/head.S69
-rw-r--r--arch/s390/kernel/head31.S48
-rw-r--r--arch/s390/kernel/head64.S59
-rw-r--r--arch/s390/kernel/ipl.c942
-rw-r--r--arch/s390/kernel/kprobes.c657
-rw-r--r--arch/s390/kernel/reipl.S33
-rw-r--r--arch/s390/kernel/reipl64.S34
-rw-r--r--arch/s390/kernel/reipl_diag.c39
-rw-r--r--arch/s390/kernel/s390_ksyms.c6
-rw-r--r--arch/s390/kernel/setup.c272
-rw-r--r--arch/s390/kernel/signal.c40
-rw-r--r--arch/s390/kernel/smp.c10
-rw-r--r--arch/s390/kernel/traps.c31
-rw-r--r--arch/s390/kernel/vmlinux.lds.S3
-rw-r--r--arch/s390/lib/Makefile4
-rw-r--r--arch/s390/lib/uaccess.S211
-rw-r--r--arch/s390/lib/uaccess64.S207
-rw-r--r--arch/s390/lib/uaccess_mvcos.c156
-rw-r--r--arch/s390/lib/uaccess_std.c340
-rw-r--r--arch/s390/mm/cmm.c30
-rw-r--r--arch/s390/mm/fault.c40
-rw-r--r--arch/s390/mm/init.c36
39 files changed, 3031 insertions, 1266 deletions
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 2f4f70c4dbb..b216ca659cd 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -460,8 +460,7 @@ config S390_HYPFS_FS
information in an s390 hypervisor environment.
config KEXEC
- bool "kexec system call (EXPERIMENTAL)"
- depends on EXPERIMENTAL
+ bool "kexec system call"
help
kexec is a system call that implements the ability to shutdown your
current kernel, and to start another kernel. It is like a reboot
@@ -487,8 +486,22 @@ source "drivers/net/Kconfig"
source "fs/Kconfig"
+menu "Instrumentation Support"
+
source "arch/s390/oprofile/Kconfig"
+config KPROBES
+ bool "Kprobes (EXPERIMENTAL)"
+ depends on EXPERIMENTAL && MODULES
+ help
+ Kprobes allows you to trap at almost any kernel address and
+ execute a callback function. register_kprobe() establishes
+ a probepoint and specifies the callback. Kprobes is useful
+ for kernel debugging, non-intrusive instrumentation and testing.
+ If in doubt, say "N".
+
+endmenu
+
source "arch/s390/Kconfig.debug"
source "security/Kconfig"
diff --git a/arch/s390/appldata/appldata.h b/arch/s390/appldata/appldata.h
index 71d65eb3065..0429481dea6 100644
--- a/arch/s390/appldata/appldata.h
+++ b/arch/s390/appldata/appldata.h
@@ -29,22 +29,6 @@
#define CTL_APPLDATA_NET_SUM 2125
#define CTL_APPLDATA_PROC 2126
-#ifndef CONFIG_64BIT
-
-#define APPLDATA_START_INTERVAL_REC 0x00 /* Function codes for */
-#define APPLDATA_STOP_REC 0x01 /* DIAG 0xDC */
-#define APPLDATA_GEN_EVENT_RECORD 0x02
-#define APPLDATA_START_CONFIG_REC 0x03
-
-#else
-
-#define APPLDATA_START_INTERVAL_REC 0x80
-#define APPLDATA_STOP_REC 0x81
-#define APPLDATA_GEN_EVENT_RECORD 0x82
-#define APPLDATA_START_CONFIG_REC 0x83
-
-#endif /* CONFIG_64BIT */
-
#define P_INFO(x...) printk(KERN_INFO MY_PRINT_NAME " info: " x)
#define P_ERROR(x...) printk(KERN_ERR MY_PRINT_NAME " error: " x)
#define P_WARNING(x...) printk(KERN_WARNING MY_PRINT_NAME " status: " x)
diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c
index a0a94e0ef8d..b69ed742f98 100644
--- a/arch/s390/appldata/appldata_base.c
+++ b/arch/s390/appldata/appldata_base.c
@@ -14,20 +14,20 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/errno.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/smp.h>
#include <linux/interrupt.h>
#include <linux/proc_fs.h>
#include <linux/page-flags.h>
#include <linux/swap.h>
#include <linux/pagemap.h>
#include <linux/sysctl.h>
-#include <asm/timer.h>
-//#include <linux/kernel_stat.h>
#include <linux/notifier.h>
#include <linux/cpu.h>
#include <linux/workqueue.h>
+#include <asm/appldata.h>
+#include <asm/timer.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/smp.h>
#include "appldata.h"
@@ -39,34 +39,6 @@
#define TOD_MICRO 0x01000 /* nr. of TOD clock units
for 1 microsecond */
-
-/*
- * Parameter list for DIAGNOSE X'DC'
- */
-#ifndef CONFIG_64BIT
-struct appldata_parameter_list {
- u16 diag; /* The DIAGNOSE code X'00DC' */
- u8 function; /* The function code for the DIAGNOSE */
- u8 parlist_length; /* Length of the parameter list */
- u32 product_id_addr; /* Address of the 16-byte product ID */
- u16 reserved;
- u16 buffer_length; /* Length of the application data buffer */
- u32 buffer_addr; /* Address of the application data buffer */
-};
-#else
-struct appldata_parameter_list {
- u16 diag;
- u8 function;
- u8 parlist_length;
- u32 unused01;
- u16 reserved;
- u16 buffer_length;
- u32 unused02;
- u64 product_id_addr;
- u64 buffer_addr;
-};
-#endif /* CONFIG_64BIT */
-
/*
* /proc entries (sysctl)
*/
@@ -181,46 +153,17 @@ static void appldata_work_fn(void *data)
int appldata_diag(char record_nr, u16 function, unsigned long buffer,
u16 length, char *mod_lvl)
{
- unsigned long ry;
- struct appldata_product_id {
- char prod_nr[7]; /* product nr. */
- char prod_fn[2]; /* product function */
- char record_nr; /* record nr. */
- char version_nr[2]; /* version */
- char release_nr[2]; /* release */
- char mod_lvl[2]; /* modification lvl. */
- } appldata_product_id = {
- /* all strings are EBCDIC, record_nr is byte */
+ struct appldata_product_id id = {
.prod_nr = {0xD3, 0xC9, 0xD5, 0xE4,
- 0xE7, 0xD2, 0xD9}, /* "LINUXKR" */
- .prod_fn = {0xD5, 0xD3}, /* "NL" */
+ 0xE7, 0xD2, 0xD9}, /* "LINUXKR" */
+ .prod_fn = 0xD5D3, /* "NL" */
.record_nr = record_nr,
- .version_nr = {0xF2, 0xF6}, /* "26" */
- .release_nr = {0xF0, 0xF1}, /* "01" */
- .mod_lvl = {mod_lvl[0], mod_lvl[1]},
- };
- struct appldata_parameter_list appldata_parameter_list = {
- .diag = 0xDC,
- .function = function,
- .parlist_length =
- sizeof(appldata_parameter_list),
- .buffer_length = length,
- .product_id_addr =
- (unsigned long) &appldata_product_id,
- .buffer_addr = virt_to_phys((void *) buffer)
+ .version_nr = 0xF2F6, /* "26" */
+ .release_nr = 0xF0F1, /* "01" */
+ .mod_lvl = (mod_lvl[0]) << 8 | mod_lvl[1],
};
- if (!MACHINE_IS_VM)
- return -ENOSYS;
- ry = -1;
- asm volatile(
- "diag %1,%0,0xDC\n\t"
- : "=d" (ry)
- : "d" (&appldata_parameter_list),
- "m" (appldata_parameter_list),
- "m" (appldata_product_id)
- : "cc");
- return (int) ry;
+ return appldata_asm(&id, function, (void *) buffer, length);
}
/************************ timer, work, DIAG <END> ****************************/
diff --git a/arch/s390/appldata/appldata_os.c b/arch/s390/appldata/appldata_os.c
index 161acc5c8a1..76a15523ae9 100644
--- a/arch/s390/appldata/appldata_os.c
+++ b/arch/s390/appldata/appldata_os.c
@@ -16,6 +16,7 @@
#include <linux/kernel_stat.h>
#include <linux/netdevice.h>
#include <linux/sched.h>
+#include <asm/appldata.h>
#include <asm/smp.h>
#include "appldata.h"
diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c
index 5713c7e5bd1..15c9eec0292 100644
--- a/arch/s390/crypto/aes_s390.c
+++ b/arch/s390/crypto/aes_s390.c
@@ -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,133 +113,206 @@ 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);
+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),
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(aes_alg.cra_list),
+ .cra_u = {
+ .cipher = {
+ .cia_min_keysize = AES_MIN_KEY_SIZE,
+ .cia_max_keysize = AES_MAX_KEY_SIZE,
+ .cia_setkey = aes_set_key,
+ .cia_encrypt = aes_encrypt,
+ .cia_decrypt = aes_decrypt,
+ }
+ }
+};
+
+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 (sctx->key_len) {
+ switch (key_len) {
case 16:
- ret = crypt_s390_km(KM_AES_128_ENCRYPT, &sctx->key, out, in, nbytes);
- BUG_ON((ret < 0) || (ret != nbytes));
+ sctx->enc = KM_AES_128_ENCRYPT;
+ sctx->dec = KM_AES_128_DECRYPT;
break;
case 24:
- ret = crypt_s390_km(KM_AES_192_ENCRYPT, &sctx->key, out, in, nbytes);
- BUG_ON((ret < 0) || (ret != nbytes));
+ sctx->enc = KM_AES_192_ENCRYPT;
+ sctx->dec = KM_AES_192_DECRYPT;
break;
case 32:
- ret = crypt_s390_km(KM_AES_256_ENCRYPT, &sctx->key, out, in, nbytes);
- BUG_ON((ret < 0) || (ret != nbytes));
+ sctx->enc = KM_AES_256_ENCRYPT;
+ sctx->dec = KM_AES_256_DECRYPT;
break;
}
- return nbytes;
+
+ return aes_set_key(tfm, in_key, key_len);
}
-static unsigned int aes_decrypt_ecb(const struct cipher_desc *desc, u8 *out,
- const u8 *in, unsigned int nbytes)
+static int ecb_aes_crypt(struct blkcipher_desc *desc, long func, void *param,
+ struct blkcipher_walk *walk)
{
- struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm);
- int ret;
+ int ret = blkcipher_walk_virt(desc, walk);
+ unsigned int nbytes;
- /* only use complete blocks */
- nbytes &= ~(AES_BLOCK_SIZE - 1);
+ 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;
- 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;
+ 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 nbytes;
+
+ return ret;
}
-static unsigned int aes_encrypt_cbc(const struct cipher_desc *desc, u8 *out,
- const u8 *in, unsigned int nbytes)
+static int ecb_aes_encrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
{
- struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm);
- int ret;
+ struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
- /* only use complete blocks */
- nbytes &= ~(AES_BLOCK_SIZE - 1);
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ return ecb_aes_crypt(desc, sctx->enc, sctx->key, &walk);
+}
- memcpy(&sctx->iv, desc->info, AES_BLOCK_SIZE);
- switch (sctx->key_len) {
+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:
- ret = crypt_s390_kmc(KMC_AES_128_ENCRYPT, &sctx->iv, out, in, nbytes);
- BUG_ON((ret < 0) || (ret != nbytes));
+ sctx->enc = KMC_AES_128_ENCRYPT;
+ sctx->dec = KMC_AES_128_DECRYPT;
break;
case 24:
- ret = crypt_s390_kmc(KMC_AES_192_ENCRYPT, &sctx->iv, out, in, nbytes);
- BUG_ON((ret < 0) || (ret != nbytes));
+ sctx->enc = KMC_AES_192_ENCRYPT;
+ sctx->dec = KMC_AES_192_DECRYPT;
break;
case 32:
- ret = crypt_s390_kmc(KMC_AES_256_ENCRYPT, &sctx->iv, out, in, nbytes);
- BUG_ON((ret < 0) || (ret != nbytes));
+ sctx->enc = KMC_AES_256_ENCRYPT;
+ sctx->dec = KMC_AES_256_DECRYPT;
break;
}
- memcpy(desc->info, &sctx->iv, AES_BLOCK_SIZE);
- return nbytes;
+ return aes_set_key(tfm, in_key, key_len);
}
-static unsigned int aes_decrypt_cbc(const struct cipher_desc *desc, u8 *out,
- const u8 *in, unsigned int nbytes)
+static int cbc_aes_crypt(struct blkcipher_desc *desc, long func, void *param,
+ struct blkcipher_walk *walk)
{
- struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm);
- int ret;
+ int ret = blkcipher_walk_virt(desc, walk);
+ unsigned int nbytes = walk->nbytes;
- /* only use complete blocks */
- nbytes &= ~(AES_BLOCK_SIZE - 1);
+ if (!nbytes)
+ goto out;
- 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;
+ 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;
-static struct crypto_alg aes_alg = {
- .cra_name = "aes",
- .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
+ 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(aes_alg.cra_list),
+ .cra_list = LIST_HEAD_INIT(cbc_aes_alg.cra_list),
.cra_u = {
- .cipher = {
- .cia_min_keysize = AES_MIN_KEY_SIZE,
- .cia_max_keysize = AES_MAX_KEY_SIZE,
- .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,
+ .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);
}
diff --git a/arch/s390/crypto/crypt_s390.h b/arch/s390/crypto/crypt_s390.h
index d1c259a7fe3..efd836c2e4a 100644
--- a/arch/s390/crypto/crypt_s390.h
+++ b/arch/s390/crypto/crypt_s390.h
@@ -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,
diff --git a/arch/s390/crypto/des_s390.c b/arch/s390/crypto/des_s390.c
index b3f7496a79b..2aba04852fe 100644
--- a/arch/s390/crypto/des_s390.c
+++ b/arch/s390/crypto/des_s390.c
@@ -13,9 +13,10 @@
* (at your option) any later version.
*
*/
+
+#include <crypto/algapi.h>
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/crypto.h>
#include "crypt_s390.h"
#include "crypto_des.h"
@@ -45,9 +46,10 @@ struct crypt_s390_des3_192_ctx {
};
static int des_setkey(struct crypto_tfm *tfm, const u8 *key,
- unsigned int keylen, u32 *flags)
+ unsigned int keylen)
{
struct crypt_s390_des_ctx *dctx = crypto_tfm_ctx(tfm);
+ u32 *flags = &tfm->crt_flags;
int ret;
/* test if key is valid (not a weak key) */
@@ -71,85 +73,159 @@ static void des_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
crypt_s390_km(KM_DEA_DECRYPT, dctx->key, out, in, DES_BLOCK_SIZE);
}
-static unsigned int des_encrypt_ecb(const struct cipher_desc *desc, u8 *out,
- const u8 *in, unsigned int nbytes)
+static struct crypto_alg des_alg = {
+ .cra_name = "des",
+ .cra_driver_name = "des-s390",
+ .cra_priority = CRYPT_S390_PRIORITY,
+ .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
+ .cra_blocksize = DES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct crypt_s390_des_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(des_alg.cra_list),
+ .cra_u = {
+ .cipher = {
+ .cia_min_keysize = DES_KEY_SIZE,
+ .cia_max_keysize = DES_KEY_SIZE,
+ .cia_setkey = des_setkey,
+ .cia_encrypt = des_encrypt,
+ .cia_decrypt = des_decrypt,
+ }
+ }
+};
+
+static int ecb_desall_crypt(struct blkcipher_desc *desc, long func,
+ void *param, struct blkcipher_walk *walk)
{
- struct crypt_s390_des_ctx *sctx = crypto_tfm_ctx(desc->tfm);
- int ret;
+ int ret = blkcipher_walk_virt(desc, walk);
+ unsigned int nbytes;
+
+ while ((nbytes = walk->nbytes)) {
+ /* only use complete blocks */
+ unsigned int n = nbytes & ~(DES_BLOCK_SIZE - 1);
+ u8 *out = walk->dst.virt.addr;
+ u8 *in = walk->src.virt.addr;
- /* only use complete blocks */
- nbytes &= ~(DES_BLOCK_SIZE - 1);
- ret = crypt_s390_km(KM_DEA_ENCRYPT, sctx->key, out, in, nbytes);
- BUG_ON((ret < 0) || (ret != nbytes));
+ ret = crypt_s390_km(func, param, out, in, n);
+ BUG_ON((ret < 0) || (ret != n));
- return nbytes;
+ nbytes &= DES_BLOCK_SIZE - 1;
+ ret = blkcipher_walk_done(desc, walk, nbytes);
+ }
+
+ return ret;
}
-static unsigned int des_decrypt_ecb(const struct cipher_desc *desc, u8 *out,
- const u8 *in, unsigned int nbytes)
+static int cbc_desall_crypt(struct blkcipher_desc *desc, long func,
+ void *param, struct blkcipher_walk *walk)
{
- struct crypt_s390_des_ctx *sctx = crypto_tfm_ctx(desc->tfm);
- int ret;
+ int ret = blkcipher_walk_virt(desc, walk);
+ unsigned int nbytes = walk->nbytes;
+
+ if (!nbytes)
+ goto out;
+
+ memcpy(param, walk->iv, DES_BLOCK_SIZE);
+ do {
+ /* only use complete blocks */
+ unsigned int n = nbytes & ~(DES_BLOCK_SIZE - 1);
+ u8 *out = walk->dst.virt.addr;
+ u8 *in = walk->src.virt.addr;
- /* only use complete blocks */
- nbytes &= ~(DES_BLOCK_SIZE - 1);
- ret = crypt_s390_km(KM_DEA_DECRYPT, sctx->key, out, in, nbytes);
- BUG_ON((ret < 0) || (ret != nbytes));
+ ret = crypt_s390_kmc(func, param, out, in, n);
+ BUG_ON((ret < 0) || (ret != n));
- return nbytes;
+ nbytes &= DES_BLOCK_SIZE - 1;
+ ret = blkcipher_walk_done(desc, walk, nbytes);
+ } while ((nbytes = walk->nbytes));
+ memcpy(walk->iv, param, DES_BLOCK_SIZE);
+
+out:
+ return ret;
}
-static unsigned int des_encrypt_cbc(const struct cipher_desc *desc, u8 *out,
- const u8 *in, unsigned int nbytes)
+static int ecb_des_encrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
{
- struct crypt_s390_des_ctx *sctx = crypto_tfm_ctx(desc->tfm);
- int ret;
+ struct crypt_s390_des_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
- /* only use complete blocks */
- nbytes &= ~(DES_BLOCK_SIZE - 1);
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ return ecb_desall_crypt(desc, KM_DEA_ENCRYPT, sctx->key, &walk);
+}
- memcpy(sctx->iv, desc->info, DES_BLOCK_SIZE);
- ret = crypt_s390_kmc(KMC_DEA_ENCRYPT, &sctx->iv, out, in, nbytes);
- BUG_ON((ret < 0) || (ret != nbytes));
+static int ecb_des_decrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ struct crypt_s390_des_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
- memcpy(desc->info, sctx->iv, DES_BLOCK_SIZE);
- return nbytes;
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ return ecb_desall_crypt(desc, KM_DEA_DECRYPT, sctx->key, &walk);
}
-static unsigned int des_decrypt_cbc(const struct cipher_desc *desc, u8 *out,
- const u8 *in, unsigned int nbytes)
+static struct crypto_alg ecb_des_alg = {
+ .cra_name = "ecb(des)",
+ .cra_driver_name = "ecb-des-s390",
+ .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_blocksize = DES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct crypt_s390_des_ctx),
+ .cra_type = &crypto_blkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(ecb_des_alg.cra_list),
+ .cra_u = {
+ .blkcipher = {
+ .min_keysize = DES_KEY_SIZE,
+ .max_keysize = DES_KEY_SIZE,
+ .setkey = des_setkey,
+ .encrypt = ecb_des_encrypt,
+ .decrypt = ecb_des_decrypt,
+ }
+ }
+};
+
+static int cbc_des_encrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
{
- struct crypt_s390_des_ctx *sctx = crypto_tfm_ctx(desc->tfm);
- int ret;
+ struct crypt_s390_des_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
- /* only use complete blocks */
- nbytes &= ~(DES_BLOCK_SIZE - 1);
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ return cbc_desall_crypt(desc, KMC_DEA_ENCRYPT, sctx->iv, &walk);
+}
- memcpy(&sctx->iv, desc->info, DES_BLOCK_SIZE);
- ret = crypt_s390_kmc(KMC_DEA_DECRYPT, &sctx->iv, out, in, nbytes);
- BUG_ON((ret < 0) || (ret != nbytes));
+static int cbc_des_decrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ struct crypt_s390_des_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
- return nbytes;
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ return cbc_desall_crypt(desc, KMC_DEA_DECRYPT, sctx->iv, &walk);
}
-static struct crypto_alg des_alg = {
- .cra_name = "des",
- .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
+static struct crypto_alg cbc_des_alg = {
+ .cra_name = "cbc(des)",
+ .cra_driver_name = "cbc-des-s390",
+ .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
.cra_blocksize = DES_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct crypt_s390_des_ctx),
+ .cra_type = &crypto_blkcipher_type,
.cra_module = THIS_MODULE,
- .cra_list = LIST_HEAD_INIT(des_alg.cra_list),
+ .cra_list = LIST_HEAD_INIT(cbc_des_alg.cra_list),
.cra_u = {
- .cipher = {
- .cia_min_keysize = DES_KEY_SIZE,
- .cia_max_keysize = DES_KEY_SIZE,
- .cia_setkey = des_setkey,
- .cia_encrypt = des_encrypt,
- .cia_decrypt = des_decrypt,
- .cia_encrypt_ecb = des_encrypt_ecb,
- .cia_decrypt_ecb = des_decrypt_ecb,
- .cia_encrypt_cbc = des_encrypt_cbc,
- .cia_decrypt_cbc = des_decrypt_cbc,
+ .blkcipher =