aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/crypto/fsl-sec4.txt397
-rw-r--r--arch/powerpc/boot/dts/p4080ds.dts86
-rw-r--r--arch/s390/crypto/Makefile1
-rw-r--r--arch/s390/crypto/aes_s390.c383
-rw-r--r--arch/s390/crypto/crypt_s390.h112
-rw-r--r--arch/s390/crypto/des_check_key.c132
-rw-r--r--arch/s390/crypto/des_s390.c370
-rw-r--r--arch/s390/crypto/ghash_s390.c162
-rw-r--r--arch/s390/crypto/prng.c2
-rw-r--r--arch/s390/crypto/sha1_s390.c2
-rw-r--r--arch/s390/crypto/sha256_s390.c2
-rw-r--r--arch/s390/crypto/sha512_s390.c2
-rw-r--r--arch/x86/crypto/Makefile4
-rw-r--r--arch/x86/crypto/aesni-intel_glue.c9
-rw-r--r--arch/x86/crypto/fpu.c10
-rw-r--r--crypto/Kconfig6
-rw-r--r--crypto/tcrypt.c4
-rw-r--r--crypto/testmgr.c16
-rw-r--r--crypto/testmgr.h60
-rw-r--r--drivers/char/hw_random/Kconfig2
-rw-r--r--drivers/char/hw_random/amd-rng.c9
-rw-r--r--drivers/crypto/Kconfig65
-rw-r--r--drivers/crypto/Makefile2
-rw-r--r--drivers/crypto/caam/Kconfig72
-rw-r--r--drivers/crypto/caam/Makefile8
-rw-r--r--drivers/crypto/caam/caamalg.c1268
-rw-r--r--drivers/crypto/caam/compat.h35
-rw-r--r--drivers/crypto/caam/ctrl.c269
-rw-r--r--drivers/crypto/caam/desc.h1605
-rw-r--r--drivers/crypto/caam/desc_constr.h205
-rw-r--r--drivers/crypto/caam/error.c248
-rw-r--r--drivers/crypto/caam/error.h11
-rw-r--r--drivers/crypto/caam/intern.h113
-rw-r--r--drivers/crypto/caam/jr.c517
-rw-r--r--drivers/crypto/caam/jr.h21
-rw-r--r--drivers/crypto/caam/regs.h663
-rw-r--r--drivers/crypto/mv_cesa.c97
-rw-r--r--drivers/crypto/omap-sham.c78
-rw-r--r--drivers/crypto/padlock-sha.c269
-rw-r--r--drivers/crypto/picoxcell_crypto.c64
-rw-r--r--drivers/crypto/s5p-sss.c701
41 files changed, 7660 insertions, 422 deletions
diff --git a/Documentation/devicetree/bindings/crypto/fsl-sec4.txt b/Documentation/devicetree/bindings/crypto/fsl-sec4.txt
new file mode 100644
index 00000000000..bf57ecd5d73
--- /dev/null
+++ b/Documentation/devicetree/bindings/crypto/fsl-sec4.txt
@@ -0,0 +1,397 @@
+=====================================================================
+SEC 4 Device Tree Binding
+Copyright (C) 2008-2011 Freescale Semiconductor Inc.
+
+ CONTENTS
+ -Overview
+ -SEC 4 Node
+ -Job Ring Node
+ -Run Time Integrity Check (RTIC) Node
+ -Run Time Integrity Check (RTIC) Memory Node
+ -Secure Non-Volatile Storage (SNVS) Node
+ -Full Example
+
+NOTE: the SEC 4 is also known as Freescale's Cryptographic Accelerator
+Accelerator and Assurance Module (CAAM).
+
+=====================================================================
+Overview
+
+DESCRIPTION
+
+SEC 4 h/w can process requests from 2 types of sources.
+1. DPAA Queue Interface (HW interface between Queue Manager & SEC 4).
+2. Job Rings (HW interface between cores & SEC 4 registers).
+
+High Speed Data Path Configuration:
+
+HW interface between QM & SEC 4 and also BM & SEC 4, on DPAA-enabled parts
+such as the P4080. The number of simultaneous dequeues the QI can make is
+equal to the number of Descriptor Controller (DECO) engines in a particular
+SEC version. E.g., the SEC 4.0 in the P4080 has 5 DECOs and can thus
+dequeue from 5 subportals simultaneously.
+
+Job Ring Data Path Configuration:
+
+Each JR is located on a separate 4k page, they may (or may not) be made visible
+in the memory partition devoted to a particular core. The P4080 has 4 JRs, so
+up to 4 JRs can be configured; and all 4 JRs process requests in parallel.
+
+=====================================================================
+SEC 4 Node
+
+Description
+
+ Node defines the base address of the SEC 4 block.
+ This block specifies the address range of all global
+ configuration registers for the SEC 4 block. It
+ also receives interrupts from the Run Time Integrity Check
+ (RTIC) function within the SEC 4 block.
+
+PROPERTIES
+
+ - compatible
+ Usage: required
+ Value type: <string>
+ Definition: Must include "fsl,sec-v4.0"
+
+ - #address-cells
+ Usage: required
+ Value type: <u32>
+ Definition: A standard property. Defines the number of cells
+ for representing physical addresses in child nodes.
+
+ - #size-cells
+ Usage: required
+ Value type: <u32>
+ Definition: A standard property. Defines the number of cells
+ for representing the size of physical addresses in
+ child nodes.
+
+ - reg
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: A standard property. Specifies the physical
+ address and length of the SEC4 configuration registers.
+ registers
+
+ - ranges
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: A standard property. Specifies the physical address
+ range of the SEC 4.0 register space (-SNVS not included). A
+ triplet that includes the child address, parent address, &
+ length.
+
+ - interrupts
+ Usage: required
+ Value type: <prop_encoded-array>
+ Definition: Specifies the interrupts generated by this
+ device. The value of the interrupts property
+ consists of one interrupt specifier. The format
+ of the specifier is defined by the binding document
+ describing the node's interrupt parent.
+
+ - interrupt-parent
+ Usage: (required if interrupt property is defined)
+ Value type: <phandle>
+ Definition: A single <phandle> value that points
+ to the interrupt parent to which the child domain
+ is being mapped.
+
+ Note: All other standard properties (see the ePAPR) are allowed
+ but are optional.
+
+
+EXAMPLE
+ crypto@300000 {
+ compatible = "fsl,sec-v4.0";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x300000 0x10000>;
+ ranges = <0 0x300000 0x10000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <92 2>;
+ };
+
+=====================================================================
+Job Ring (JR) Node
+
+ Child of the crypto node defines data processing interface to SEC 4
+ across the peripheral bus for purposes of processing
+ cryptographic descriptors. The specified address
+ range can be made visible to one (or more) cores.
+ The interrupt defined for this node is controlled within
+ the address range of this node.
+
+ - compatible
+ Usage: required
+ Value type: <string>
+ Definition: Must include "fsl,sec-v4.0-job-ring"
+
+ - reg
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: Specifies a two JR parameters: an offset from
+ the parent physical address and the length the JR registers.
+
+ - fsl,liodn
+ Usage: optional-but-recommended
+ Value type: <prop-encoded-array>
+ Definition:
+ Specifies the LIODN to be used in conjunction with
+ the ppid-to-liodn table that specifies the PPID to LIODN mapping.
+ Needed if the PAMU is used. Value is a 12 bit value
+ where value is a LIODN ID for this JR. This property is
+ normally set by boot firmware.
+
+ - interrupts
+ Usage: required
+ Value type: <prop_encoded-array>
+ Definition: Specifies the interrupts generated by this
+ device. The value of the interrupts property
+ consists of one interrupt specifier. The format
+ of the specifier is defined by the binding document
+ describing the node's interrupt parent.
+
+ - interrupt-parent
+ Usage: (required if interrupt property is defined)
+ Value type: <phandle>
+ Definition: A single <phandle> value that points
+ to the interrupt parent to which the child domain
+ is being mapped.
+
+EXAMPLE
+ jr@1000 {
+ compatible = "fsl,sec-v4.0-job-ring";
+ reg = <0x1000 0x1000>;
+ fsl,liodn = <0x081>;
+ interrupt-parent = <&mpic>;
+ interrupts = <88 2>;
+ };
+
+
+=====================================================================
+Run Time Integrity Check (RTIC) Node
+
+ Child node of the crypto node. Defines a register space that
+ contains up to 5 sets of addresses and their lengths (sizes) that
+ will be checked at run time. After an initial hash result is
+ calculated, these addresses are checked by HW to monitor any
+ change. If any memory is modified, a Security Violation is
+ triggered (see SNVS definition).
+
+
+ - compatible
+ Usage: required
+ Value type: <string>
+ Definition: Must include "fsl,sec-v4.0-rtic".
+
+ - #address-cells
+ Usage: required
+ Value type: <u32>
+ Definition: A standard property. Defines the number of cells
+ for representing physical addresses in child nodes. Must
+ have a value of 1.
+
+ - #size-cells
+ Usage: required
+ Value type: <u32>
+ Definition: A standard property. Defines the number of cells
+ for representing the size of physical addresses in
+ child nodes. Must have a value of 1.
+
+ - reg
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: A standard property. Specifies a two parameters:
+ an offset from the parent physical address and the length
+ the SEC4 registers.
+
+ - ranges
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: A standard property. Specifies the physical address
+ range of the SEC 4 register space (-SNVS not included). A
+ triplet that includes the child address, parent address, &
+ length.
+
+EXAMPLE
+ rtic@6000 {
+ compatible = "fsl,sec-v4.0-rtic";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x6000 0x100>;
+ ranges = <0x0 0x6100 0xe00>;
+ };
+
+=====================================================================
+Run Time Integrity Check (RTIC) Memory Node
+ A child node that defines individual RTIC memory regions that are used to
+ perform run-time integrity check of memory areas that should not modified.
+ The node defines a register that contains the memory address &
+ length (combined) and a second register that contains the hash result
+ in big endian format.
+
+ - compatible
+ Usage: required
+ Value type: <string>
+ Definition: Must include "fsl,sec-v4.0-rtic-memory".
+
+ - reg
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: A standard property. Specifies two parameters:
+ an offset from the parent physical address and the length:
+
+ 1. The location of the RTIC memory address & length registers.
+ 2. The location RTIC hash result.
+
+ - fsl,rtic-region
+ Usage: optional-but-recommended
+ Value type: <prop-encoded-array>
+ Definition:
+ Specifies the HW address (36 bit address) for this region
+ followed by the length of the HW partition to be checked;
+ the address is represented as a 64 bit quantity followed
+ by a 32 bit length.
+
+ - fsl,liodn
+ Usage: optional-but-recommended
+ Value type: <prop-encoded-array>
+ Definition:
+ Specifies the LIODN to be used in conjunction with
+ the ppid-to-liodn table that specifies the PPID to LIODN
+ mapping. Needed if the PAMU is used. Value is a 12 bit value
+ where value is a LIODN ID for this RTIC memory region. This
+ property is normally set by boot firmware.
+
+EXAMPLE
+ rtic-a@0 {
+ compatible = "fsl,sec-v4.0-rtic-memory";
+ reg = <0x00 0x20 0x100 0x80>;
+ fsl,liodn = <0x03c>;
+ fsl,rtic-region = <0x12345678 0x12345678 0x12345678>;
+ };
+
+=====================================================================
+Secure Non-Volatile Storage (SNVS) Node
+
+ Node defines address range and the associated
+ interrupt for the SNVS function. This function
+ monitors security state information & reports
+ security violations.
+
+ - compatible
+ Usage: required
+ Value type: <string>
+ Definition: Must include "fsl,sec-v4.0-mon".
+
+ - reg
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: A standard property. Specifies the physical
+ address and length of the SEC4 configuration
+ registers.
+
+ - interrupts
+ Usage: required
+ Value type: <prop_encoded-array>
+ Definition: Specifies the interrupts generated by this
+ device. The value of the interrupts property
+ consists of one interrupt specifier. The format
+ of the specifier is defined by the binding document
+ describing the node's interrupt parent.
+
+ - interrupt-parent
+ Usage: (required if interrupt property is defined)
+ Value type: <phandle>
+ Definition: A single <phandle> value that points
+ to the interrupt parent to which the child domain
+ is being mapped.
+
+EXAMPLE
+ sec_mon@314000 {
+ compatible = "fsl,sec-v4.0-mon";
+ reg = <0x314000 0x1000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <93 2>;
+ };
+
+=====================================================================
+FULL EXAMPLE
+
+ crypto: crypto@300000 {
+ compatible = "fsl,sec-v4.0";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x300000 0x10000>;
+ ranges = <0 0x300000 0x10000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <92 2>;
+
+ sec_jr0: jr@1000 {
+ compatible = "fsl,sec-v4.0-job-ring";
+ reg = <0x1000 0x1000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <88 2>;
+ };
+
+ sec_jr1: jr@2000 {
+ compatible = "fsl,sec-v4.0-job-ring";
+ reg = <0x2000 0x1000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <89 2>;
+ };
+
+ sec_jr2: jr@3000 {
+ compatible = "fsl,sec-v4.0-job-ring";
+ reg = <0x3000 0x1000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <90 2>;
+ };
+
+ sec_jr3: jr@4000 {
+ compatible = "fsl,sec-v4.0-job-ring";
+ reg = <0x4000 0x1000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <91 2>;
+ };
+
+ rtic@6000 {
+ compatible = "fsl,sec-v4.0-rtic";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x6000 0x100>;
+ ranges = <0x0 0x6100 0xe00>;
+
+ rtic_a: rtic-a@0 {
+ compatible = "fsl,sec-v4.0-rtic-memory";
+ reg = <0x00 0x20 0x100 0x80>;
+ };
+
+ rtic_b: rtic-b@20 {
+ compatible = "fsl,sec-v4.0-rtic-memory";
+ reg = <0x20 0x20 0x200 0x80>;
+ };
+
+ rtic_c: rtic-c@40 {
+ compatible = "fsl,sec-v4.0-rtic-memory";
+ reg = <0x40 0x20 0x300 0x80>;
+ };
+
+ rtic_d: rtic-d@60 {
+ compatible = "fsl,sec-v4.0-rtic-memory";
+ reg = <0x60 0x20 0x500 0x80>;
+ };
+ };
+ };
+
+ sec_mon: sec_mon@314000 {
+ compatible = "fsl,sec-v4.0-mon";
+ reg = <0x314000 0x1000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <93 2>;
+ };
+
+=====================================================================
diff --git a/arch/powerpc/boot/dts/p4080ds.dts b/arch/powerpc/boot/dts/p4080ds.dts
index 5b7fc29dd6c..927f94d16e9 100644
--- a/arch/powerpc/boot/dts/p4080ds.dts
+++ b/arch/powerpc/boot/dts/p4080ds.dts
@@ -1,7 +1,7 @@
/*
* P4080DS Device Tree Source
*
- * Copyright 2009 Freescale Semiconductor Inc.
+ * Copyright 2009-2011 Freescale Semiconductor Inc.
*
* 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
@@ -33,6 +33,17 @@
dma1 = &dma1;
sdhc = &sdhc;
+ crypto = &crypto;
+ sec_jr0 = &sec_jr0;
+ sec_jr1 = &sec_jr1;
+ sec_jr2 = &sec_jr2;
+ sec_jr3 = &sec_jr3;
+ rtic_a = &rtic_a;
+ rtic_b = &rtic_b;
+ rtic_c = &rtic_c;
+ rtic_d = &rtic_d;
+ sec_mon = &sec_mon;
+
rio0 = &rapidio0;
};
@@ -410,6 +421,79 @@
dr_mode = "host";
phy_type = "ulpi";
};
+
+ crypto: crypto@300000 {
+ compatible = "fsl,sec-v4.0";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x300000 0x10000>;
+ ranges = <0 0x300000 0x10000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <92 2>;
+
+ sec_jr0: jr@1000 {
+ compatible = "fsl,sec-v4.0-job-ring";
+ reg = <0x1000 0x1000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <88 2>;
+ };
+
+ sec_jr1: jr@2000 {
+ compatible = "fsl,sec-v4.0-job-ring";
+ reg = <0x2000 0x1000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <89 2>;
+ };
+
+ sec_jr2: jr@3000 {
+ compatible = "fsl,sec-v4.0-job-ring";
+ reg = <0x3000 0x1000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <90 2>;
+ };
+
+ sec_jr3: jr@4000 {
+ compatible = "fsl,sec-v4.0-job-ring";
+ reg = <0x4000 0x1000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <91 2>;
+ };
+
+ rtic@6000 {
+ compatible = "fsl,sec-v4.0-rtic";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x6000 0x100>;
+ ranges = <0x0 0x6100 0xe00>;
+
+ rtic_a: rtic-a@0 {
+ compatible = "fsl,sec-v4.0-rtic-memory";
+ reg = <0x00 0x20 0x100 0x80>;
+ };
+
+ rtic_b: rtic-b@20 {
+ compatible = "fsl,sec-v4.0-rtic-memory";
+ reg = <0x20 0x20 0x200 0x80>;
+ };
+
+ rtic_c: rtic-c@40 {
+ compatible = "fsl,sec-v4.0-rtic-memory";
+ reg = <0x40 0x20 0x300 0x80>;
+ };
+
+ rtic_d: rtic-d@60 {
+ compatible = "fsl,sec-v4.0-rtic-memory";
+ reg = <0x60 0x20 0x500 0x80>;
+ };
+ };
+ };
+
+ sec_mon: sec_mon@314000 {
+ compatible = "fsl,sec-v4.0-mon";
+ reg = <0x314000 0x1000>;
+ interrupt-parent = <&mpic>;
+ interrupts = <93 2>;
+ };
};
rapidio0: rapidio@ffe0c0000 {
diff --git a/arch/s390/crypto/Makefile b/arch/s390/crypto/Makefile
index 1cf81d77c5a..7f0b7cda625 100644
--- a/arch/s390/crypto/Makefile
+++ b/arch/s390/crypto/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_CRYPTO_SHA512_S390) += sha512_s390.o sha_common.o
obj-$(CONFIG_CRYPTO_DES_S390) += des_s390.o
obj-$(CONFIG_CRYPTO_AES_S390) += aes_s390.o
obj-$(CONFIG_S390_PRNG) += prng.o
+obj-$(CONFIG_CRYPTO_GHASH_S390) += ghash_s390.o
diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c
index 58f46734465..a9ce135893f 100644
--- a/arch/s390/crypto/aes_s390.c
+++ b/arch/s390/crypto/aes_s390.c
@@ -31,7 +31,8 @@
#define AES_KEYLEN_192 2
#define AES_KEYLEN_256 4
-static char keylen_flag = 0;
+static u8 *ctrblk;
+static char keylen_flag;
struct s390_aes_ctx {
u8 iv[AES_BLOCK_SIZE];
@@ -45,6 +46,24 @@ struct s390_aes_ctx {
} fallback;
};
+struct pcc_param {
+ u8 key[32];
+ u8 tweak[16];
+ u8 block[16];
+ u8 bit[16];
+ u8 xts[16];
+};
+
+struct s390_xts_ctx {
+ u8 key[32];
+ u8 xts_param[16];
+ struct pcc_param pcc;
+ long enc;
+ long dec;
+ int key_len;
+ struct crypto_blkcipher *fallback;
+};
+
/*
* Check if the key_len is supported by the HW.
* Returns 0 if it is, a positive number if it is not and software fallback is
@@ -504,15 +523,337 @@ static struct crypto_alg cbc_aes_alg = {
}
};
+static int xts_fallback_setkey(struct crypto_tfm *tfm, const u8 *key,
+ unsigned int len)
+{
+ struct s390_xts_ctx *xts_ctx = crypto_tfm_ctx(tfm);
+ unsigned int ret;
+
+ xts_ctx->fallback->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
+ xts_ctx->fallback->base.crt_flags |= (tfm->crt_flags &
+ CRYPTO_TFM_REQ_MASK);
+
+ ret = crypto_blkcipher_setkey(xts_ctx->fallback, key, len);
+ if (ret) {
+ tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK;
+ tfm->crt_flags |= (xts_ctx->fallback->base.crt_flags &
+ CRYPTO_TFM_RES_MASK);
+ }
+ return ret;
+}
+
+static int xts_fallback_decrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ struct s390_xts_ctx *xts_ctx = crypto_blkcipher_ctx(desc->tfm);
+ struct crypto_blkcipher *tfm;
+ unsigned int ret;
+
+ tfm = desc->tfm;
+ desc->tfm = xts_ctx->fallback;
+
+ ret = crypto_blkcipher_decrypt_iv(desc, dst, src, nbytes);
+
+ desc->tfm = tfm;
+ return ret;
+}
+
+static int xts_fallback_encrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ struct s390_xts_ctx *xts_ctx = crypto_blkcipher_ctx(desc->tfm);
+ struct crypto_blkcipher *tfm;
+ unsigned int ret;
+
+ tfm = desc->tfm;
+ desc->tfm = xts_ctx->fallback;
+
+ ret = crypto_blkcipher_encrypt_iv(desc, dst, src, nbytes);
+
+ desc->tfm = tfm;
+ return ret;
+}
+
+static int xts_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+ unsigned int key_len)
+{
+ struct s390_xts_ctx *xts_ctx = crypto_tfm_ctx(tfm);
+ u32 *flags = &tfm->crt_flags;
+
+ switch (key_len) {
+ case 32:
+ xts_ctx->enc = KM_XTS_128_ENCRYPT;
+ xts_ctx->dec = KM_XTS_128_DECRYPT;
+ memcpy(xts_ctx->key + 16, in_key, 16);
+ memcpy(xts_ctx->pcc.key + 16, in_key + 16, 16);
+ break;
+ case 48:
+ xts_ctx->enc = 0;
+ xts_ctx->dec = 0;
+ xts_fallback_setkey(tfm, in_key, key_len);
+ break;
+ case 64:
+ xts_ctx->enc = KM_XTS_256_ENCRYPT;
+ xts_ctx->dec = KM_XTS_256_DECRYPT;
+ memcpy(xts_ctx->key, in_key, 32);
+ memcpy(xts_ctx->pcc.key, in_key + 32, 32);
+ break;
+ default:
+ *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+ return -EINVAL;
+ }
+ xts_ctx->key_len = key_len;
+ return 0;
+}
+
+static int xts_aes_crypt(struct blkcipher_desc *desc, long func,
+ struct s390_xts_ctx *xts_ctx,
+ struct blkcipher_walk *walk)
+{
+ unsigned int offset = (xts_ctx->key_len >> 1) & 0x10;
+ int ret = blkcipher_walk_virt(desc, walk);
+ unsigned int nbytes = walk->nbytes;
+ unsigned int n;
+ u8 *in, *out;
+ void *param;
+
+ if (!nbytes)
+ goto out;
+
+ memset(xts_ctx->pcc.block, 0, sizeof(xts_ctx->pcc.block));
+ memset(xts_ctx->pcc.bit, 0, sizeof(xts_ctx->pcc.bit));
+ memset(xts_ctx->pcc.xts, 0, sizeof(xts_ctx->pcc.xts));
+ memcpy(xts_ctx->pcc.tweak, walk->iv, sizeof(xts_ctx->pcc.tweak));
+ param = xts_ctx->pcc.key + offset;
+ ret = crypt_s390_pcc(func, param);
+ BUG_ON(ret < 0);
+
+ memcpy(xts_ctx->xts_param, xts_ctx->pcc.xts, 16);
+ param = xts_ctx->key + offset;
+ do {
+ /* only use complete blocks */
+ n = nbytes & ~(AES_BLOCK_SIZE - 1);
+ out = walk->dst.virt.addr;
+ in = walk->src.virt.addr;
+
+ ret = crypt_s390_km(func, param, out, in, n);
+ BUG_ON(ret < 0 || ret != n);
+
+ nbytes &= AES_BLOCK_SIZE - 1;
+ ret = blkcipher_walk_done(desc, walk, nbytes);
+ } while ((nbytes = walk->nbytes));
+out:
+ return ret;
+}
+
+static int xts_aes_encrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ struct s390_xts_ctx *xts_ctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
+
+ if (unlikely(xts_ctx->key_len == 48))
+ return xts_fallback_encrypt(desc, dst, src, nbytes);
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ return xts_aes_crypt(desc, xts_ctx->enc, xts_ctx, &walk);
+}
+
+static int xts_aes_decrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ struct s390_xts_ctx *xts_ctx = crypto_blkcipher_ctx(desc->tfm);
+ struct blkcipher_walk walk;
+
+ if (unlikely(xts_ctx->key_len == 48))
+ return xts_fallback_decrypt(desc, dst, src, nbytes);
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ return xts_aes_crypt(desc, xts_ctx->dec, xts_ctx, &walk);
+}
+
+static int xts_fallback_init(struct crypto_tfm *tfm)
+{
+ const char *name = tfm->__crt_alg->cra_name;
+ struct s390_xts_ctx *xts_ctx = crypto_tfm_ctx(tfm);
+
+ xts_ctx->fallback = crypto_alloc_blkcipher(name, 0,
+ CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK);
+
+ if (IS_ERR(xts_ctx->fallback)) {
+ pr_err("Allocating XTS fallback algorithm %s failed\n",
+ name);
+ return PTR_ERR(xts_ctx->fallback);
+ }
+ return 0;
+}
+
+static void xts_fallback_exit(struct crypto_tfm *tfm)
+{
+ struct s390_xts_ctx *xts_ctx = crypto_tfm_ctx(tfm);
+
+ crypto_free_blkcipher(xts_ctx->fallback);
+ xts_ctx->fallback = NULL;
+}
+
+static struct crypto_alg xts_aes_alg = {
+ .cra_name = "xts(aes)",
+ .cra_driver_name = "xts-aes-s390",
+ .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER |
+ CRYPTO_ALG_NEED_FALLBACK,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct s390_xts_ctx),
+ .cra_type = &crypto_blkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT(xts_aes_alg.cra_list),
+ .cra_init = xts_fallback_init,
+ .cra_exit = xts_fallback_exit,
+ .cra_u = {
+ .blkcipher = {
+ .min_keysize = 2 * AES_MIN_KEY_SIZE,
+ .max_keysize = 2 * AES_MAX_KEY_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
+ .setkey = xts_aes_set_key,
+ .encrypt = xts_aes_encrypt,
+ .decrypt = xts_aes_decrypt,
+ }
+ }
+};
+
+static int ctr_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+ unsigned int key_len)
+{
+ struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
+
+ switch (key_len) {
+ case 16:
+ sctx->enc = KMCTR_AES_128_ENCRYPT;
+ sctx->dec = KMCTR_AES_128_DECRYPT;
+ break;
+ case 24:
+ sctx->enc = KMCTR_AES_192_ENCRYPT;
+ sctx->dec = KMCTR_AES_192_DECRYPT;
+ break;
+ case 32:
+ sctx->enc = KMCTR_AES_256_ENCRYPT;
+ sctx->dec = KMCTR_AES_256_DECRYPT;
+ break;
+ }
+
+ return aes_set_key(tfm, in_key, key_len);
+}
+
+static int ctr_aes_crypt(struct blkcipher_desc *desc, long func,
+ struct s390_aes_ctx *sctx, struct blkcipher_walk *walk)
+{
+ int ret = blkcipher_walk_virt_block(desc, walk, AES_BLOCK_SIZE);
+ unsigned int i, n, nbytes;
+ u8 buf[AES_BLOCK_SIZE];
+ u8 *out, *in;
+
+ if (!walk->nbytes)
+ return ret;
+
+ memcpy(ctrblk, walk->iv, AES_BLOCK_SIZE);
+ while ((nbytes = walk->nbytes) >= AES_BLOCK_SIZE) {
+ out = walk->dst.virt.addr;
+ in = walk->src.virt.addr;
+ while (nbytes >= AES_BLOCK_SIZE) {
+ /* only use complete blocks, max. PAGE_SIZE */
+ n = (nbytes > PAGE_SIZE) ? PAGE_SIZE :
+ nbytes & ~(AES_BLOCK_SIZE - 1);
+ for (i = AES_BLOCK_SIZE; i < n; i += AES_BLOCK_SIZE) {
+ memcpy(ctrblk + i, ctrblk + i - AES_BLOCK_SIZE,
+ AES_BLOCK_SIZE);
+ crypto_inc(ctrblk + i, AES_BLOCK_SIZE);
+ }
+ ret = crypt_s390_kmctr(func, sctx->key, out, in, n, ctrblk);
+ BUG_ON(ret < 0 || ret != n);
+ if (n > AES_BLOCK_SIZE)
+