diff options
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) + |