diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-02-28 02:03:04 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-02-28 02:03:04 -0500 |
| commit | 3f5595e3d0180305cfef9a9c7c6265d7ade85dea (patch) | |
| tree | aaeca311f61794ff26be9bcdc3491e0c44ff0d67 | |
| parent | 12dfdfedbf8ce3b1464e2cea80014fa0a92ed3e2 (diff) | |
| parent | fb94a687d96c570d46332a4a890f1dcb7310e643 (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
Pull more s390 updates from Martin Schwidefsky:
"Next to the usual bug fixes (including the TASK_SIZE fix), there is
one larger crypto item. It allows to use protected keys with the
in-kernel crypto API
The protected key support has two parts, the pkey user space API to
convert key formats and the paes crypto module that uses a protected
key instead of a standard AES key"
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux:
s390: TASK_SIZE for kernel threads
s390/crypt: Add protected key AES module
s390/dasd: fix spelling mistake: "supportet" -> "supported"
s390/pkey: Introduce pkey kernel module
s390/zcrypt: export additional symbols
s390/zcrypt: Rework CONFIG_ZCRYPT Kconfig text.
s390/zcrypt: Cleanup leftover module code.
s390/nmi: purge tlbs after control register validation
s390/nmi: fix order of register validation
s390/crypto: Add PCKMO inline function
s390/zcrypt: Enable request count reset for cards and queues.
s390/mm: use _SEGMENT_ENTRY_EMPTY in the code
s390/chsc: Add exception handler for CHSC instruction
s390: opt into HAVE_COPY_THREAD_TLS
s390: restore address space when returning to user space
s390: rename CIF_ASCE to CIF_ASCE_PRIMARY
30 files changed, 2182 insertions, 93 deletions
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index d5c1073a2584..a2dcef0aacc7 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig | |||
| @@ -134,6 +134,7 @@ config S390 | |||
| 134 | select HAVE_EBPF_JIT if PACK_STACK && HAVE_MARCH_Z196_FEATURES | 134 | select HAVE_EBPF_JIT if PACK_STACK && HAVE_MARCH_Z196_FEATURES |
| 135 | select HAVE_CMPXCHG_DOUBLE | 135 | select HAVE_CMPXCHG_DOUBLE |
| 136 | select HAVE_CMPXCHG_LOCAL | 136 | select HAVE_CMPXCHG_LOCAL |
| 137 | select HAVE_COPY_THREAD_TLS | ||
| 137 | select HAVE_DEBUG_KMEMLEAK | 138 | select HAVE_DEBUG_KMEMLEAK |
| 138 | select HAVE_DMA_API_DEBUG | 139 | select HAVE_DMA_API_DEBUG |
| 139 | select HAVE_DMA_CONTIGUOUS | 140 | select HAVE_DMA_CONTIGUOUS |
diff --git a/arch/s390/configs/default_defconfig b/arch/s390/configs/default_defconfig index e00975361fec..143b1e00b818 100644 --- a/arch/s390/configs/default_defconfig +++ b/arch/s390/configs/default_defconfig | |||
| @@ -678,6 +678,7 @@ CONFIG_CRYPTO_USER_API_SKCIPHER=m | |||
| 678 | CONFIG_CRYPTO_USER_API_RNG=m | 678 | CONFIG_CRYPTO_USER_API_RNG=m |
| 679 | CONFIG_CRYPTO_USER_API_AEAD=m | 679 | CONFIG_CRYPTO_USER_API_AEAD=m |
| 680 | CONFIG_ZCRYPT=m | 680 | CONFIG_ZCRYPT=m |
| 681 | CONFIG_PKEY=m | ||
| 681 | CONFIG_CRYPTO_SHA1_S390=m | 682 | CONFIG_CRYPTO_SHA1_S390=m |
| 682 | CONFIG_CRYPTO_SHA256_S390=m | 683 | CONFIG_CRYPTO_SHA256_S390=m |
| 683 | CONFIG_CRYPTO_SHA512_S390=m | 684 | CONFIG_CRYPTO_SHA512_S390=m |
diff --git a/arch/s390/configs/performance_defconfig b/arch/s390/configs/performance_defconfig index 2cf87343b590..2358bf33c5ef 100644 --- a/arch/s390/configs/performance_defconfig +++ b/arch/s390/configs/performance_defconfig | |||
| @@ -628,6 +628,7 @@ CONFIG_CRYPTO_USER_API_SKCIPHER=m | |||
| 628 | CONFIG_CRYPTO_USER_API_RNG=m | 628 | CONFIG_CRYPTO_USER_API_RNG=m |
| 629 | CONFIG_CRYPTO_USER_API_AEAD=m | 629 | CONFIG_CRYPTO_USER_API_AEAD=m |
| 630 | CONFIG_ZCRYPT=m | 630 | CONFIG_ZCRYPT=m |
| 631 | CONFIG_PKEY=m | ||
| 631 | CONFIG_CRYPTO_SHA1_S390=m | 632 | CONFIG_CRYPTO_SHA1_S390=m |
| 632 | CONFIG_CRYPTO_SHA256_S390=m | 633 | CONFIG_CRYPTO_SHA256_S390=m |
| 633 | CONFIG_CRYPTO_SHA512_S390=m | 634 | CONFIG_CRYPTO_SHA512_S390=m |
diff --git a/arch/s390/crypto/Makefile b/arch/s390/crypto/Makefile index d1033de4c4ee..402c530c6da5 100644 --- a/arch/s390/crypto/Makefile +++ b/arch/s390/crypto/Makefile | |||
| @@ -6,7 +6,7 @@ obj-$(CONFIG_CRYPTO_SHA1_S390) += sha1_s390.o sha_common.o | |||
| 6 | obj-$(CONFIG_CRYPTO_SHA256_S390) += sha256_s390.o sha_common.o | 6 | obj-$(CONFIG_CRYPTO_SHA256_S390) += sha256_s390.o sha_common.o |
| 7 | obj-$(CONFIG_CRYPTO_SHA512_S390) += sha512_s390.o sha_common.o | 7 | obj-$(CONFIG_CRYPTO_SHA512_S390) += sha512_s390.o sha_common.o |
| 8 | obj-$(CONFIG_CRYPTO_DES_S390) += des_s390.o | 8 | obj-$(CONFIG_CRYPTO_DES_S390) += des_s390.o |
| 9 | obj-$(CONFIG_CRYPTO_AES_S390) += aes_s390.o | 9 | obj-$(CONFIG_CRYPTO_AES_S390) += aes_s390.o paes_s390.o |
| 10 | obj-$(CONFIG_S390_PRNG) += prng.o | 10 | obj-$(CONFIG_S390_PRNG) += prng.o |
| 11 | obj-$(CONFIG_CRYPTO_GHASH_S390) += ghash_s390.o | 11 | obj-$(CONFIG_CRYPTO_GHASH_S390) += ghash_s390.o |
| 12 | obj-$(CONFIG_CRYPTO_CRC32_S390) += crc32-vx_s390.o | 12 | obj-$(CONFIG_CRYPTO_CRC32_S390) += crc32-vx_s390.o |
diff --git a/arch/s390/crypto/paes_s390.c b/arch/s390/crypto/paes_s390.c new file mode 100644 index 000000000000..d69ea495c4d7 --- /dev/null +++ b/arch/s390/crypto/paes_s390.c | |||
| @@ -0,0 +1,619 @@ | |||
| 1 | /* | ||
| 2 | * Cryptographic API. | ||
| 3 | * | ||
| 4 | * s390 implementation of the AES Cipher Algorithm with protected keys. | ||
| 5 | * | ||
| 6 | * s390 Version: | ||
| 7 | * Copyright IBM Corp. 2017 | ||
| 8 | * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> | ||
| 9 | * Harald Freudenberger <freude@de.ibm.com> | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or modify | ||
| 12 | * it under the terms of the GNU General Public License (version 2 only) | ||
| 13 | * as published by the Free Software Foundation. | ||
| 14 | * | ||
| 15 | */ | ||
| 16 | |||
| 17 | #define KMSG_COMPONENT "paes_s390" | ||
| 18 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | ||
| 19 | |||
| 20 | #include <crypto/aes.h> | ||
| 21 | #include <crypto/algapi.h> | ||
| 22 | #include <linux/bug.h> | ||
| 23 | #include <linux/err.h> | ||
| 24 | #include <linux/module.h> | ||
| 25 | #include <linux/cpufeature.h> | ||
| 26 | #include <linux/init.h> | ||
| 27 | #include <linux/spinlock.h> | ||
| 28 | #include <crypto/xts.h> | ||
| 29 | #include <asm/cpacf.h> | ||
| 30 | #include <asm/pkey.h> | ||
| 31 | |||
| 32 | static u8 *ctrblk; | ||
| 33 | static DEFINE_SPINLOCK(ctrblk_lock); | ||
| 34 | |||
| 35 | static cpacf_mask_t km_functions, kmc_functions, kmctr_functions; | ||
| 36 | |||
| 37 | struct s390_paes_ctx { | ||
| 38 | struct pkey_seckey sk; | ||
| 39 | struct pkey_protkey pk; | ||
| 40 | unsigned long fc; | ||
| 41 | }; | ||
| 42 | |||
| 43 | struct s390_pxts_ctx { | ||
| 44 | struct pkey_seckey sk[2]; | ||
| 45 | struct pkey_protkey pk[2]; | ||
| 46 | unsigned long fc; | ||
| 47 | }; | ||
| 48 | |||
| 49 | static inline int __paes_convert_key(struct pkey_seckey *sk, | ||
| 50 | struct pkey_protkey *pk) | ||
| 51 | { | ||
| 52 | int i, ret; | ||
| 53 | |||
| 54 | /* try three times in case of failure */ | ||
| 55 | for (i = 0; i < 3; i++) { | ||
| 56 | ret = pkey_skey2pkey(sk, pk); | ||
| 57 | if (ret == 0) | ||
| 58 | break; | ||
| 59 | } | ||
| 60 | |||
| 61 | return ret; | ||
| 62 | } | ||
| 63 | |||
| 64 | static int __paes_set_key(struct s390_paes_ctx *ctx) | ||
| 65 | { | ||
| 66 | unsigned long fc; | ||
| 67 | |||
| 68 | if (__paes_convert_key(&ctx->sk, &ctx->pk)) | ||
| 69 | return -EINVAL; | ||
| 70 | |||
| 71 | /* Pick the correct function code based on the protected key type */ | ||
| 72 | fc = (ctx->pk.type == PKEY_KEYTYPE_AES_128) ? CPACF_KM_PAES_128 : | ||
| 73 | (ctx->pk.type == PKEY_KEYTYPE_AES_192) ? CPACF_KM_PAES_192 : | ||
| 74 | (ctx->pk.type == PKEY_KEYTYPE_AES_256) ? CPACF_KM_PAES_256 : 0; | ||
| 75 | |||
| 76 | /* Check if the function code is available */ | ||
| 77 | ctx->fc = (fc && cpacf_test_func(&km_functions, fc)) ? fc : 0; | ||
| 78 | |||
| 79 | return ctx->fc ? 0 : -EINVAL; | ||
| 80 | } | ||
| 81 | |||
| 82 | static int ecb_paes_set_key(struct crypto_tfm *tfm, const u8 *in_key, | ||
| 83 | unsigned int key_len) | ||
| 84 | { | ||
| 85 | struct s390_paes_ctx *ctx = crypto_tfm_ctx(tfm); | ||
| 86 | |||
| 87 | if (key_len != SECKEYBLOBSIZE) | ||
| 88 | return -EINVAL; | ||
| 89 | |||
| 90 | memcpy(ctx->sk.seckey, in_key, SECKEYBLOBSIZE); | ||
| 91 | if (__paes_set_key(ctx)) { | ||
| 92 | tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; | ||
| 93 | return -EINVAL; | ||
| 94 | } | ||
| 95 | return 0; | ||
| 96 | } | ||
| 97 | |||
| 98 | static int ecb_paes_crypt(struct blkcipher_desc *desc, | ||
| 99 | unsigned long modifier, | ||
| 100 | struct blkcipher_walk *walk) | ||
| 101 | { | ||
| 102 | struct s390_paes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); | ||
| 103 | unsigned int nbytes, n, k; | ||
| 104 | int ret; | ||
| 105 | |||
| 106 | ret = blkcipher_walk_virt(desc, walk); | ||
| 107 | while ((nbytes = walk->nbytes) >= AES_BLOCK_SIZE) { | ||
| 108 | /* only use complete blocks */ | ||
| 109 | n = nbytes & ~(AES_BLOCK_SIZE - 1); | ||
| 110 | k = cpacf_km(ctx->fc | modifier, ctx->pk.protkey, | ||
| 111 | walk->dst.virt.addr, walk->src.virt.addr, n); | ||
| 112 | if (k) | ||
| 113 | ret = blkcipher_walk_done(desc, walk, nbytes - k); | ||
| 114 | if (k < n) { | ||
| 115 | if (__paes_set_key(ctx) != 0) | ||
| 116 | return blkcipher_walk_done(desc, walk, -EIO); | ||
| 117 | } | ||
| 118 | } | ||
| 119 | return ret; | ||
| 120 | } | ||
| 121 | |||
| 122 | static int ecb_paes_encrypt(struct blkcipher_desc *desc, | ||
| 123 | struct scatterlist *dst, struct scatterlist *src, | ||
| 124 | unsigned int nbytes) | ||
| 125 | { | ||
| 126 | struct blkcipher_walk walk; | ||
| 127 | |||
| 128 | blkcipher_walk_init(&walk, dst, src, nbytes); | ||
| 129 | return ecb_paes_crypt(desc, CPACF_ENCRYPT, &walk); | ||
| 130 | } | ||
| 131 | |||
| 132 | static int ecb_paes_decrypt(struct blkcipher_desc *desc, | ||
| 133 | struct scatterlist *dst, struct scatterlist *src, | ||
| 134 | unsigned int nbytes) | ||
| 135 | { | ||
| 136 | struct blkcipher_walk walk; | ||
| 137 | |||
| 138 | blkcipher_walk_init(&walk, dst, src, nbytes); | ||
| 139 | return ecb_paes_crypt(desc, CPACF_DECRYPT, &walk); | ||
| 140 | } | ||
| 141 | |||
| 142 | static struct crypto_alg ecb_paes_alg = { | ||
| 143 | .cra_name = "ecb(paes)", | ||
| 144 | .cra_driver_name = "ecb-paes-s390", | ||
| 145 | .cra_priority = 400, /* combo: aes + ecb */ | ||
| 146 | .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, | ||
| 147 | .cra_blocksize = AES_BLOCK_SIZE, | ||
| 148 | .cra_ctxsize = sizeof(struct s390_paes_ctx), | ||
| 149 | .cra_type = &crypto_blkcipher_type, | ||
| 150 | .cra_module = THIS_MODULE, | ||
| 151 | .cra_list = LIST_HEAD_INIT(ecb_paes_alg.cra_list), | ||
| 152 | .cra_u = { | ||
| 153 | .blkcipher = { | ||
| 154 | .min_keysize = SECKEYBLOBSIZE, | ||
| 155 | .max_keysize = SECKEYBLOBSIZE, | ||
| 156 | .setkey = ecb_paes_set_key, | ||
| 157 | .encrypt = ecb_paes_encrypt, | ||
| 158 | .decrypt = ecb_paes_decrypt, | ||
| 159 | } | ||
| 160 | } | ||
| 161 | }; | ||
| 162 | |||
| 163 | static int __cbc_paes_set_key(struct s390_paes_ctx *ctx) | ||
| 164 | { | ||
| 165 | unsigned long fc; | ||
| 166 | |||
| 167 | if (__paes_convert_key(&ctx->sk, &ctx->pk)) | ||
| 168 | return -EINVAL; | ||
| 169 | |||
| 170 | /* Pick the correct function code based on the protected key type */ | ||
| 171 | fc = (ctx->pk.type == PKEY_KEYTYPE_AES_128) ? CPACF_KMC_PAES_128 : | ||
| 172 | (ctx->pk.type == PKEY_KEYTYPE_AES_192) ? CPACF_KMC_PAES_192 : | ||
| 173 | (ctx->pk.type == PKEY_KEYTYPE_AES_256) ? CPACF_KMC_PAES_256 : 0; | ||
| 174 | |||
| 175 | /* Check if the function code is available */ | ||
| 176 | ctx->fc = (fc && cpacf_test_func(&kmc_functions, fc)) ? fc : 0; | ||
| 177 | |||
| 178 | return ctx->fc ? 0 : -EINVAL; | ||
| 179 | } | ||
| 180 | |||
| 181 | static int cbc_paes_set_key(struct crypto_tfm *tfm, const u8 *in_key, | ||
| 182 | unsigned int key_len) | ||
| 183 | { | ||
| 184 | struct s390_paes_ctx *ctx = crypto_tfm_ctx(tfm); | ||
| 185 | |||
| 186 | memcpy(ctx->sk.seckey, in_key, SECKEYBLOBSIZE); | ||
| 187 | if (__cbc_paes_set_key(ctx)) { | ||
| 188 | tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; | ||
| 189 | return -EINVAL; | ||
| 190 | } | ||
| 191 | return 0; | ||
| 192 | } | ||
| 193 | |||
| 194 | static int cbc_paes_crypt(struct blkcipher_desc *desc, unsigned long modifier, | ||
| 195 | struct blkcipher_walk *walk) | ||
| 196 | { | ||
| 197 | struct s390_paes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); | ||
| 198 | unsigned int nbytes, n, k; | ||
| 199 | int ret; | ||
| 200 | struct { | ||
| 201 | u8 iv[AES_BLOCK_SIZE]; | ||
| 202 | u8 key[MAXPROTKEYSIZE]; | ||
| 203 | } param; | ||
| 204 | |||
| 205 | ret = blkcipher_walk_virt(desc, walk); | ||
| 206 | memcpy(param.iv, walk->iv, AES_BLOCK_SIZE); | ||
| 207 | memcpy(param.key, ctx->pk.protkey, MAXPROTKEYSIZE); | ||
| 208 | while ((nbytes = walk->nbytes) >= AES_BLOCK_SIZE) { | ||
| 209 | /* only use complete blocks */ | ||
| 210 | n = nbytes & ~(AES_BLOCK_SIZE - 1); | ||
| 211 | k = cpacf_kmc(ctx->fc | modifier, ¶m, | ||
| 212 | walk->dst.virt.addr, walk->src.virt.addr, n); | ||
| 213 | if (k) | ||
| 214 | ret = blkcipher_walk_done(desc, walk, nbytes - k); | ||
| 215 | if (n < k) { | ||
| 216 | if (__cbc_paes_set_key(ctx) != 0) | ||
| 217 | return blkcipher_walk_done(desc, walk, -EIO); | ||
| 218 | memcpy(param.key, ctx->pk.protkey, MAXPROTKEYSIZE); | ||
| 219 | } | ||
| 220 | } | ||
| 221 | memcpy(walk->iv, param.iv, AES_BLOCK_SIZE); | ||
| 222 | return ret; | ||
| 223 | } | ||
| 224 | |||
| 225 | static int cbc_paes_encrypt(struct blkcipher_desc *desc, | ||
| 226 | struct scatterlist *dst, struct scatterlist *src, | ||
| 227 | unsigned int nbytes) | ||
| 228 | { | ||
| 229 | struct blkcipher_walk walk; | ||
| 230 | |||
| 231 | blkcipher_walk_init(&walk, dst, src, nbytes); | ||
| 232 | return cbc_paes_crypt(desc, 0, &walk); | ||
| 233 | } | ||
| 234 | |||
| 235 | static int cbc_paes_decrypt(struct blkcipher_desc *desc, | ||
| 236 | struct scatterlist *dst, struct scatterlist *src, | ||
| 237 | unsigned int nbytes) | ||
| 238 | { | ||
| 239 | struct blkcipher_walk walk; | ||
| 240 | |||
| 241 | blkcipher_walk_init(&walk, dst, src, nbytes); | ||
| 242 | return cbc_paes_crypt(desc, CPACF_DECRYPT, &walk); | ||
| 243 | } | ||
| 244 | |||
| 245 | static struct crypto_alg cbc_paes_alg = { | ||
| 246 | .cra_name = "cbc(paes)", | ||
| 247 | .cra_driver_name = "cbc-paes-s390", | ||
| 248 | .cra_priority = 400, /* combo: aes + cbc */ | ||
| 249 | .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, | ||
| 250 | .cra_blocksize = AES_BLOCK_SIZE, | ||
| 251 | .cra_ctxsize = sizeof(struct s390_paes_ctx), | ||
| 252 | .cra_type = &crypto_blkcipher_type, | ||
| 253 | .cra_module = THIS_MODULE, | ||
| 254 | .cra_list = LIST_HEAD_INIT(cbc_paes_alg.cra_list), | ||
| 255 | .cra_u = { | ||
| 256 | .blkcipher = { | ||
| 257 | .min_keysize = SECKEYBLOBSIZE, | ||
| 258 | .max_keysize = SECKEYBLOBSIZE, | ||
| 259 | .ivsize = AES_BLOCK_SIZE, | ||
| 260 | .setkey = cbc_paes_set_key, | ||
| 261 | .encrypt = cbc_paes_encrypt, | ||
| 262 | .decrypt = cbc_paes_decrypt, | ||
| 263 | } | ||
| 264 | } | ||
| 265 | }; | ||
| 266 | |||
| 267 | static int __xts_paes_set_key(struct s390_pxts_ctx *ctx) | ||
| 268 | { | ||
| 269 | unsigned long fc; | ||
| 270 | |||
| 271 | if (__paes_convert_key(&ctx->sk[0], &ctx->pk[0]) || | ||
| 272 | __paes_convert_key(&ctx->sk[1], &ctx->pk[1])) | ||
| 273 | return -EINVAL; | ||
| 274 | |||
| 275 | if (ctx->pk[0].type != ctx->pk[1].type) | ||
| 276 | return -EINVAL; | ||
| 277 | |||
| 278 | /* Pick the correct function code based on the protected key type */ | ||
| 279 | fc = (ctx->pk[0].type == PKEY_KEYTYPE_AES_128) ? CPACF_KM_PXTS_128 : | ||
| 280 | (ctx->pk[0].type == PKEY_KEYTYPE_AES_256) ? | ||
| 281 | CPACF_KM_PXTS_256 : 0; | ||
| 282 | |||
| 283 | /* Check if the function code is available */ | ||
| 284 | ctx->fc = (fc && cpacf_test_func(&km_functions, fc)) ? fc : 0; | ||
| 285 | |||
| 286 | return ctx->fc ? 0 : -EINVAL; | ||
| 287 | } | ||
| 288 | |||
| 289 | static int xts_paes_set_key(struct crypto_tfm *tfm, const u8 *in_key, | ||
| 290 | unsigned int key_len) | ||
| 291 | { | ||
| 292 | struct s390_pxts_ctx *ctx = crypto_tfm_ctx(tfm); | ||
| 293 | u8 ckey[2 * AES_MAX_KEY_SIZE]; | ||
| 294 | unsigned int ckey_len; | ||
| 295 | |||
| 296 | memcpy(ctx->sk[0].seckey, in_key, SECKEYBLOBSIZE); | ||
| 297 | memcpy(ctx->sk[1].seckey, in_key + SECKEYBLOBSIZE, SECKEYBLOBSIZE); | ||
| 298 | if (__xts_paes_set_key(ctx)) { | ||
| 299 | tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; | ||
| 300 | return -EINVAL; | ||
| 301 | } | ||
| 302 | |||
| 303 | /* | ||
| 304 | * xts_check_key verifies the key length is not odd and makes | ||
| 305 | * sure that the two keys are not the same. This can be done | ||
| 306 | * on the two protected keys as well | ||
| 307 | */ | ||
| 308 | ckey_len = (ctx->pk[0].type == PKEY_KEYTYPE_AES_128) ? | ||
| 309 | AES_KEYSIZE_128 : AES_KEYSIZE_256; | ||
| 310 | memcpy(ckey, ctx->pk[0].protkey, ckey_len); | ||
| 311 | memcpy(ckey + ckey_len, ctx->pk[1].protkey, ckey_len); | ||
| 312 | return xts_check_key(tfm, ckey, 2*ckey_len); | ||
| 313 | } | ||
| 314 | |||
| 315 | static int xts_paes_crypt(struct blkcipher_desc *desc, unsigned long modifier, | ||
| 316 | struct blkcipher_walk *walk) | ||
| 317 | { | ||
| 318 | struct s390_pxts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); | ||
| 319 | unsigned int keylen, offset, nbytes, n, k; | ||
| 320 | int ret; | ||
| 321 | struct { | ||
| 322 | u8 key[MAXPROTKEYSIZE]; /* key + verification pattern */ | ||
| 323 | u8 tweak[16]; | ||
| 324 | u8 block[16]; | ||
| 325 | u8 bit[16]; | ||
| 326 | u8 xts[16]; | ||
| 327 | } pcc_param; | ||
| 328 | struct { | ||
| 329 | u8 key[MAXPROTKEYSIZE]; /* key + verification pattern */ | ||
| 330 | u8 init[16]; | ||
| 331 | } xts_param; | ||
| 332 | |||
| 333 | ret = blkcipher_walk_virt(desc, walk); | ||
| 334 | keylen = (ctx->pk[0].type == PKEY_KEYTYPE_AES_128) ? 48 : 64; | ||
| 335 | offset = (ctx->pk[0].type == PKEY_KEYTYPE_AES_128) ? 16 : 0; | ||
| 336 | retry: | ||
| 337 | memset(&pcc_param, 0, sizeof(pcc_param)); | ||
| 338 | memcpy(pcc_param.tweak, walk->iv, sizeof(pcc_param.tweak)); | ||
| 339 | memcpy(pcc_param.key + offset, ctx->pk[1].protkey, keylen); | ||
| 340 | cpacf_pcc(ctx->fc, pcc_param.key + offset); | ||
| 341 | |||
| 342 | memcpy(xts_param.key + offset, ctx->pk[0].protkey, keylen); | ||
| 343 | memcpy(xts_param.init, pcc_param.xts, 16); | ||
| 344 | |||
| 345 | while ((nbytes = walk->nbytes) >= AES_BLOCK_SIZE) { | ||
| 346 | /* only use complete blocks */ | ||
| 347 | n = nbytes & ~(AES_BLOCK_SIZE - 1); | ||
| 348 | k = cpacf_km(ctx->fc | modifier, xts_param.key + offset, | ||
| 349 | walk->dst.virt.addr, walk->src.virt.addr, n); | ||
| 350 | if (k) | ||
| 351 | ret = blkcipher_walk_done(desc, walk, nbytes - k); | ||
| 352 | if (k < n) { | ||
| 353 | if (__xts_paes_set_key(ctx) != 0) | ||
| 354 | return blkcipher_walk_done(desc, walk, -EIO); | ||
| 355 | goto retry; | ||
| 356 | } | ||
| 357 | } | ||
| 358 | return ret; | ||
| 359 | } | ||
| 360 | |||
| 361 | static int xts_paes_encrypt(struct blkcipher_desc *desc, | ||
| 362 | struct scatterlist *dst, struct scatterlist *src, | ||
| 363 | unsigned int nbytes) | ||
| 364 | { | ||
| 365 | struct blkcipher_walk walk; | ||
| 366 | |||
| 367 | blkcipher_walk_init(&walk, dst, src, nbytes); | ||
| 368 | return xts_paes_crypt(desc, 0, &walk); | ||
| 369 | } | ||
| 370 | |||
| 371 | static int xts_paes_decrypt(struct blkcipher_desc *desc, | ||
| 372 | struct scatterlist *dst, struct scatterlist *src, | ||
| 373 | unsigned int nbytes) | ||
| 374 | { | ||
| 375 | struct blkcipher_walk walk; | ||
| 376 | |||
| 377 | blkcipher_walk_init(&walk, dst, src, nbytes); | ||
| 378 | return xts_paes_crypt(desc, CPACF_DECRYPT, &walk); | ||
| 379 | } | ||
| 380 | |||
| 381 | static struct crypto_alg xts_paes_alg = { | ||
| 382 | .cra_name = "xts(paes)", | ||
| 383 | .cra_driver_name = "xts-paes-s390", | ||
| 384 | .cra_priority = 400, /* combo: aes + xts */ | ||
| 385 | .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, | ||
| 386 | .cra_blocksize = AES_BLOCK_SIZE, | ||
| 387 | .cra_ctxsize = sizeof(struct s390_pxts_ctx), | ||
| 388 | .cra_type = &crypto_blkcipher_type, | ||
| 389 | .cra_module = THIS_MODULE, | ||
| 390 | .cra_list = LIST_HEAD_INIT(xts_paes_alg.cra_list), | ||
| 391 | .cra_u = { | ||
| 392 | .blkcipher = { | ||
| 393 | .min_keysize = 2 * SECKEYBLOBSIZE, | ||
| 394 | .max_keysize = 2 * SECKEYBLOBSIZE, | ||
| 395 | .ivsize = AES_BLOCK_SIZE, | ||
| 396 | .setkey = xts_paes_set_key, | ||
| 397 | .encrypt = xts_paes_encrypt, | ||
| 398 | .decrypt = xts_paes_decrypt, | ||
| 399 | } | ||
| 400 | } | ||
| 401 | }; | ||
| 402 | |||
| 403 | static int __ctr_paes_set_key(struct s390_paes_ctx *ctx) | ||
| 404 | { | ||
| 405 | unsigned long fc; | ||
| 406 | |||
| 407 | if (__paes_convert_key(&ctx->sk, &ctx->pk)) | ||
| 408 | return -EINVAL; | ||
| 409 | |||
| 410 | /* Pick the correct function code based on the protected key type */ | ||
| 411 | fc = (ctx->pk.type == PKEY_KEYTYPE_AES_128) ? CPACF_KMCTR_PAES_128 : | ||
| 412 | (ctx->pk.type == PKEY_KEYTYPE_AES_192) ? CPACF_KMCTR_PAES_192 : | ||
| 413 | (ctx->pk.type == PKEY_KEYTYPE_AES_256) ? | ||
| 414 | CPACF_KMCTR_PAES_256 : 0; | ||
| 415 | |||
| 416 | /* Check if the function code is available */ | ||
| 417 | ctx->fc = (fc && cpacf_test_func(&kmctr_functions, fc)) ? fc : 0; | ||
| 418 | |||
| 419 | return ctx->fc ? 0 : -EINVAL; | ||
| 420 | } | ||
| 421 | |||
| 422 | static int ctr_paes_set_key(struct crypto_tfm *tfm, const u8 *in_key, | ||
| 423 | unsigned int key_len) | ||
| 424 | { | ||
| 425 | struct s390_paes_ctx *ctx = crypto_tfm_ctx(tfm); | ||
| 426 | |||
| 427 | memcpy(ctx->sk.seckey, in_key, key_len); | ||
| 428 | if (__ctr_paes_set_key(ctx)) { | ||
| 429 | tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; | ||
| 430 | return -EINVAL; | ||
| 431 | } | ||
| 432 | return 0; | ||
| 433 | } | ||
| 434 | |||
| 435 | static unsigned int __ctrblk_init(u8 *ctrptr, u8 *iv, unsigned int nbytes) | ||
| 436 | { | ||
| 437 | unsigned int i, n; | ||
| 438 | |||
| 439 | /* only use complete blocks, max. PAGE_SIZE */ | ||
| 440 | memcpy(ctrptr, iv, AES_BLOCK_SIZE); | ||
| 441 | n = (nbytes > PAGE_SIZE) ? PAGE_SIZE : nbytes & ~(AES_BLOCK_SIZE - 1); | ||
| 442 | for (i = (n / AES_BLOCK_SIZE) - 1; i > 0; i--) { | ||
| 443 | memcpy(ctrptr + AES_BLOCK_SIZE, ctrptr, AES_BLOCK_SIZE); | ||
| 444 | crypto_inc(ctrptr + AES_BLOCK_SIZE, AES_BLOCK_SIZE); | ||
| 445 | ctrptr += AES_BLOCK_SIZE; | ||
| 446 | } | ||
| 447 | return n; | ||
| 448 | } | ||
| 449 | |||
| 450 | static int ctr_paes_crypt(struct blkcipher_desc *desc, unsigned long modifier, | ||
| 451 | struct blkcipher_walk *walk) | ||
| 452 | { | ||
| 453 | struct s390_paes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); | ||
| 454 | u8 buf[AES_BLOCK_SIZE], *ctrptr; | ||
| 455 | unsigned int nbytes, n, k; | ||
| 456 | int ret, locked; | ||
| 457 | |||
| 458 | locked = spin_trylock(&ctrblk_lock); | ||
| 459 | |||
| 460 | ret = blkcipher_walk_virt_block(desc, walk, AES_BLOCK_SIZE); | ||
| 461 | while ((nbytes = walk->nbytes) >= AES_BLOCK_SIZE) { | ||
| 462 | n = AES_BLOCK_SIZE; | ||
| 463 | if (nbytes >= 2*AES_BLOCK_SIZE && locked) | ||
| 464 | n = __ctrblk_init(ctrblk, walk->iv, nbytes); | ||
| 465 | ctrptr = (n > AES_BLOCK_SIZE) ? ctrblk : walk->iv; | ||
| 466 | k = cpacf_kmctr(ctx->fc | modifier, ctx->pk.protkey, | ||
| 467 | walk->dst.virt.addr, walk->src.virt.addr, | ||
| 468 | n, ctrptr); | ||
| 469 | if (k) { | ||
| 470 | if (ctrptr == ctrblk) | ||
| 471 | memcpy(walk->iv, ctrptr + k - AES_BLOCK_SIZE, | ||
| 472 | AES_BLOCK_SIZE); | ||
| 473 | crypto_inc(walk->iv, AES_BLOCK_SIZE); | ||
| 474 | ret = blkcipher_walk_done(desc, walk, nbytes - n); | ||
| 475 | } | ||
| 476 | if (k < n) { | ||
| 477 | if (__ctr_paes_set_key(ctx) != 0) | ||
| 478 | return blkcipher_walk_done(desc, walk, -EIO); | ||
| 479 | } | ||
| 480 | } | ||
| 481 | if (locked) | ||
| 482 | spin_unlock(&ctrblk_lock); | ||
| 483 | /* | ||
| 484 | * final block may be < AES_BLOCK_SIZE, copy only nbytes | ||
| 485 | */ | ||
| 486 | if (nbytes) { | ||
| 487 | while (1) { | ||
| 488 | if (cpacf_kmctr(ctx->fc | modifier, | ||
| 489 | ctx->pk.protkey, buf, | ||
| 490 | walk->src.virt.addr, AES_BLOCK_SIZE, | ||
| 491 | walk->iv) == AES_BLOCK_SIZE) | ||
| 492 | break; | ||
| 493 | if (__ctr_paes_set_key(ctx) != 0) | ||
| 494 | return blkcipher_walk_done(desc, walk, -EIO); | ||
| 495 | } | ||
| 496 | memcpy(walk->dst.virt.addr, buf, nbytes); | ||
| 497 | crypto_inc(walk->iv, AES_BLOCK_SIZE); | ||
| 498 | ret = blkcipher_walk_done(desc, walk, 0); | ||
| 499 | } | ||
| 500 | |||
| 501 | return ret; | ||
| 502 | } | ||
| 503 | |||
| 504 | static int ctr_paes_encrypt(struct blkcipher_desc *desc, | ||
| 505 | struct scatterlist *dst, struct scatterlist *src, | ||
| 506 | unsigned int nbytes) | ||
| 507 | { | ||
| 508 | struct blkcipher_walk walk; | ||
| 509 | |||
| 510 | blkcipher_walk_init(&walk, dst, src, nbytes); | ||
| 511 | return ctr_paes_crypt(desc, 0, &walk); | ||
| 512 | } | ||
| 513 | |||
| 514 | static int ctr_paes_decrypt(struct blkcipher_desc *desc, | ||
| 515 | struct scatterlist *dst, struct scatterlist *src, | ||
| 516 | unsigned int nbytes) | ||
| 517 | { | ||
| 518 | struct blkcipher_walk walk; | ||
| 519 | |||
| 520 | blkcipher_walk_init(&walk, dst, src, nbytes); | ||
| 521 | return ctr_paes_crypt(desc, CPACF_DECRYPT, &walk); | ||
| 522 | } | ||
| 523 | |||
| 524 | static struct crypto_alg ctr_paes_alg = { | ||
| 525 | .cra_name = "ctr(paes)", | ||
| 526 | .cra_driver_name = "ctr-paes-s390", | ||
| 527 | .cra_priority = 400, /* combo: aes + ctr */ | ||
| 528 | .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, | ||
| 529 | .cra_blocksize = 1, | ||
| 530 | .cra_ctxsize = sizeof(struct s390_paes_ctx), | ||
| 531 | .cra_type = &crypto_blkcipher_type, | ||
| 532 | .cra_module = THIS_MODULE, | ||
| 533 | .cra_list = LIST_HEAD_INIT(ctr_paes_alg.cra_list), | ||
| 534 | .cra_u = { | ||
| 535 | .blkcipher = { | ||
| 536 | .min_keysize = SECKEYBLOBSIZE, | ||
| 537 | .max_keysize = SECKEYBLOBSIZE, | ||
| 538 | .ivsize = AES_BLOCK_SIZE, | ||
| 539 | .setkey = ctr_paes_set_key, | ||
| 540 | .encrypt = ctr_paes_encrypt, | ||
| 541 | .decrypt = ctr_paes_decrypt, | ||
| 542 | } | ||
| 543 | } | ||
| 544 | }; | ||
| 545 | |||
| 546 | static inline void __crypto_unregister_alg(struct crypto_alg *alg) | ||
| 547 | { | ||
| 548 | if (!list_empty(&alg->cra_list)) | ||
| 549 | crypto_unregister_alg(alg); | ||
| 550 | } | ||
| 551 | |||
| 552 | static void paes_s390_fini(void) | ||
| 553 | { | ||
| 554 | if (ctrblk) | ||
| 555 | free_page((unsigned long) ctrblk); | ||
| 556 | __crypto_unregister_alg(&ctr_paes_alg); | ||
| 557 | __crypto_unregister_alg(&xts_paes_alg); | ||
| 558 | __crypto_unregister_alg(&cbc_paes_alg); | ||
| 559 | __crypto_unregister_alg(&ecb_paes_alg); | ||
| 560 | } | ||
| 561 | |||
| 562 | static int __init paes_s390_init(void) | ||
| 563 | { | ||
| 564 | int ret; | ||
| 565 | |||
| 566 | /* Query available functions for KM, KMC and KMCTR */ | ||
| 567 | cpacf_query(CPACF_KM, &km_functions); | ||
| 568 | cpacf_query(CPACF_KMC, &kmc_functions); | ||
| 569 | cpacf_query(CPACF_KMCTR, &kmctr_functions); | ||
| 570 | |||
| 571 | if (cpacf_test_func(&km_functions, CPACF_KM_PAES_128) || | ||
| 572 | cpacf_test_func(&km_functions, CPACF_KM_PAES_192) || | ||
| 573 | cpacf_test_func(&km_functions, CPACF_KM_PAES_256)) { | ||
| 574 | ret = crypto_register_alg(&ecb_paes_alg); | ||
| 575 | if (ret) | ||
| 576 | goto out_err; | ||
| 577 | } | ||
| 578 | |||
| 579 | if (cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_128) || | ||
| 580 | cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_192) || | ||
| 581 | cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_256)) { | ||
| 582 | ret = crypto_register_alg(&cbc_paes_alg); | ||
| 583 | if (ret) | ||
| 584 | goto out_err; | ||
| 585 | } | ||
| 586 | |||
| 587 | if (cpacf_test_func(&km_functions, CPACF_KM_PXTS_128) || | ||
| 588 | cpacf_test_func(&km_functions, CPACF_KM_PXTS_256)) { | ||
| 589 | ret = crypto_register_alg(&xts_paes_alg); | ||
| 590 | if (ret) | ||
| 591 | goto out_err; | ||
| 592 | } | ||
| 593 | |||
| 594 | if (cpacf_test_func(&kmctr_functions, CPACF_KMCTR_PAES_128) || | ||
| 595 | cpacf_test_func(&kmctr_functions, CPACF_KMCTR_PAES_192) || | ||
| 596 | cpacf_test_func(&kmctr_functions, CPACF_KMCTR_PAES_256)) { | ||
| 597 | ret = crypto_register_alg(&ctr_paes_alg); | ||
| 598 | if (ret) | ||
| 599 | goto out_err; | ||
| 600 | ctrblk = (u8 *) __get_free_page(GFP_KERNEL); | ||
| 601 | if (!ctrblk) { | ||
| 602 | ret = -ENOMEM; | ||
| 603 | goto out_err; | ||
| 604 | } | ||
| 605 | } | ||
| 606 | |||
| 607 | return 0; | ||
| 608 | out_err: | ||
| 609 | paes_s390_fini(); | ||
| 610 | return ret; | ||
| 611 | } | ||
| 612 | |||
| 613 | module_init(paes_s390_init); | ||
| 614 | module_exit(paes_s390_fini); | ||
| 615 | |||
| 616 | MODULE_ALIAS_CRYPTO("aes-all"); | ||
| 617 | |||
| 618 | MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm with protected keys"); | ||
| 619 | MODULE_LICENSE("GPL"); | ||
diff --git a/arch/s390/defconfig b/arch/s390/defconfig index d00e368fb5e6..68bfd09f1b02 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig | |||
| @@ -229,6 +229,7 @@ CONFIG_CRYPTO_USER_API_HASH=m | |||
| 229 | CONFIG_CRYPTO_USER_API_SKCIPHER=m | 229 | CONFIG_CRYPTO_USER_API_SKCIPHER=m |
| 230 | CONFIG_CRYPTO_USER_API_RNG=m | 230 | CONFIG_CRYPTO_USER_API_RNG=m |
| 231 | CONFIG_ZCRYPT=m | 231 | CONFIG_ZCRYPT=m |
| 232 | CONFIG_PKEY=m | ||
| 232 | CONFIG_CRYPTO_SHA1_S390=m | 233 | CONFIG_CRYPTO_SHA1_S390=m |
| 233 | CONFIG_CRYPTO_SHA256_S390=m | 234 | CONFIG_CRYPTO_SHA256_S390=m |
| 234 | CONFIG_CRYPTO_SHA512_S390=m | 235 | CONFIG_CRYPTO_SHA512_S390=m |
diff --git a/arch/s390/include/asm/cpacf.h b/arch/s390/include/asm/cpacf.h index 2c680db7e5c1..e2dfbf280d12 100644 --- a/arch/s390/include/asm/cpacf.h +++ b/arch/s390/include/asm/cpacf.h | |||
| @@ -28,8 +28,9 @@ | |||
| 28 | #define CPACF_PPNO 0xb93c /* MSA5 */ | 28 | #define CPACF_PPNO 0xb93c /* MSA5 */ |
| 29 | 29 | ||
| 30 | /* | 30 | /* |
| 31 | * Decryption modifier bit | 31 | * En/decryption modifier bits |
| 32 | */ | 32 | */ |
| 33 | #define CPACF_ENCRYPT 0x00 | ||
| 33 | #define CPACF_DECRYPT 0x80 | 34 | #define CPACF_DECRYPT 0x80 |
| 34 | 35 | ||
| 35 | /* | 36 | /* |
| @@ -42,8 +43,13 @@ | |||
| 42 | #define CPACF_KM_AES_128 0x12 | 43 | #define CPACF_KM_AES_128 0x12 |
| 43 | #define CPACF_KM_AES_192 0x13 | 44 | #define CPACF_KM_AES_192 0x13 |
| 44 | #define CPACF_KM_AES_256 0x14 | 45 | #define CPACF_KM_AES_256 0x14 |
| 46 | #define CPACF_KM_PAES_128 0x1a | ||
| 47 | #define CPACF_KM_PAES_192 0x1b | ||
| 48 | #define CPACF_KM_PAES_256 0x1c | ||
| 45 | #define CPACF_KM_XTS_128 0x32 | 49 | #define CPACF_KM_XTS_128 0x32 |
| 46 | #define CPACF_KM_XTS_256 0x34 | 50 | #define CPACF_KM_XTS_256 0x34 |
| 51 | #define CPACF_KM_PXTS_128 0x3a | ||
| 52 | #define CPACF_KM_PXTS_256 0x3c | ||
| 47 | 53 | ||
| 48 | /* | 54 | /* |
| 49 | * Function codes for the KMC (CIPHER MESSAGE WITH CHAINING) | 55 | * Function codes for the KMC (CIPHER MESSAGE WITH CHAINING) |
| @@ -56,6 +62,9 @@ | |||
| 56 | #define CPACF_KMC_AES_128 0x12 | 62 | #define CPACF_KMC_AES_128 0x12 |
| 57 | #define CPACF_KMC_AES_192 0x13 | 63 | #define CPACF_KMC_AES_192 0x13 |
| 58 | #define CPACF_KMC_AES_256 0x14 | 64 | #define CPACF_KMC_AES_256 0x14 |
| 65 | #define CPACF_KMC_PAES_128 0x1a | ||
| 66 | #define CPACF_KMC_PAES_192 0x1b | ||
| 67 | #define CPACF_KMC_PAES_256 0x1c | ||
| 59 | #define CPACF_KMC_PRNG 0x43 | 68 | #define CPACF_KMC_PRNG 0x43 |
| 60 | 69 | ||
| 61 | /* | 70 | /* |
| @@ -69,6 +78,9 @@ | |||
| 69 | #define CPACF_KMCTR_AES_128 0x12 | 78 | #define CPACF_KMCTR_AES_128 0x12 |
| 70 | #define CPACF_KMCTR_AES_192 0x13 | 79 | #define CPACF_KMCTR_AES_192 0x13 |
| 71 | #define CPACF_KMCTR_AES_256 0x14 | 80 | #define CPACF_KMCTR_AES_256 0x14 |
| 81 | #define CPACF_KMCTR_PAES_128 0x1a | ||
| 82 | #define CPACF_KMCTR_PAES_192 0x1b | ||
| 83 | #define CPACF_KMCTR_PAES_256 0x1c | ||
| 72 | 84 | ||
| 73 | /* | 85 | /* |
| 74 | * Function codes for the KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST) | 86 | * Function codes for the KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST) |
| @@ -99,6 +111,18 @@ | |||
| 99 | #define CPACF_KMAC_TDEA_192 0x03 | 111 | #define CPACF_KMAC_TDEA_192 0x03 |
| 100 | 112 | ||
| 101 | /* | 113 | /* |
| 114 | * Function codes for the PCKMO (PERFORM CRYPTOGRAPHIC KEY MANAGEMENT) | ||
| 115 | * instruction | ||
| 116 | */ | ||
| 117 | #define CPACF_PCKMO_QUERY 0x00 | ||
| 118 | #define CPACF_PCKMO_ENC_DES_KEY 0x01 | ||
| 119 | #define CPACF_PCKMO_ENC_TDES_128_KEY 0x02 | ||
| 120 | #define CPACF_PCKMO_ENC_TDES_192_KEY 0x03 | ||
| 121 | #define CPACF_PCKMO_ENC_AES_128_KEY 0x12 | ||
| 122 | #define CPACF_PCKMO_ENC_AES_192_KEY 0x13 | ||
| 123 | #define CPACF_PCKMO_ENC_AES_256_KEY 0x14 | ||
| 124 | |||
| 125 | /* | ||
| 102 | * Function codes for the PPNO (PERFORM PSEUDORANDOM NUMBER OPERATION) | 126 | * Function codes for the PPNO (PERFORM PSEUDORANDOM NUMBER OPERATION) |
| 103 | * instruction | 127 | * instruction |
| 104 | */ | 128 | */ |
| @@ -397,4 +421,24 @@ static inline void cpacf_pcc(unsigned long func, void *param) | |||
| 397 | : "cc", "memory"); | 421 | : "cc", "memory"); |
| 398 | } | 422 | } |
| 399 | 423 | ||
| 424 | /** | ||
| 425 | * cpacf_pckmo() - executes the PCKMO (PERFORM CRYPTOGRAPHIC KEY | ||
| 426 | * MANAGEMENT) instruction | ||
| 427 | * @func: the function code passed to PCKMO; see CPACF_PCKMO_xxx defines | ||
| 428 | * @param: address of parameter block; see POP for details on each func | ||
| 429 | * | ||
| 430 | * Returns 0. | ||
| 431 | */ | ||
| 432 | static inline void cpacf_pckmo(long func, void *param) | ||
| 433 | { | ||
| 434 | register unsigned long r0 asm("0") = (unsigned long) func; | ||
| 435 | register unsigned long r1 asm("1") = (unsigned long) param; | ||
| 436 | |||
| 437 | asm volatile( | ||
| 438 | " .insn rre,%[opc] << 16,0,0\n" /* PCKMO opcode */ | ||
| 439 | : | ||
| 440 | : [fc] "d" (r0), [pba] "a" (r1), [opc] "i" (CPACF_PCKMO) | ||
| 441 | : "cc", "memory"); | ||
| 442 | } | ||
| 443 | |||
| 400 | #endif /* _ASM_S390_CPACF_H */ | 444 | #endif /* _ASM_S390_CPACF_H */ |
diff --git a/arch/s390/include/asm/mmu_context.h b/arch/s390/include/asm/mmu_context.h index 67f7a991c929..9b828c073176 100644 --- a/arch/s390/include/asm/mmu_context.h +++ b/arch/s390/include/asm/mmu_context.h | |||
| @@ -63,7 +63,7 @@ static inline void set_user_asce(struct mm_struct *mm) | |||
| 63 | S390_lowcore.user_asce = mm->context.asce; | 63 | S390_lowcore.user_asce = mm->context.asce; |
| 64 | if (current->thread.mm_segment.ar4) | 64 | if (current->thread.mm_segment.ar4) |
| 65 | __ctl_load(S390_lowcore.user_asce, 7, 7); | 65 | __ctl_load(S390_lowcore.user_asce, 7, 7); |
| 66 | set_cpu_flag(CIF_ASCE); | 66 | set_cpu_flag(CIF_ASCE_PRIMARY); |
| 67 | } | 67 | } |
| 68 | 68 | ||
| 69 | static inline void clear_user_asce(void) | 69 | static inline void clear_user_asce(void) |
| @@ -81,7 +81,7 @@ static inline void load_kernel_asce(void) | |||
| 81 | __ctl_store(asce, 1, 1); | 81 | __ctl_store(asce, 1, 1); |
| 82 | if (asce != S390_lowcore.kernel_asce) | 82 | if (asce != S390_lowcore.kernel_asce) |
| 83 | __ctl_load(S390_lowcore.kernel_asce, 1, 1); | 83 | __ctl_load(S390_lowcore.kernel_asce, 1, 1); |
| 84 | set_cpu_flag(CIF_ASCE); | 84 | set_cpu_flag(CIF_ASCE_PRIMARY); |
| 85 | } | 85 | } |
| 86 | 86 | ||
| 87 | static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, | 87 | static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, |
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index 52511866fb14..7ed1972b1920 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h | |||
| @@ -640,12 +640,12 @@ static inline int pud_bad(pud_t pud) | |||
| 640 | 640 | ||
| 641 | static inline int pmd_present(pmd_t pmd) | 641 | static inline int pmd_present(pmd_t pmd) |
| 642 | { | 642 | { |
| 643 | return pmd_val(pmd) != _SEGMENT_ENTRY_INVALID; | 643 | return pmd_val(pmd) != _SEGMENT_ENTRY_EMPTY; |
| 644 | } | 644 | } |
| 645 | 645 | ||
| 646 | static inline int pmd_none(pmd_t pmd) | 646 | static inline int pmd_none(pmd_t pmd) |
| 647 | { | 647 | { |
| 648 | return pmd_val(pmd) == _SEGMENT_ENTRY_INVALID; | 648 | return pmd_val(pmd) == _SEGMENT_ENTRY_EMPTY; |
| 649 | } | 649 | } |
| 650 | 650 | ||
| 651 | static inline unsigned long pmd_pfn(pmd_t pmd) | 651 | static inline unsigned long pmd_pfn(pmd_t pmd) |
| @@ -803,7 +803,7 @@ static inline void pud_clear(pud_t *pud) | |||
| 803 | 803 | ||
| 804 | static inline void pmd_clear(pmd_t *pmdp) | 804 | static inline void pmd_clear(pmd_t *pmdp) |
| 805 | { | 805 | { |
| 806 | pmd_val(*pmdp) = _SEGMENT_ENTRY_INVALID; | 806 | pmd_val(*pmdp) = _SEGMENT_ENTRY_EMPTY; |
| 807 | } | 807 | } |
| 808 | 808 | ||
| 809 | static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) | 809 | static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) |
| @@ -1357,7 +1357,7 @@ static inline pmd_t pmd_mkhuge(pmd_t pmd) | |||
| 1357 | static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm, | 1357 | static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm, |
| 1358 | unsigned long addr, pmd_t *pmdp) | 1358 | unsigned long addr, pmd_t *pmdp) |
| 1359 | { | 1359 | { |
| 1360 | return pmdp_xchg_direct(mm, addr, pmdp, __pmd(_SEGMENT_ENTRY_INVALID)); | 1360 | return pmdp_xchg_direct(mm, addr, pmdp, __pmd(_SEGMENT_ENTRY_EMPTY)); |
| 1361 | } | 1361 | } |
| 1362 | 1362 | ||
| 1363 | #define __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR_FULL | 1363 | #define __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR_FULL |
| @@ -1367,10 +1367,10 @@ static inline pmd_t pmdp_huge_get_and_clear_full(struct mm_struct *mm, | |||
| 1367 | { | 1367 | { |
| 1368 | if (full) { | 1368 | if (full) { |
| 1369 | pmd_t pmd = *pmdp; | 1369 | pmd_t pmd = *pmdp; |
| 1370 | *pmdp = __pmd(_SEGMENT_ENTRY_INVALID); | 1370 | *pmdp = __pmd(_SEGMENT_ENTRY_EMPTY); |
| 1371 | return pmd; | 1371 | return pmd; |
| 1372 | } | 1372 | } |
| 1373 | return pmdp_xchg_lazy(mm, addr, pmdp, __pmd(_SEGMENT_ENTRY_INVALID)); | 1373 | return pmdp_xchg_lazy(mm, addr, pmdp, __pmd(_SEGMENT_ENTRY_EMPTY)); |
| 1374 | } | 1374 | } |
| 1375 | 1375 | ||
| 1376 | #define __HAVE_ARCH_PMDP_HUGE_CLEAR_FLUSH | 1376 | #define __HAVE_ARCH_PMDP_HUGE_CLEAR_FLUSH |
| @@ -1384,7 +1384,7 @@ static inline pmd_t pmdp_huge_clear_flush(struct vm_area_struct *vma, | |||
| 1384 | static inline void pmdp_invalidate(struct vm_area_struct *vma, | 1384 | static inline void pmdp_invalidate(struct vm_area_struct *vma, |
| 1385 | unsigned long addr, pmd_t *pmdp) | 1385 | unsigned long addr, pmd_t *pmdp) |
| 1386 | { | 1386 | { |
| 1387 | pmdp_xchg_direct(vma->vm_mm, addr, pmdp, __pmd(_SEGMENT_ENTRY_INVALID)); | 1387 | pmdp_xchg_direct(vma->vm_mm, addr, pmdp, __pmd(_SEGMENT_ENTRY_EMPTY)); |
| 1388 | } | 1388 | } |
| 1389 | 1389 | ||
| 1390 | #define __HAVE_ARCH_PMDP_SET_WRPROTECT | 1390 | #define __HAVE_ARCH_PMDP_SET_WRPROTECT |
diff --git a/arch/s390/include/asm/pkey.h b/arch/s390/include/asm/pkey.h new file mode 100644 index 000000000000..b48aef4188f6 --- /dev/null +++ b/arch/s390/include/asm/pkey.h | |||
| @@ -0,0 +1,90 @@ | |||
| 1 | /* | ||
| 2 | * Kernelspace interface to the pkey device driver | ||
| 3 | * | ||
| 4 | * Copyright IBM Corp. 2016 | ||
| 5 | * | ||
| 6 | * Author: Harald Freudenberger <freude@de.ibm.com> | ||
| 7 | * | ||
| 8 | */ | ||
| 9 | |||
| 10 | #ifndef _KAPI_PKEY_H | ||
| 11 | #define _KAPI_PKEY_H | ||
| 12 | |||
| 13 | #include <linux/ioctl.h> | ||
| 14 | #include <linux/types.h> | ||
| 15 | #include <uapi/asm/pkey.h> | ||
| 16 | |||
| 17 | /* | ||
| 18 | * Generate (AES) random secure key. | ||
| 19 | * @param cardnr may be -1 (use default card) | ||
| 20 | * @param domain may be -1 (use default domain) | ||
| 21 | * @param keytype one of the PKEY_KEYTYPE values | ||
| 22 | * @param seckey pointer to buffer receiving the secure key | ||
| 23 | * @return 0 on success, negative errno value on failure | ||
| 24 | */ | ||
| 25 | int pkey_genseckey(__u16 cardnr, __u16 domain, | ||
| 26 | __u32 keytype, struct pkey_seckey *seckey); | ||
| 27 | |||
| 28 | /* | ||
| 29 | * Generate (AES) secure key with given key value. | ||
| 30 | * @param cardnr may be -1 (use default card) | ||
| 31 | * @param domain may be -1 (use default domain) | ||
| 32 | * @param keytype one of the PKEY_KEYTYPE values | ||
| 33 | * @param clrkey pointer to buffer with clear key data | ||
| 34 | * @param seckey pointer to buffer receiving the secure key | ||
| 35 | * @return 0 on success, negative errno value on failure | ||
| 36 | */ | ||
| 37 | int pkey_clr2seckey(__u16 cardnr, __u16 domain, __u32 keytype, | ||
| 38 | const struct pkey_clrkey *clrkey, | ||
| 39 | struct pkey_seckey *seckey); | ||
| 40 | |||
| 41 | /* | ||
| 42 | * Derive (AES) proteced key from the (AES) secure key blob. | ||
| 43 | * @param cardnr may be -1 (use default card) | ||
| 44 | * @param domain may be -1 (use default domain) | ||
| 45 | * @param seckey pointer to buffer with the input secure key | ||
| 46 | * @param protkey pointer to buffer receiving the protected key and | ||
| 47 | * additional info (type, length) | ||
| 48 | * @return 0 on success, negative errno value on failure | ||
| 49 | */ | ||
| 50 | int pkey_sec2protkey(__u16 cardnr, __u16 domain, | ||
| 51 | const struct pkey_seckey *seckey, | ||
| 52 | struct pkey_protkey *protkey); | ||
| 53 | |||
| 54 | /* | ||
| 55 | * Derive (AES) protected key from a given clear key value. | ||
| 56 | * @param keytype one of the PKEY_KEYTYPE values | ||
| 57 | * @param clrkey pointer to buffer with clear key data | ||
| 58 | * @param protkey pointer to buffer receiving the protected key and | ||
| 59 | * additional info (type, length) | ||
| 60 | * @return 0 on success, negative errno value on failure | ||
| 61 | */ | ||
| 62 | int pkey_clr2protkey(__u32 keytype, | ||
| 63 | const struct pkey_clrkey *clrkey, | ||
| 64 | struct pkey_protkey *protkey); | ||
| 65 | |||
| 66 | /* | ||
| 67 | * Search for a matching crypto card based on the Master Key | ||
| 68 | * Verification Pattern provided inside a secure key. | ||
| 69 | * @param seckey pointer to buffer with the input secure key | ||
| 70 | * @param cardnr pointer to cardnr, receives the card number on success | ||
| 71 | * @param domain pointer to domain, receives the domain number on success | ||
| 72 | * @param verify if set, always verify by fetching verification pattern | ||
| 73 | * from card | ||
| 74 | * @return 0 on success, negative errno value on failure. If no card could be | ||
| 75 | * found, -ENODEV is returned. | ||
| 76 | */ | ||
| 77 | int pkey_findcard(const struct pkey_seckey *seckey, | ||
| 78 | __u16 *cardnr, __u16 *domain, int verify); | ||
| 79 | |||
| 80 | /* | ||
| 81 | * Find card and transform secure key to protected key. | ||
| 82 | * @param seckey pointer to buffer with the input secure key | ||
| 83 | * @param protkey pointer to buffer receiving the protected key and | ||
| 84 | * additional info (type, length) | ||
| 85 | * @return 0 on success, negative errno value on failure | ||
| 86 | */ | ||
| 87 | int pkey_skey2pkey(const struct pkey_seckey *seckey, | ||
| 88 | struct pkey_protkey *protkey); | ||
| 89 | |||
| 90 | #endif /* _KAPI_PKEY_H */ | ||
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h index dacba341e475..e4988710aa86 100644 --- a/arch/s390/include/asm/processor.h +++ b/arch/s390/include/asm/processor.h | |||
| @@ -14,14 +14,16 @@ | |||
| 14 | #include <linux/const.h> | 14 | #include <linux/const.h> |
| 15 | 15 | ||
| 16 | #define CIF_MCCK_PENDING 0 /* machine check handling is pending */ | 16 | #define CIF_MCCK_PENDING 0 /* machine check handling is pending */ |
| 17 | #define CIF_ASCE 1 /* user asce needs fixup / uaccess */ | 17 | #define CIF_ASCE_PRIMARY 1 /* primary asce needs fixup / uaccess */ |
| 18 | #define CIF_NOHZ_DELAY 2 /* delay HZ disable for a tick */ | 18 | #define CIF_ASCE_SECONDARY 2 /* secondary asce needs fixup / uaccess */ |
| 19 | #define CIF_FPU 3 /* restore FPU registers */ | 19 | #define CIF_NOHZ_DELAY 3 /* delay HZ disable for a tick */ |
| 20 | #define CIF_IGNORE_IRQ 4 /* ignore interrupt (for udelay) */ | 20 | #define CIF_FPU 4 /* restore FPU registers */ |
| 21 | #define CIF_ENABLED_WAIT 5 /* in enabled wait state */ | 21 | #define CIF_IGNORE_IRQ 5 /* ignore interrupt (for udelay) */ |
| 22 | #define CIF_ENABLED_WAIT 6 /* in enabled wait state */ | ||
| 22 | 23 | ||
| 23 | #define _CIF_MCCK_PENDING _BITUL(CIF_MCCK_PENDING) | 24 | #define _CIF_MCCK_PENDING _BITUL(CIF_MCCK_PENDING) |
| 24 | #define _CIF_ASCE _BITUL(CIF_ASCE) | 25 | #define _CIF_ASCE_PRIMARY _BITUL(CIF_ASCE_PRIMARY) |
| 26 | #define _CIF_ASCE_SECONDARY _BITUL(CIF_ASCE_SECONDARY) | ||
| 25 | #define _CIF_NOHZ_DELAY _BITUL(CIF_NOHZ_DELAY) | 27 | #define _CIF_NOHZ_DELAY _BITUL(CIF_NOHZ_DELAY) |
| 26 | #define _CIF_FPU _BITUL(CIF_FPU) | 28 | #define _CIF_FPU _BITUL(CIF_FPU) |
| 27 | #define _CIF_IGNORE_IRQ _BITUL(CIF_IGNORE_IRQ) | 29 | #define _CIF_IGNORE_IRQ _BITUL(CIF_IGNORE_IRQ) |
| @@ -89,7 +91,8 @@ extern void execve_tail(void); | |||
| 89 | * User space process size: 2GB for 31 bit, 4TB or 8PT for 64 bit. | 91 | * User space process size: 2GB for 31 bit, 4TB or 8PT for 64 bit. |
| 90 | */ | 92 | */ |
| 91 | 93 | ||
| 92 | #define TASK_SIZE_OF(tsk) ((tsk)->mm->context.asce_limit) | 94 | #define TASK_SIZE_OF(tsk) ((tsk)->mm ? \ |
| 95 | (tsk)->mm->context.asce_limit : TASK_MAX_SIZE) | ||
| 93 | #define TASK_UNMAPPED_BASE (test_thread_flag(TIF_31BIT) ? \ | 96 | #define TASK_UNMAPPED_BASE (test_thread_flag(TIF_31BIT) ? \ |
| 94 | (1UL << 30) : (1UL << 41)) | 97 | (1UL << 30) : (1UL << 41)) |
| 95 | #define TASK_SIZE TASK_SIZE_OF(current) | 98 | #define TASK_SIZE TASK_SIZE_OF(current) |
| @@ -200,10 +203,12 @@ struct stack_frame { | |||
| 200 | struct task_struct; | 203 | struct task_struct; |
| 201 | struct mm_struct; | 204 | struct mm_struct; |
| 202 | struct seq_file; | 205 | struct seq_file; |
| 206 | struct pt_regs; | ||
| 203 | 207 | ||
| 204 | typedef int (*dump_trace_func_t)(void *data, unsigned long address, int reliable); | 208 | typedef int (*dump_trace_func_t)(void *data, unsigned long address, int reliable); |
| 205 | void dump_trace(dump_trace_func_t func, void *data, | 209 | void dump_trace(dump_trace_func_t func, void *data, |
| 206 | struct task_struct *task, unsigned long sp); | 210 | struct task_struct *task, unsigned long sp); |
| 211 | void show_registers(struct pt_regs *regs); | ||
| 207 | 212 | ||
| 208 | void show_cacheinfo(struct seq_file *m); | 213 | void show_cacheinfo(struct seq_file *m); |
| 209 | 214 | ||
diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h index b2988fc60f65..136932ff4250 100644 --- a/arch/s390/include/asm/uaccess.h +++ b/arch/s390/include/asm/uaccess.h | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | */ | 14 | */ |
| 15 | #include <linux/sched.h> | 15 | #include <linux/sched.h> |
| 16 | #include <linux/errno.h> | 16 | #include <linux/errno.h> |
| 17 | #include <asm/processor.h> | ||
| 17 | #include <asm/ctl_reg.h> | 18 | #include <asm/ctl_reg.h> |
| 18 | 19 | ||
| 19 | #define VERIFY_READ 0 | 20 | #define VERIFY_READ 0 |
| @@ -36,18 +37,20 @@ | |||
| 36 | 37 | ||
| 37 | #define get_ds() (KERNEL_DS) | 38 | #define get_ds() (KERNEL_DS) |
| 38 | #define get_fs() (current->thread.mm_segment) | 39 | #define get_fs() (current->thread.mm_segment) |
| 39 | |||
| 40 | #define set_fs(x) \ | ||
| 41 | do { \ | ||
| 42 | unsigned long __pto; \ | ||
| 43 | current->thread.mm_segment = (x); \ | ||
| 44 | __pto = current->thread.mm_segment.ar4 ? \ | ||
| 45 | S390_lowcore.user_asce : S390_lowcore.kernel_asce; \ | ||
| 46 | __ctl_load(__pto, 7, 7); \ | ||
| 47 | } while (0) | ||
| 48 | |||
| 49 | #define segment_eq(a,b) ((a).ar4 == (b).ar4) | 40 | #define segment_eq(a,b) ((a).ar4 == (b).ar4) |
| 50 | 41 | ||
| 42 | static inline void set_fs(mm_segment_t fs) | ||
| 43 | { | ||
| 44 | current->thread.mm_segment = fs; | ||
| 45 | if (segment_eq(fs, KERNEL_DS)) { | ||
| 46 | set_cpu_flag(CIF_ASCE_SECONDARY); | ||
| 47 | __ctl_load(S390_lowcore.kernel_asce, 7, 7); | ||
| 48 | } else { | ||
| 49 | clear_cpu_flag(CIF_ASCE_SECONDARY); | ||
| 50 | __ctl_load(S390_lowcore.user_asce, 7, 7); | ||
| 51 | } | ||
| 52 | } | ||
| 53 | |||
| 51 | static inline int __range_ok(unsigned long addr, unsigned long size) | 54 | static inline int __range_ok(unsigned long addr, unsigned long size) |
| 52 | { | 55 | { |
| 53 | return 1; | 56 | return 1; |
diff --git a/arch/s390/include/uapi/asm/Kbuild b/arch/s390/include/uapi/asm/Kbuild index bf736e764cb4..6848ba5c1454 100644 --- a/arch/s390/include/uapi/asm/Kbuild +++ b/arch/s390/include/uapi/asm/Kbuild | |||
| @@ -24,6 +24,7 @@ header-y += mman.h | |||
| 24 | header-y += monwriter.h | 24 | header-y += monwriter.h |
| 25 | header-y += msgbuf.h | 25 | header-y += msgbuf.h |
| 26 | header-y += param.h | 26 | header-y += param.h |
| 27 | header-y += pkey.h | ||
| 27 | header-y += poll.h | 28 | header-y += poll.h |
| 28 | header-y += posix_types.h | 29 | header-y += posix_types.h |
| 29 | header-y += ptrace.h | 30 | header-y += ptrace.h |
diff --git a/arch/s390/include/uapi/asm/pkey.h b/arch/s390/include/uapi/asm/pkey.h new file mode 100644 index 000000000000..ed7f19c27ce5 --- /dev/null +++ b/arch/s390/include/uapi/asm/pkey.h | |||
| @@ -0,0 +1,112 @@ | |||
| 1 | /* | ||
| 2 | * Userspace interface to the pkey device driver | ||
| 3 | * | ||
| 4 | * Copyright IBM Corp. 2017 | ||
| 5 | * | ||
| 6 | * Author: Harald Freudenberger <freude@de.ibm.com> | ||
| 7 | * | ||
| 8 | */ | ||
| 9 | |||
| 10 | #ifndef _UAPI_PKEY_H | ||
| 11 | #define _UAPI_PKEY_H | ||
| 12 | |||
| 13 | #include <linux/ioctl.h> | ||
| 14 | #include <linux/types.h> | ||
| 15 | |||
| 16 | /* | ||
| 17 | * Ioctl calls supported by the pkey device driver | ||
| 18 | */ | ||
| 19 | |||
| 20 | #define PKEY_IOCTL_MAGIC 'p' | ||
| 21 | |||
| 22 | #define SECKEYBLOBSIZE 64 /* secure key blob size is always 64 bytes */ | ||
| 23 | #define MAXPROTKEYSIZE 64 /* a protected key blob may be up to 64 bytes */ | ||
| 24 | #define MAXCLRKEYSIZE 32 /* a clear key value may be up to 32 bytes */ | ||
| 25 | |||
| 26 | /* defines for the type field within the pkey_protkey struct */ | ||
| 27 | #define PKEY_KEYTYPE_AES_128 1 | ||
| 28 | #define PKEY_KEYTYPE_AES_192 2 | ||
| 29 | #define PKEY_KEYTYPE_AES_256 3 | ||
| 30 | |||
| 31 | /* Struct to hold a secure key blob */ | ||
| 32 | struct pkey_seckey { | ||
| 33 | __u8 seckey[SECKEYBLOBSIZE]; /* the secure key blob */ | ||
| 34 | }; | ||
| 35 | |||
| 36 | /* Struct to hold protected key and length info */ | ||
| 37 | struct pkey_protkey { | ||
| 38 | __u32 type; /* key type, one of the PKEY_KEYTYPE values */ | ||
| 39 | __u32 len; /* bytes actually stored in protkey[] */ | ||
| 40 | __u8 protkey[MAXPROTKEYSIZE]; /* the protected key blob */ | ||
| 41 | }; | ||
| 42 | |||
| 43 | /* Struct to hold a clear key value */ | ||
| 44 | struct pkey_clrkey { | ||
| 45 | __u8 clrkey[MAXCLRKEYSIZE]; /* 16, 24, or 32 byte clear key value */ | ||
| 46 | }; | ||
| 47 | |||
| 48 | /* | ||
| 49 | * Generate secure key | ||
| 50 | */ | ||
| 51 | struct pkey_genseck { | ||
| 52 | __u16 cardnr; /* in: card to use or FFFF for any */ | ||
| 53 | __u16 domain; /* in: domain or FFFF for any */ | ||
| 54 | __u32 keytype; /* in: key type to generate */ | ||
| 55 | struct pkey_seckey seckey; /* out: the secure key blob */ | ||
| 56 | }; | ||
| 57 | #define PKEY_GENSECK _IOWR(PKEY_IOCTL_MAGIC, 0x01, struct pkey_genseck) | ||
| 58 | |||
| 59 | /* | ||
| 60 | * Construct secure key from clear key value | ||
| 61 | */ | ||
| 62 | struct pkey_clr2seck { | ||
| 63 | __u16 cardnr; /* in: card to use or FFFF for any */ | ||
| 64 | __u16 domain; /* in: domain or FFFF for any */ | ||
| 65 | __u32 keytype; /* in: key type to generate */ | ||
| 66 | struct pkey_clrkey clrkey; /* in: the clear key value */ | ||
| 67 | struct pkey_seckey seckey; /* out: the secure key blob */ | ||
| 68 | }; | ||
| 69 | #define PKEY_CLR2SECK _IOWR(PKEY_IOCTL_MAGIC, 0x02, struct pkey_clr2seck) | ||
| 70 | |||
| 71 | /* | ||
| 72 | * Fabricate protected key from a secure key | ||
| 73 | */ | ||
| 74 | struct pkey_sec2protk { | ||
| 75 | __u16 cardnr; /* in: card to use or FFFF for any */ | ||
| 76 | __u16 domain; /* in: domain or FFFF for any */ | ||
| 77 | struct pkey_seckey seckey; /* in: the secure key blob */ | ||
| 78 | struct pkey_protkey protkey; /* out: the protected key */ | ||
| 79 | }; | ||
| 80 | #define PKEY_SEC2PROTK _IOWR(PKEY_IOCTL_MAGIC, 0x03, struct pkey_sec2protk) | ||
| 81 | |||
| 82 | /* | ||
| 83 | * Fabricate protected key from an clear key value | ||
| 84 | */ | ||
| 85 | struct pkey_clr2protk { | ||
| 86 | __u32 keytype; /* in: key type to generate */ | ||
| 87 | struct pkey_clrkey clrkey; /* in: the clear key value */ | ||
| 88 | struct pkey_protkey protkey; /* out: the protected key */ | ||
| 89 | }; | ||
| 90 | #define PKEY_CLR2PROTK _IOWR(PKEY_IOCTL_MAGIC, 0x04, struct pkey_clr2protk) | ||
| 91 | |||
| 92 | /* | ||
| 93 | * Search for matching crypto card based on the Master Key | ||
| 94 | * Verification Pattern provided inside a secure key. | ||
| 95 | */ | ||
| 96 | struct pkey_findcard { | ||
| 97 | struct pkey_seckey seckey; /* in: the secure key blob */ | ||
| 98 | __u16 cardnr; /* out: card number */ | ||
| 99 | __u16 domain; /* out: domain number */ | ||
| 100 | }; | ||
| 101 | #define PKEY_FINDCARD _IOWR(PKEY_IOCTL_MAGIC, 0x05, struct pkey_findcard) | ||
| 102 | |||
| 103 | /* | ||
| 104 | * Combined together: findcard + sec2prot | ||
| 105 | */ | ||
| 106 | struct pkey_skey2pkey { | ||
| 107 | struct pkey_seckey seckey; /* in: the secure key blob */ | ||
| 108 | struct pkey_protkey protkey; /* out: the protected key */ | ||
| 109 | }; | ||
| 110 | #define PKEY_SKEY2PKEY _IOWR(PKEY_IOCTL_MAGIC, 0x06, struct pkey_skey2pkey) | ||
| 111 | |||
| 112 | #endif /* _UAPI_PKEY_H */ | ||
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index db469fa11462..dff2152350a7 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S | |||
| @@ -50,7 +50,8 @@ _TIF_WORK = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \ | |||
| 50 | _TIF_UPROBE) | 50 | _TIF_UPROBE) |
| 51 | _TIF_TRACE = (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | \ | 51 | _TIF_TRACE = (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | \ |
| 52 | _TIF_SYSCALL_TRACEPOINT) | 52 | _TIF_SYSCALL_TRACEPOINT) |
| 53 | _CIF_WORK = (_CIF_MCCK_PENDING | _CIF_ASCE | _CIF_FPU) | 53 | _CIF_WORK = (_CIF_MCCK_PENDING | _CIF_ASCE_PRIMARY | \ |
| 54 | _CIF_ASCE_SECONDARY | _CIF_FPU) | ||
| 54 | _PIF_WORK = (_PIF_PER_TRAP) | 55 | _PIF_WORK = (_PIF_PER_TRAP) |
| 55 | 56 | ||
| 56 | #define BASED(name) name-cleanup_critical(%r13) | 57 | #define BASED(name) name-cleanup_critical(%r13) |
| @@ -339,8 +340,8 @@ ENTRY(system_call) | |||
| 339 | jo .Lsysc_notify_resume | 340 | jo .Lsysc_notify_resume |
| 340 | TSTMSK __LC_CPU_FLAGS,_CIF_FPU | 341 | TSTMSK __LC_CPU_FLAGS,_CIF_FPU |
| 341 | jo .Lsysc_vxrs | 342 | jo .Lsysc_vxrs |
| 342 | TSTMSK __LC_CPU_FLAGS,_CIF_ASCE | 343 | TSTMSK __LC_CPU_FLAGS,(_CIF_ASCE_PRIMARY|_CIF_ASCE_SECONDARY) |
| 343 | jo .Lsysc_uaccess | 344 | jnz .Lsysc_asce |
| 344 | j .Lsysc_return # beware of critical section cleanup | 345 | j .Lsysc_return # beware of critical section cleanup |
| 345 | 346 | ||
| 346 | # | 347 | # |
| @@ -358,12 +359,15 @@ ENTRY(system_call) | |||
| 358 | jg s390_handle_mcck # TIF bit will be cleared by handler | 359 | jg s390_handle_mcck # TIF bit will be cleared by handler |
| 359 | 360 | ||
| 360 | # | 361 | # |
| 361 | # _CIF_ASCE is set, load user space asce | 362 | # _CIF_ASCE_PRIMARY and/or CIF_ASCE_SECONDARY set, load user space asce |
| 362 | # | 363 | # |
| 363 | .Lsysc_uaccess: | 364 | .Lsysc_asce: |
| 364 | ni __LC_CPU_FLAGS+7,255-_CIF_ASCE | 365 | ni __LC_CPU_FLAGS+7,255-_CIF_ASCE_PRIMARY |
| 365 | lctlg %c1,%c1,__LC_USER_ASCE # load primary asce | 366 | lctlg %c1,%c1,__LC_USER_ASCE # load primary asce |
| 366 | j .Lsysc_return | 367 | TSTMSK __LC_CPU_FLAGS,_CIF_ASCE_SECONDARY |
| 368 | jz .Lsysc_return | ||
| 369 | larl %r14,.Lsysc_return | ||
| 370 | jg set_fs_fixup | ||
| 367 | 371 | ||
| 368 | # | 372 | # |
| 369 | # CIF_FPU is set, restore floating-point controls and floating-point registers. | 373 | # CIF_FPU is set, restore floating-point controls and floating-point registers. |
| @@ -661,8 +665,8 @@ ENTRY(io_int_handler) | |||
| 661 | jo .Lio_notify_resume | 665 | jo .Lio_notify_resume |
| 662 | TSTMSK __LC_CPU_FLAGS,_CIF_FPU | 666 | TSTMSK __LC_CPU_FLAGS,_CIF_FPU |
| 663 | jo .Lio_vxrs | 667 | jo .Lio_vxrs |
| 664 | TSTMSK __LC_CPU_FLAGS,_CIF_ASCE | 668 | TSTMSK __LC_CPU_FLAGS,(_CIF_ASCE_PRIMARY|_CIF_ASCE_SECONDARY) |
| 665 | jo .Lio_uaccess | 669 | jnz .Lio_asce |
| 666 | j .Lio_return # beware of critical section cleanup | 670 | j .Lio_return # beware of critical section cleanup |
| 667 | 671 | ||
| 668 | # | 672 | # |
| @@ -675,12 +679,15 @@ ENTRY(io_int_handler) | |||
| 675 | j .Lio_return | 679 | j .Lio_return |
| 676 | 680 | ||
| 677 | # | 681 | # |
| 678 | # _CIF_ASCE is set, load user space asce | 682 | # _CIF_ASCE_PRIMARY and/or CIF_ASCE_SECONDARY set, load user space asce |
| 679 | # | 683 | # |
| 680 | .Lio_uaccess: | 684 | .Lio_asce: |
| 681 | ni __LC_CPU_FLAGS+7,255-_CIF_ASCE | 685 | ni __LC_CPU_FLAGS+7,255-_CIF_ASCE_PRIMARY |
| 682 | lctlg %c1,%c1,__LC_USER_ASCE # load primary asce | 686 | lctlg %c1,%c1,__LC_USER_ASCE # load primary asce |
| 683 | j .Lio_return | 687 | TSTMSK __LC_CPU_FLAGS,_CIF_ASCE_SECONDARY |
| 688 | jz .Lio_return | ||
| 689 | larl %r14,.Lio_return | ||
| 690 | jg set_fs_fixup | ||
| 684 | 691 | ||
| 685 | # | 692 | # |
| 686 | # CIF_FPU is set, restore floating-point controls and floating-point registers. | 693 | # CIF_FPU is set, restore floating-point controls and floating-point registers. |
diff --git a/arch/s390/kernel/entry.h b/arch/s390/kernel/entry.h index e79f030dd276..33f901865326 100644 --- a/arch/s390/kernel/entry.h +++ b/arch/s390/kernel/entry.h | |||
| @@ -80,5 +80,6 @@ long sys_s390_pci_mmio_read(unsigned long, void __user *, size_t); | |||
| 80 | DECLARE_PER_CPU(u64, mt_cycles[8]); | 80 | DECLARE_PER_CPU(u64, mt_cycles[8]); |
| 81 | 81 | ||
| 82 | void verify_facilities(void); | 82 | void verify_facilities(void); |
| 83 | void set_fs_fixup(void); | ||
| 83 | 84 | ||
| 84 | #endif /* _ENTRY_H */ | 85 | #endif /* _ENTRY_H */ |
diff --git a/arch/s390/kernel/nmi.c b/arch/s390/kernel/nmi.c index 56e14d073167..80c093e0c6f1 100644 --- a/arch/s390/kernel/nmi.c +++ b/arch/s390/kernel/nmi.c | |||
| @@ -116,6 +116,19 @@ static int notrace s390_validate_registers(union mci mci, int umode) | |||
| 116 | s390_handle_damage(); | 116 | s390_handle_damage(); |
| 117 | kill_task = 1; | 117 | kill_task = 1; |
| 118 | } | 118 | } |
| 119 | /* Validate control registers */ | ||
| 120 | if (!mci.cr) { | ||
| 121 | /* | ||
| 122 | * Control registers have unknown contents. | ||
| 123 | * Can't recover and therefore stopping machine. | ||
| 124 | */ | ||
| 125 | s390_handle_damage(); | ||
| 126 | } else { | ||
| 127 | asm volatile( | ||
| 128 | " lctlg 0,15,0(%0)\n" | ||
| 129 | " ptlb\n" | ||
| 130 | : : "a" (&S390_lowcore.cregs_save_area) : "memory"); | ||
| 131 | } | ||
| 119 | if (!mci.fp) { | 132 | if (!mci.fp) { |
| 120 | /* | 133 | /* |
| 121 | * Floating point registers can't be restored. If the | 134 | * Floating point registers can't be restored. If the |
| @@ -208,18 +221,6 @@ static int notrace s390_validate_registers(union mci mci, int umode) | |||
| 208 | */ | 221 | */ |
| 209 | kill_task = 1; | 222 | kill_task = 1; |
| 210 | } | 223 | } |
| 211 | /* Validate control registers */ | ||
| 212 | if (!mci.cr) { | ||
| 213 | /* | ||
| 214 | * Control registers have unknown contents. | ||
| 215 | * Can't recover and therefore stopping machine. | ||
| 216 | */ | ||
| 217 | s390_handle_damage(); | ||
| 218 | } else { | ||
| 219 | asm volatile( | ||
| 220 | " lctlg 0,15,0(%0)" | ||
| 221 | : : "a" (&S390_lowcore.cregs_save_area) : "memory"); | ||
| 222 | } | ||
| 223 | /* | 224 | /* |
| 224 | * We don't even try to validate the TOD register, since we simply | 225 | * We don't even try to validate the TOD register, since we simply |
| 225 | * can't write something sensible into that register. | 226 | * can't write something sensible into that register. |
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index c5b86b4a1a8b..54281660582c 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c | |||
| @@ -100,8 +100,8 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) | |||
| 100 | return 0; | 100 | return 0; |
| 101 | } | 101 | } |
| 102 | 102 | ||
| 103 | int copy_thread(unsigned long clone_flags, unsigned long new_stackp, | 103 | int copy_thread_tls(unsigned long clone_flags, unsigned long new_stackp, |
| 104 | unsigned long arg, struct task_struct *p) | 104 | unsigned long arg, struct task_struct *p, unsigned long tls) |
| 105 | { | 105 | { |
| 106 | struct fake_frame | 106 | struct fake_frame |
| 107 | { | 107 | { |
| @@ -156,7 +156,6 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp, | |||
| 156 | 156 | ||
| 157 | /* Set a new TLS ? */ | 157 | /* Set a new TLS ? */ |
| 158 | if (clone_flags & CLONE_SETTLS) { | 158 | if (clone_flags & CLONE_SETTLS) { |
| 159 | unsigned long tls = frame->childregs.gprs[6]; | ||
| 160 | if (is_compat_task()) { | 159 | if (is_compat_task()) { |
| 161 | p->thread.acrs[0] = (unsigned int)tls; | 160 | p->thread.acrs[0] = (unsigned int)tls; |
| 162 | } else { | 161 | } else { |
| @@ -234,3 +233,16 @@ unsigned long arch_randomize_brk(struct mm_struct *mm) | |||
| 234 | ret = PAGE_ALIGN(mm->brk + brk_rnd()); | 233 | ret = PAGE_ALIGN(mm->brk + brk_rnd()); |
| 235 | return (ret > mm->brk) ? ret : mm->brk; | 234 | return (ret > mm->brk) ? ret : mm->brk; |
| 236 | } | 235 | } |
| 236 | |||
| 237 | void set_fs_fixup(void) | ||
| 238 | { | ||
| 239 | struct pt_regs *regs = current_pt_regs(); | ||
| 240 | static bool warned; | ||
| 241 | |||
| 242 | set_fs(USER_DS); | ||
| 243 | if (warned) | ||
| 244 | return; | ||
| 245 | WARN(1, "Unbalanced set_fs - int code: 0x%x\n", regs->int_code); | ||
| 246 | show_registers(regs); | ||
| 247 | warned = true; | ||
| 248 | } | ||
diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c index 59ac93714fa4..a07b1ec1391d 100644 --- a/arch/s390/mm/gmap.c +++ b/arch/s390/mm/gmap.c | |||
| @@ -359,8 +359,8 @@ static int __gmap_unlink_by_vmaddr(struct gmap *gmap, unsigned long vmaddr) | |||
| 359 | spin_lock(&gmap->guest_table_lock); | 359 | spin_lock(&gmap->guest_table_lock); |
| 360 | entry = radix_tree_delete(&gmap->host_to_guest, vmaddr >> PMD_SHIFT); | 360 | entry = radix_tree_delete(&gmap->host_to_guest, vmaddr >> PMD_SHIFT); |
| 361 | if (entry) { | 361 | if (entry) { |
| 362 | flush = (*entry != _SEGMENT_ENTRY_INVALID); | 362 | flush = (*entry != _SEGMENT_ENTRY_EMPTY); |
| 363 | *entry = _SEGMENT_ENTRY_INVALID; | 363 | *entry = _SEGMENT_ENTRY_EMPTY; |
| 364 | } | 364 | } |
| 365 | spin_unlock(&gmap->guest_table_lock); | 365 | spin_unlock(&gmap->guest_table_lock); |
| 366 | return flush; | 366 | return flush; |
| @@ -589,7 +589,7 @@ int __gmap_link(struct gmap *gmap, unsigned long gaddr, unsigned long vmaddr) | |||
| 589 | return rc; | 589 | return rc; |
| 590 | ptl = pmd_lock(mm, pmd); | 590 | ptl = pmd_lock(mm, pmd); |
| 591 | spin_lock(&gmap->guest_table_lock); | 591 | spin_lock(&gmap->guest_table_lock); |
| 592 | if (*table == _SEGMENT_ENTRY_INVALID) { | 592 | if (*table == _SEGMENT_ENTRY_EMPTY) { |
| 593 | rc = radix_tree_insert(&gmap->host_to_guest, | 593 | rc = radix_tree_insert(&gmap->host_to_guest, |
| 594 | vmaddr >> PMD_SHIFT, table); | 594 | vmaddr >> PMD_SHIFT, table); |
| 595 | if (!rc) | 595 | if (!rc) |
diff --git a/arch/s390/mm/hugetlbpage.c b/arch/s390/mm/hugetlbpage.c index a03816227719..9b4050caa4e9 100644 --- a/arch/s390/mm/hugetlbpage.c +++ b/arch/s390/mm/hugetlbpage.c | |||
| @@ -62,7 +62,7 @@ static inline unsigned long __pte_to_rste(pte_t pte) | |||
| 62 | rste |= move_set_bit(pte_val(pte), _PAGE_NOEXEC, | 62 | rste |= move_set_bit(pte_val(pte), _PAGE_NOEXEC, |
| 63 | _SEGMENT_ENTRY_NOEXEC); | 63 | _SEGMENT_ENTRY_NOEXEC); |
| 64 | } else | 64 | } else |
| 65 | rste = _SEGMENT_ENTRY_INVALID; | 65 | rste = _SEGMENT_ENTRY_EMPTY; |
| 66 | return rste; | 66 | return rste; |
| 67 | } | 67 | } |
| 68 | 68 | ||
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 2cac445b02fd..0b49dbc423e2 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig | |||
| @@ -62,19 +62,32 @@ config CRYPTO_DEV_GEODE | |||
| 62 | will be called geode-aes. | 62 | will be called geode-aes. |
| 63 | 63 | ||
| 64 | config ZCRYPT | 64 | config ZCRYPT |
| 65 | tristate "Support for PCI-attached cryptographic adapters" | 65 | tristate "Support for s390 cryptographic adapters" |
| 66 | depends on S390 | 66 | depends on S390 |
| 67 | select HW_RANDOM | 67 | select HW_RANDOM |
| 68 | help | 68 | help |
| 69 | Select this option if you want to use a PCI-attached cryptographic | 69 | Select this option if you want to enable support for |
| 70 | adapter like: | 70 | s390 cryptographic adapters like: |
| 71 | + PCI Cryptographic Accelerator (PCICA) | ||
| 72 | + PCI Cryptographic Coprocessor (PCICC) | ||
| 73 | + PCI-X Cryptographic Coprocessor (PCIXCC) | 71 | + PCI-X Cryptographic Coprocessor (PCIXCC) |
| 74 | + Crypto Express2 Coprocessor (CEX2C) | 72 | + Crypto Express 2,3,4 or 5 Coprocessor (CEXxC) |
| 75 | + Crypto Express2 Accelerator (CEX2A) | 73 | + Crypto Express 2,3,4 or 5 Accelerator (CEXxA) |
| 76 | + Crypto Express3 Coprocessor (CEX3C) | 74 | + Crypto Express 4 or 5 EP11 Coprocessor (CEXxP) |
| 77 | + Crypto Express3 Accelerator (CEX3A) | 75 | |
| 76 | config PKEY | ||
| 77 | tristate "Kernel API for protected key handling" | ||
| 78 | depends on S390 | ||
| 79 | depends on ZCRYPT | ||
| 80 | help | ||
| 81 | With this option enabled the pkey kernel module provides an API | ||
| 82 | for creation and handling of protected keys. Other parts of the | ||
| 83 | kernel or userspace applications may use these functions. | ||
| 84 | |||
| 85 | Select this option if you want to enable the kernel and userspace | ||
| 86 | API for proteced key handling. | ||
| 87 | |||
| 88 | Please note that creation of protected keys from secure keys | ||
| 89 | requires to have at least one CEX card in coprocessor mode | ||
| 90 | available at runtime. | ||
| 78 | 91 | ||
| 79 | config CRYPTO_SHA1_S390 | 92 | config CRYPTO_SHA1_S390 |
| 80 | tristate "SHA1 digest algorithm" | 93 | tristate "SHA1 digest algorithm" |
| @@ -124,6 +137,7 @@ config CRYPTO_AES_S390 | |||
| 124 | depends on S390 | 137 | depends on S390 |
| 125 | select CRYPTO_ALGAPI | 138 | select CRYPTO_ALGAPI |
| 126 | select CRYPTO_BLKCIPHER | 139 | select CRYPTO_BLKCIPHER |
| 140 | select PKEY | ||
| 127 | help | 141 | help |
| 128 | This is the s390 hardware accelerated implementation of the | 142 | This is the s390 hardware accelerated implementation of the |
| 129 | AES cipher algorithms (FIPS-197). | 143 | AES cipher algorithms (FIPS-197). |
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 0f1713727d4c..0b38217f8147 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
| @@ -4864,7 +4864,7 @@ static void dasd_eckd_dump_sense_tcw(struct dasd_device *device, | |||
| 4864 | break; | 4864 | break; |
| 4865 | case 3: /* tsa_intrg */ | 4865 | case 3: /* tsa_intrg */ |
| 4866 | len += sprintf(page + len, PRINTK_HEADER | 4866 | len += sprintf(page + len, PRINTK_HEADER |
| 4867 | " tsb->tsa.intrg.: not supportet yet\n"); | 4867 | " tsb->tsa.intrg.: not supported yet\n"); |
| 4868 | break; | 4868 | break; |
| 4869 | } | 4869 | } |
| 4870 | 4870 | ||
diff --git a/drivers/s390/cio/ioasm.c b/drivers/s390/cio/ioasm.c index 8225da619014..4182f60124da 100644 --- a/drivers/s390/cio/ioasm.c +++ b/drivers/s390/cio/ioasm.c | |||
| @@ -165,13 +165,15 @@ int tpi(struct tpi_info *addr) | |||
| 165 | int chsc(void *chsc_area) | 165 | int chsc(void *chsc_area) |
| 166 | { | 166 | { |
| 167 | typedef struct { char _[4096]; } addr_type; | 167 | typedef struct { char _[4096]; } addr_type; |
| 168 | int cc; | 168 | int cc = -EIO; |
| 169 | 169 | ||
| 170 | asm volatile( | 170 | asm volatile( |
| 171 | " .insn rre,0xb25f0000,%2,0\n" | 171 | " .insn rre,0xb25f0000,%2,0\n" |
| 172 | " ipm %0\n" | 172 | "0: ipm %0\n" |
| 173 | " srl %0,28\n" | 173 | " srl %0,28\n" |
| 174 | : "=d" (cc), "=m" (*(addr_type *) chsc_area) | 174 | "1:\n" |
| 175 | EX_TABLE(0b, 1b) | ||
| 176 | : "+d" (cc), "=m" (*(addr_type *) chsc_area) | ||
| 175 | : "d" (chsc_area), "m" (*(addr_type *) chsc_area) | 177 | : "d" (chsc_area), "m" (*(addr_type *) chsc_area) |
| 176 | : "cc"); | 178 | : "cc"); |
| 177 | trace_s390_cio_chsc(chsc_area, cc); | 179 | trace_s390_cio_chsc(chsc_area, cc); |
diff --git a/drivers/s390/crypto/Makefile b/drivers/s390/crypto/Makefile index 0a7fb83f35e5..be36f1010d75 100644 --- a/drivers/s390/crypto/Makefile +++ b/drivers/s390/crypto/Makefile | |||
| @@ -10,3 +10,7 @@ zcrypt-objs += zcrypt_msgtype6.o zcrypt_msgtype50.o | |||
| 10 | obj-$(CONFIG_ZCRYPT) += zcrypt.o | 10 | obj-$(CONFIG_ZCRYPT) += zcrypt.o |
| 11 | # adapter drivers depend on ap.o and zcrypt.o | 11 | # adapter drivers depend on ap.o and zcrypt.o |
| 12 | obj-$(CONFIG_ZCRYPT) += zcrypt_pcixcc.o zcrypt_cex2a.o zcrypt_cex4.o | 12 | obj-$(CONFIG_ZCRYPT) += zcrypt_pcixcc.o zcrypt_cex2a.o zcrypt_cex4.o |
| 13 | |||
| 14 | # pkey kernel module | ||
| 15 | pkey-objs := pkey_api.o | ||
| 16 | obj-$(CONFIG_PKEY) += pkey.o | ||
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 56db76c05775..9be4596d8a08 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c | |||
| @@ -1107,16 +1107,6 @@ static void ap_config_timeout(unsigned long ptr) | |||
| 1107 | queue_work(system_long_wq, &ap_scan_work); | 1107 | queue_work(system_long_wq, &ap_scan_work); |
| 1108 | } | 1108 | } |
| 1109 | 1109 | ||
| 1110 | static void ap_reset_domain(void) | ||
| 1111 | { | ||
| 1112 | int i; | ||
| 1113 | |||
| 1114 | if (ap_domain_index == -1 || !ap_test_config_domain(ap_domain_index)) | ||
| 1115 | return; | ||
| 1116 | for (i = 0; i < AP_DEVICES; i++) | ||
| 1117 | ap_rapq(AP_MKQID(i, ap_domain_index)); | ||
| 1118 | } | ||
| 1119 | |||
| 1120 | static void ap_reset_all(void) | 1110 | static void ap_reset_all(void) |
| 1121 | { | 1111 | { |
| 1122 | int i, j; | 1112 | int i, j; |
diff --git a/drivers/s390/crypto/ap_card.c b/drivers/s390/crypto/ap_card.c index 1cd9128593e4..cfa161ccc74e 100644 --- a/drivers/s390/crypto/ap_card.c +++ b/drivers/s390/crypto/ap_card.c | |||
| @@ -58,9 +58,9 @@ static ssize_t ap_functions_show(struct device *dev, | |||
| 58 | 58 | ||
| 59 | static DEVICE_ATTR(ap_functions, 0444, ap_functions_show, NULL); | 59 | static DEVICE_ATTR(ap_functions, 0444, ap_functions_show, NULL); |
| 60 | 60 | ||
| 61 | static ssize_t ap_request_count_show(struct device *dev, | 61 | static ssize_t ap_req_count_show(struct device *dev, |
| 62 | struct device_attribute *attr, | 62 | struct device_attribute *attr, |
| 63 | char *buf) | 63 | char *buf) |
| 64 | { | 64 | { |
| 65 | struct ap_card *ac = to_ap_card(dev); | 65 | struct ap_card *ac = to_ap_card(dev); |
| 66 | unsigned int req_cnt; | 66 | unsigned int req_cnt; |
| @@ -72,7 +72,23 @@ static ssize_t ap_request_count_show(struct device *dev, | |||
| 72 | return snprintf(buf, PAGE_SIZE, "%d\n", req_cnt); | 72 | return snprintf(buf, PAGE_SIZE, "%d\n", req_cnt); |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | static DEVICE_ATTR(request_count, 0444, ap_request_count_show, NULL); | 75 | static ssize_t ap_req_count_store(struct device *dev, |
| 76 | struct device_attribute *attr, | ||
| 77 | const char *buf, size_t count) | ||
| 78 | { | ||
| 79 | struct ap_card *ac = to_ap_card(dev); | ||
| 80 | struct ap_queue *aq; | ||
| 81 | |||
| 82 | spin_lock_bh(&ap_list_lock); | ||
| 83 | for_each_ap_queue(aq, ac) | ||
| 84 | aq->total_request_count = 0; | ||
| 85 | spin_unlock_bh(&ap_list_lock); | ||
| 86 | atomic_set(&ac->total_request_count, 0); | ||
| 87 | |||
| 88 | return count; | ||
| 89 | } | ||
| 90 | |||
| 91 | static DEVICE_ATTR(request_count, 0644, ap_req_count_show, ap_req_count_store); | ||
| 76 | 92 | ||
| 77 | static ssize_t ap_requestq_count_show(struct device *dev, | 93 | static ssize_t ap_requestq_count_show(struct device *dev, |
| 78 | struct device_attribute *attr, char *buf) | 94 | struct device_attribute *attr, char *buf) |
diff --git a/drivers/s390/crypto/ap_queue.c b/drivers/s390/crypto/ap_queue.c index 7be67fa9f224..480c58a63769 100644 --- a/drivers/s390/crypto/ap_queue.c +++ b/drivers/s390/crypto/ap_queue.c | |||
| @@ -459,9 +459,9 @@ EXPORT_SYMBOL(ap_queue_resume); | |||
| 459 | /* | 459 | /* |
| 460 | * AP queue related attributes. | 460 | * AP queue related attributes. |
| 461 | */ | 461 | */ |
| 462 | static ssize_t ap_request_count_show(struct device *dev, | 462 | static ssize_t ap_req_count_show(struct device *dev, |
| 463 | struct device_attribute *attr, | 463 | struct device_attribute *attr, |
| 464 | char *buf) | 464 | char *buf) |
| 465 | { | 465 | { |
| 466 | struct ap_queue *aq = to_ap_queue(dev); | 466 | struct ap_queue *aq = to_ap_queue(dev); |
| 467 | unsigned int req_cnt; | 467 | unsigned int req_cnt; |
| @@ -472,7 +472,20 @@ static ssize_t ap_request_count_show(struct device *dev, | |||
| 472 | return snprintf(buf, PAGE_SIZE, "%d\n", req_cnt); | 472 | return snprintf(buf, PAGE_SIZE, "%d\n", req_cnt); |
| 473 | } | 473 | } |
| 474 | 474 | ||
| 475 | static DEVICE_ATTR(request_count, 0444, ap_request_count_show, NULL); | 475 | static ssize_t ap_req_count_store(struct device *dev, |
| 476 | struct device_attribute *attr, | ||
| 477 | const char *buf, size_t count) | ||
| 478 | { | ||
| 479 | struct ap_queue *aq = to_ap_queue(dev); | ||
| 480 | |||
| 481 | spin_lock_bh(&aq->lock); | ||
| 482 | aq->total_request_count = 0; | ||
| 483 | spin_unlock_bh(&aq->lock); | ||
| 484 | |||
| 485 | return count; | ||
| 486 | } | ||
| 487 | |||
| 488 | static DEVICE_ATTR(request_count, 0644, ap_req_count_show, ap_req_count_store); | ||
| 476 | 489 | ||
| 477 | static ssize_t ap_requestq_count_show(struct device *dev, | 490 | static ssize_t ap_requestq_count_show(struct device *dev, |
| 478 | struct device_attribute *attr, char *buf) | 491 | struct device_attribute *attr, char *buf) |
diff --git a/drivers/s390/crypto/pkey_api.c b/drivers/s390/crypto/pkey_api.c new file mode 100644 index 000000000000..40f1136f5568 --- /dev/null +++ b/drivers/s390/crypto/pkey_api.c | |||
| @@ -0,0 +1,1148 @@ | |||
| 1 | /* | ||
| 2 | * pkey device driver | ||
| 3 | * | ||
| 4 | * Copyright IBM Corp. 2017 | ||
| 5 | * Author(s): Harald Freudenberger | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License (version 2 only) | ||
| 9 | * as published by the Free Software Foundation. | ||
| 10 | * | ||
| 11 | */ | ||
| 12 | |||
| 13 | #define KMSG_COMPONENT "pkey" | ||
| 14 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | ||
| 15 | |||
| 16 | #include <linux/fs.h> | ||
| 17 | #include <linux/init.h> | ||
| 18 | #include <linux/miscdevice.h> | ||
| 19 | #include <linux/module.h> | ||
| 20 | #include <linux/slab.h> | ||
| 21 | #include <linux/kallsyms.h> | ||
| 22 | #include <linux/debugfs.h> | ||
| 23 | #include <asm/zcrypt.h> | ||
| 24 | #include <asm/cpacf.h> | ||
| 25 | #include <asm/pkey.h> | ||
| 26 | |||
| 27 | #include "zcrypt_api.h" | ||
| 28 | |||
| 29 | MODULE_LICENSE("GPL"); | ||
| 30 | MODULE_AUTHOR("IBM Corporation"); | ||
| 31 | MODULE_DESCRIPTION("s390 protected key interface"); | ||
| 32 | |||
| 33 | /* Size of parameter block used for all cca requests/replies */ | ||
| 34 | #define PARMBSIZE 512 | ||
| 35 | |||
| 36 | /* Size of vardata block used for some of the cca requests/replies */ | ||
| 37 | #define VARDATASIZE 4096 | ||
| 38 | |||
| 39 | /* | ||
| 40 | * debug feature data and functions | ||
| 41 | */ | ||
| 42 | |||
| 43 | static debug_info_t *debug_info; | ||
| 44 | |||
| 45 | #define DEBUG_DBG(...) debug_sprintf_event(debug_info, 6, ##__VA_ARGS__) | ||
| 46 | #define DEBUG_INFO(...) debug_sprintf_event(debug_info, 5, ##__VA_ARGS__) | ||
| 47 | #define DEBUG_WARN(...) debug_sprintf_event(debug_info, 4, ##__VA_ARGS__) | ||
| 48 | #define DEBUG_ERR(...) debug_sprintf_event(debug_info, 3, ##__VA_ARGS__) | ||
| 49 | |||
| 50 | static void __init pkey_debug_init(void) | ||
| 51 | { | ||
| 52 | debug_info = debug_register("pkey", 1, 1, 4 * sizeof(long)); | ||
| 53 | debug_register_view(debug_info, &debug_sprintf_view); | ||
| 54 | debug_set_level(debug_info, 3); | ||
| 55 | } | ||
| 56 | |||
| 57 | static void __exit pkey_debug_exit(void) | ||
| 58 | { | ||
| 59 | debug_unregister(debug_info); | ||
| 60 | } | ||
| 61 | |||
| 62 | /* inside view of a secure key token (only type 0x01 version 0x04) */ | ||
| 63 | struct secaeskeytoken { | ||
| 64 | u8 type; /* 0x01 for internal key token */ | ||
| 65 | u8 res0[3]; | ||
| 66 | u8 version; /* should be 0x04 */ | ||
| 67 | u8 res1[1]; | ||
| 68 | u8 flag; /* key flags */ | ||
| 69 | u8 res2[1]; | ||
| 70 | u64 mkvp; /* master key verification pattern */ | ||
| 71 | u8 key[32]; /* key value (encrypted) */ | ||
| 72 | u8 cv[8]; /* control vector */ | ||
| 73 | u16 bitsize; /* key bit size */ | ||
| 74 | u16 keysize; /* key byte size */ | ||
| 75 | u8 tvv[4]; /* token validation value */ | ||
| 76 | } __packed; | ||
| 77 | |||
| 78 | /* | ||
| 79 | * Simple check if the token is a valid CCA secure AES key | ||
| 80 | * token. If keybitsize is given, the bitsize of the key is | ||
| 81 | * also checked. Returns 0 on success or errno value on failure. | ||
| 82 | */ | ||
| 83 | static int check_secaeskeytoken(u8 *token, int keybitsize) | ||
| 84 | { | ||
| 85 | struct secaeskeytoken *t = (struct secaeskeytoken *) token; | ||
| 86 | |||
| 87 | if (t->type != 0x01) { | ||
| 88 | DEBUG_ERR( | ||
| 89 | "check_secaeskeytoken secure token check failed, type mismatch 0x%02x != 0x01\n", | ||
| 90 | (int) t->type); | ||
| 91 | return -EINVAL; | ||
| 92 | } | ||
| 93 | if (t->version != 0x04) { | ||
| 94 | DEBUG_ERR( | ||
| 95 | "check_secaeskeytoken secure token check failed, version mismatch 0x%02x != 0x04\n", | ||
| 96 | (int) t->version); | ||
| 97 | return -EINVAL; | ||
| 98 | } | ||
| 99 | if (keybitsize > 0 && t->bitsize != keybitsize) { | ||
| 100 | DEBUG_ERR( | ||
| 101 | "check_secaeskeytoken secure token check failed, bitsize mismatch %d != %d\n", | ||
| 102 | (int) t->bitsize, keybitsize); | ||
| 103 | return -EINVAL; | ||
| 104 | } | ||
| 105 | |||
| 106 | return 0; | ||
| 107 | } | ||
| 108 | |||
| 109 | /* | ||
| 110 | * Allocate consecutive memory for request CPRB, request param | ||
| 111 | * block, reply CPRB and reply param block and fill in values | ||
| 112 | * for the common fields. Returns 0 on success or errno value | ||
| 113 | * on failure. | ||
| 114 | */ | ||
| 115 | static int alloc_and_prep_cprbmem(size_t paramblen, | ||
| 116 | u8 **pcprbmem, | ||
| 117 | struct CPRBX **preqCPRB, | ||
| 118 | struct CPRBX **prepCPRB) | ||
| 119 | { | ||
| 120 | u8 *cprbmem; | ||
| 121 | size_t cprbplusparamblen = sizeof(struct CPRBX) + paramblen; | ||
| 122 | struct CPRBX *preqcblk, *prepcblk; | ||
| 123 | |||
| 124 | /* | ||
| 125 | * allocate consecutive memory for request CPRB, request param | ||
| 126 | * block, reply CPRB and reply param block | ||
| 127 | */ | ||
| 128 | cprbmem = kmalloc(2 * cprbplusparamblen, GFP_KERNEL); | ||
| 129 | if (!cprbmem) | ||
| 130 | return -ENOMEM; | ||
| 131 | memset(cprbmem, 0, 2 * cprbplusparamblen); | ||
| 132 | |||
| 133 | preqcblk = (struct CPRBX *) cprbmem; | ||
| 134 | prepcblk = (struct CPRBX *) (cprbmem + cprbplusparamblen); | ||
| 135 | |||
| 136 | /* fill request cprb struct */ | ||
| 137 | preqcblk->cprb_len = sizeof(struct CPRBX); | ||
| 138 | preqcblk->cprb_ver_id = 0x02; | ||
| 139 | memcpy(preqcblk->func_id, "T2", 2); | ||
| 140 | preqcblk->rpl_msgbl = cprbplusparamblen; | ||
| 141 | if (paramblen) { | ||
| 142 | preqcblk->req_parmb = | ||
| 143 | ((u8 *) preqcblk) + sizeof(struct CPRBX); | ||
| 144 | preqcblk->rpl_parmb = | ||
| 145 | ((u8 *) prepcblk) + sizeof(struct CPRBX); | ||
| 146 | } | ||
| 147 | |||
| 148 | *pcprbmem = cprbmem; | ||
| 149 | *preqCPRB = preqcblk; | ||
| 150 | *prepCPRB = prepcblk; | ||
| 151 | |||
| 152 | return 0; | ||
| 153 | } | ||
| 154 | |||
| 155 | /* | ||
| 156 | * Free the cprb memory allocated with the function above. | ||
| 157 | * If the scrub value is not zero, the memory is filled | ||
| 158 | * with zeros before freeing (useful if there was some | ||
| 159 | * clear key material in there). | ||
| 160 | */ | ||
| 161 | static void free_cprbmem(void *mem, size_t paramblen, int scrub) | ||
| 162 | { | ||
| 163 | if (scrub) | ||
| 164 | memzero_explicit(mem, 2 * (sizeof(struct CPRBX) + paramblen)); | ||
| 165 | kfree(mem); | ||
| 166 | } | ||
| 167 | |||
| 168 | /* | ||
| 169 | * Helper function to prepare the xcrb struct | ||
| 170 | */ | ||
| 171 | static inline void prep_xcrb(struct ica_xcRB *pxcrb, | ||
| 172 | u16 cardnr, | ||
| 173 | struct CPRBX *preqcblk, | ||
| 174 | struct CPRBX *prepcblk) | ||
| 175 | { | ||
| 176 | memset(pxcrb, 0, sizeof(*pxcrb)); | ||
| 177 | pxcrb->agent_ID = 0x4341; /* 'CA' */ | ||
| 178 | pxcrb->user_defined = (cardnr == 0xFFFF ? AUTOSELECT : cardnr); | ||
| 179 | pxcrb->request_control_blk_length = | ||
| 180 | preqcblk->cprb_len + preqcblk->req_parml; | ||
| 181 | pxcrb->request_control_blk_addr = (void *) preqcblk; | ||
| 182 | pxcrb->reply_control_blk_length = preqcblk->rpl_msgbl; | ||
| 183 | pxcrb->reply_control_blk_addr = (void *) prepcblk; | ||
| 184 | } | ||
| 185 | |||
| 186 | /* | ||
| 187 | * Helper function which calls zcrypt_send_cprb with | ||
| 188 | * memory management segment adjusted to kernel space | ||
| 189 | * so that the copy_from_user called within this | ||
| 190 | * function do in fact copy from kernel space. | ||
| 191 | */ | ||
| 192 | static inline int _zcrypt_send_cprb(struct ica_xcRB *xcrb) | ||
| 193 | { | ||
| 194 | int rc; | ||
| 195 | mm_segment_t old_fs = get_fs(); | ||
| 196 | |||
| 197 | set_fs(KERNEL_DS); | ||
| 198 | rc = zcrypt_send_cprb(xcrb); | ||
| 199 | set_fs(old_fs); | ||
| 200 | |||
| 201 | return rc; | ||
| 202 | } | ||
| 203 | |||
| 204 | /* | ||
| 205 | * Generate (random) AES secure key. | ||
| 206 | */ | ||
| 207 | int pkey_genseckey(u16 cardnr, u16 domain, | ||
| 208 | u32 keytype, struct pkey_seckey *seckey) | ||
| 209 | { | ||
| 210 | int i, rc, keysize; | ||
| 211 | int seckeysize; | ||
| 212 | u8 *mem; | ||
| 213 | struct CPRBX *preqcblk, *prepcblk; | ||
| 214 | struct ica_xcRB xcrb; | ||
| 215 | struct kgreqparm { | ||
| 216 | u8 subfunc_code[2]; | ||
| 217 | u16 rule_array_len; | ||
| 218 | struct lv1 { | ||
| 219 | u16 len; | ||
| 220 | char key_form[8]; | ||
| 221 | char key_length[8]; | ||
| 222 | char key_type1[8]; | ||
| 223 | char key_type2[8]; | ||
| 224 | } lv1; | ||
| 225 | struct lv2 { | ||
| 226 | u16 len; | ||
| 227 | struct keyid { | ||
| 228 | u16 len; | ||
| 229 | u16 attr; | ||
| 230 | u8 data[SECKEYBLOBSIZE]; | ||
| 231 | } keyid[6]; | ||
| 232 | } lv2; | ||
| 233 | } *preqparm; | ||
| 234 | struct kgrepparm { | ||
| 235 | u8 subfunc_code[2]; | ||
| 236 | u16 rule_array_len; | ||
| 237 | struct lv3 { | ||
| 238 | u16 len; | ||
| 239 | u16 keyblocklen; | ||
| 240 | struct { | ||
| 241 | u16 toklen; | ||
| 242 | u16 tokattr; | ||
| 243 | u8 tok[0]; | ||
| 244 | /* ... some more data ... */ | ||
| 245 | } keyblock; | ||
| 246 | } lv3; | ||
| 247 | } *prepparm; | ||
| 248 | |||
| 249 | /* get already prepared memory for 2 cprbs with param block each */ | ||
| 250 | rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk); | ||
| 251 | if (rc) | ||
| 252 | return rc; | ||
| 253 | |||
| 254 | /* fill request cprb struct */ | ||
| 255 | preqcblk->domain = domain; | ||
| 256 | |||
| 257 | /* fill request cprb param block with KG request */ | ||
| 258 | preqparm = (struct kgreqparm *) preqcblk->req_parmb; | ||
| 259 | memcpy(preqparm->subfunc_code, "KG", 2); | ||
| 260 | preqparm->rule_array_len = sizeof(preqparm->rule_array_len); | ||
| 261 | preqparm->lv1.len = sizeof(struct lv1); | ||
| 262 | memcpy(preqparm->lv1.key_form, "OP ", 8); | ||
| 263 | switch (keytype) { | ||
| 264 | case PKEY_KEYTYPE_AES_128: | ||
| 265 | keysize = 16; | ||
| 266 | memcpy(preqparm->lv1.key_length, "KEYLN16 ", 8); | ||
| 267 | break; | ||
| 268 | case PKEY_KEYTYPE_AES_192: | ||
| 269 | keysize = 24; | ||
| 270 | memcpy(preqparm->lv1.key_length, "KEYLN24 ", 8); | ||
| 271 | break; | ||
| 272 | case PKEY_KEYTYPE_AES_256: | ||
| 273 | keysize = 32; | ||
| 274 | memcpy(preqparm->lv1.key_length, "KEYLN32 ", 8); | ||
| 275 | break; | ||
| 276 | default: | ||
| 277 | DEBUG_ERR( | ||
| 278 | "pkey_genseckey unknown/unsupported keytype %d\n", | ||
| 279 | keytype); | ||
| 280 | rc = -EINVAL; | ||
| 281 | goto out; | ||
| 282 | } | ||
| 283 | memcpy(preqparm->lv1.key_type1, "AESDATA ", 8); | ||
| 284 | preqparm->lv2.len = sizeof(struct lv2); | ||
| 285 | for (i = 0; i < 6; i++) { | ||
| 286 | preqparm->lv2.keyid[i].len = sizeof(struct keyid); | ||
| 287 | preqparm->lv2.keyid[i].attr = (i == 2 ? 0x30 : 0x10); | ||
| 288 | } | ||
| 289 | preqcblk->req_parml = sizeof(struct kgreqparm); | ||
| 290 | |||
| 291 | /* fill xcrb struct */ | ||
| 292 | prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk); | ||
| 293 | |||
| 294 | /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */ | ||
| 295 | rc = _zcrypt_send_cprb(&xcrb); | ||
| 296 | if (rc) { | ||
| 297 | DEBUG_ERR( | ||
| 298 | "pkey_genseckey zcrypt_send_cprb (cardnr=%d domain=%d) failed with errno %d\n", | ||
| 299 | (int) cardnr, (int) domain, rc); | ||
| 300 | goto out; | ||
| 301 | } | ||
| 302 | |||
| 303 | /* check response returncode and reasoncode */ | ||
| 304 | if (prepcblk->ccp_rtcode != 0) { | ||
| 305 | DEBUG_ERR( | ||
| 306 | "pkey_genseckey secure key generate failure, card response %d/%d\n", | ||
| 307 | (int) prepcblk->ccp_rtcode, | ||
| 308 | (int) prepcblk->ccp_rscode); | ||
| 309 | rc = -EIO; | ||
| 310 | goto out; | ||
| 311 | } | ||
| 312 | |||
| 313 | /* process response cprb param block */ | ||
| 314 | prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); | ||
| 315 | prepparm = (struct kgrepparm *) prepcblk->rpl_parmb; | ||
| 316 | |||
| 317 | /* check length of the returned secure key token */ | ||
| 318 | seckeysize = prepparm->lv3.keyblock.toklen | ||
| 319 | - sizeof(prepparm->lv3.keyblock.toklen) | ||
| 320 | - sizeof(prepparm->lv3.keyblock.tokattr); | ||
| 321 | if (seckeysize != SECKEYBLOBSIZE) { | ||
| 322 | DEBUG_ERR( | ||
| 323 | "pkey_genseckey secure token size mismatch %d != %d bytes\n", | ||
| 324 | seckeysize, SECKEYBLOBSIZE); | ||
| 325 | rc = -EIO; | ||
| 326 | goto out; | ||
| 327 | } | ||
| 328 | |||
| 329 | /* check secure key token */ | ||
| 330 | rc = check_secaeskeytoken(prepparm->lv3.keyblock.tok, 8*keysize); | ||
| 331 | if (rc) { | ||
| 332 | rc = -EIO; | ||
| 333 | goto out; | ||
| 334 | } | ||
| 335 | |||
| 336 | /* copy the generated secure key token */ | ||
| 337 | memcpy(seckey->seckey, prepparm->lv3.keyblock.tok, SECKEYBLOBSIZE); | ||
| 338 | |||
| 339 | out: | ||
| 340 | free_cprbmem(mem, PARMBSIZE, 0); | ||
| 341 | return rc; | ||
| 342 | } | ||
| 343 | EXPORT_SYMBOL(pkey_genseckey); | ||
| 344 | |||
| 345 | /* | ||
| 346 | * Generate an AES secure key with given key value. | ||
| 347 | */ | ||
| 348 | int pkey_clr2seckey(u16 cardnr, u16 domain, u32 keytype, | ||
| 349 | const struct pkey_clrkey *clrkey, | ||
| 350 | struct pkey_seckey *seckey) | ||
| 351 | { | ||
| 352 | int rc, keysize, seckeysize; | ||
| 353 | u8 *mem; | ||
| 354 | struct CPRBX *preqcblk, *prepcblk; | ||
| 355 | struct ica_xcRB xcrb; | ||
| 356 | struct cmreqparm { | ||
| 357 | u8 subfunc_code[2]; | ||
| 358 | u16 rule_array_len; | ||
| 359 | char rule_array[8]; | ||
| 360 | struct lv1 { | ||
| 361 | u16 len; | ||
| 362 | u8 clrkey[0]; | ||
| 363 | } lv1; | ||
| 364 | struct lv2 { | ||
| 365 | u16 len; | ||
| 366 | struct keyid { | ||
| 367 | u16 len; | ||
| 368 | u16 attr; | ||
| 369 | u8 data[SECKEYBLOBSIZE]; | ||
| 370 | } keyid; | ||
| 371 | } lv2; | ||
| 372 | } *preqparm; | ||
| 373 | struct lv2 *plv2; | ||
| 374 | struct cmrepparm { | ||
| 375 | u8 subfunc_code[2]; | ||
| 376 | u16 rule_array_len; | ||
| 377 | struct lv3 { | ||
| 378 | u16 len; | ||
| 379 | u16 keyblocklen; | ||
| 380 | struct { | ||
| 381 | u16 toklen; | ||
| 382 | u16 tokattr; | ||
| 383 | u8 tok[0]; | ||
| 384 | /* ... some more data ... */ | ||
| 385 | } keyblock; | ||
| 386 | } lv3; | ||
| 387 | } *prepparm; | ||
| 388 | |||
| 389 | /* get already prepared memory for 2 cprbs with param block each */ | ||
| 390 | rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk); | ||
| 391 | if (rc) | ||
| 392 | return rc; | ||
| 393 | |||
| 394 | /* fill request cprb struct */ | ||
| 395 | preqcblk->domain = domain; | ||
| 396 | |||
| 397 | /* fill request cprb param block with CM request */ | ||
| 398 | preqparm = (struct cmreqparm *) preqcblk->req_parmb; | ||
| 399 | memcpy(preqparm->subfunc_code, "CM", 2); | ||
| 400 | memcpy(preqparm->rule_array, "AES ", 8); | ||
| 401 | preqparm->rule_array_len = | ||
| 402 | sizeof(preqparm->rule_array_len) + sizeof(preqparm->rule_array); | ||
| 403 | switch (keytype) { | ||
| 404 | case PKEY_KEYTYPE_AES_128: | ||
| 405 | keysize = 16; | ||
| 406 | break; | ||
| 407 | case PKEY_KEYTYPE_AES_192: | ||
| 408 | keysize = 24; | ||
| 409 | break; | ||
| 410 | case PKEY_KEYTYPE_AES_256: | ||
| 411 | keysize = 32; | ||
| 412 | break; | ||
| 413 | default: | ||
| 414 | DEBUG_ERR( | ||
| 415 | "pkey_clr2seckey unknown/unsupported keytype %d\n", | ||
| 416 | keytype); | ||
| 417 | rc = -EINVAL; | ||
| 418 | goto out; | ||
| 419 | } | ||
| 420 | preqparm->lv1.len = sizeof(struct lv1) + keysize; | ||
| 421 | memcpy(preqparm->lv1.clrkey, clrkey->clrkey, keysize); | ||
| 422 | plv2 = (struct lv2 *) (((u8 *) &preqparm->lv2) + keysize); | ||
| 423 | plv2->len = sizeof(struct lv2); | ||
| 424 | plv2->keyid.len = sizeof(struct keyid); | ||
| 425 | plv2->keyid.attr = 0x30; | ||
| 426 | preqcblk->req_parml = sizeof(struct cmreqparm) + keysize; | ||
| 427 | |||
| 428 | /* fill xcrb struct */ | ||
| 429 | prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk); | ||
| 430 | |||
| 431 | /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */ | ||
| 432 | rc = _zcrypt_send_cprb(&xcrb); | ||
| 433 | if (rc) { | ||
| 434 | DEBUG_ERR( | ||
| 435 | "pkey_clr2seckey zcrypt_send_cprb (cardnr=%d domain=%d) failed with errno %d\n", | ||
| 436 | (int) cardnr, (int) domain, rc); | ||
| 437 | goto out; | ||
| 438 | } | ||
| 439 | |||
| 440 | /* check response returncode and reasoncode */ | ||
| 441 | if (prepcblk->ccp_rtcode != 0) { | ||
| 442 | DEBUG_ERR( | ||
| 443 | "pkey_clr2seckey clear key import failure, card response %d/%d\n", | ||
| 444 | (int) prepcblk->ccp_rtcode, | ||
| 445 | (int) prepcblk->ccp_rscode); | ||
| 446 | rc = -EIO; | ||
| 447 | goto out; | ||
| 448 | } | ||
| 449 | |||
| 450 | /* process response cprb param block */ | ||
| 451 | prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); | ||
| 452 | prepparm = (struct cmrepparm *) prepcblk->rpl_parmb; | ||
| 453 | |||
| 454 | /* check length of the returned secure key token */ | ||
| 455 | seckeysize = prepparm->lv3.keyblock.toklen | ||
| 456 | - sizeof(prepparm->lv3.keyblock.toklen) | ||
| 457 | - sizeof(prepparm->lv3.keyblock.tokattr); | ||
| 458 | if (seckeysize != SECKEYBLOBSIZE) { | ||
| 459 | DEBUG_ERR( | ||
| 460 | "pkey_clr2seckey secure token size mismatch %d != %d bytes\n", | ||
| 461 | seckeysize, SECKEYBLOBSIZE); | ||
| 462 | rc = -EIO; | ||
| 463 | goto out; | ||
| 464 | } | ||
| 465 | |||
| 466 | /* check secure key token */ | ||
| 467 | rc = check_secaeskeytoken(prepparm->lv3.keyblock.tok, 8*keysize); | ||
| 468 | if (rc) { | ||
| 469 | rc = -EIO; | ||
| 470 | goto out; | ||
| 471 | } | ||
| 472 | |||
| 473 | /* copy the generated secure key token */ | ||
| 474 | memcpy(seckey->seckey, prepparm->lv3.keyblock.tok, SECKEYBLOBSIZE); | ||
| 475 | |||
| 476 | out: | ||
| 477 | free_cprbmem(mem, PARMBSIZE, 1); | ||
| 478 | return rc; | ||
| 479 | } | ||
| 480 | EXPORT_SYMBOL(pkey_clr2seckey); | ||
| 481 | |||
| 482 | /* | ||
| 483 | * Derive a proteced key from the secure key blob. | ||
| 484 | */ | ||
| 485 | int pkey_sec2protkey(u16 cardnr, u16 domain, | ||
| 486 | const struct pkey_seckey *seckey, | ||
| 487 | struct pkey_protkey *protkey) | ||
| 488 | { | ||
| 489 | int rc; | ||
| 490 | u8 *mem; | ||
| 491 | struct CPRBX *preqcblk, *prepcblk; | ||
| 492 | struct ica_xcRB xcrb; | ||
| 493 | struct uskreqparm { | ||
| 494 | u8 subfunc_code[2]; | ||
| 495 | u16 rule_array_len; | ||
| 496 | struct lv1 { | ||
| 497 | u16 len; | ||
| 498 | u16 attr_len; | ||
| 499 | u16 attr_flags; | ||
| 500 | } lv1; | ||
| 501 | struct lv2 { | ||
| 502 | u16 len; | ||
| 503 | u16 attr_len; | ||
| 504 | u16 attr_flags; | ||
| 505 | u8 token[0]; /* cca secure key token */ | ||
| 506 | } lv2 __packed; | ||
| 507 | } *preqparm; | ||
| 508 | struct uskrepparm { | ||
| 509 | u8 subfunc_code[2]; | ||
| 510 | u16 rule_array_len; | ||
| 511 | struct lv3 { | ||
| 512 | u16 len; | ||
| 513 | u16 attr_len; | ||
| 514 | u16 attr_flags; | ||
| 515 | struct cpacfkeyblock { | ||
| 516 | u8 version; /* version of this struct */ | ||
| 517 | u8 flags[2]; | ||
| 518 | u8 algo; | ||
| 519 | u8 form; | ||
| 520 | u8 pad1[3]; | ||
| 521 | u16 keylen; | ||
| 522 | u8 key[64]; /* the key (keylen bytes) */ | ||
| 523 | u16 keyattrlen; | ||
| 524 | u8 keyattr[32]; | ||
| 525 | u8 pad2[1]; | ||
| 526 | u8 vptype; | ||
| 527 | u8 vp[32]; /* verification pattern */ | ||
| 528 | } keyblock; | ||
| 529 | } lv3 __packed; | ||
| 530 | } *prepparm; | ||
| 531 | |||
| 532 | /* get already prepared memory for 2 cprbs with param block each */ | ||
| 533 | rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk); | ||
| 534 | if (rc) | ||
| 535 | return rc; | ||
| 536 | |||
| 537 | /* fill request cprb struct */ | ||
| 538 | preqcblk->domain = domain; | ||
| 539 | |||
| 540 | /* fill request cprb param block with USK request */ | ||
| 541 | preqparm = (struct uskreqparm *) preqcblk->req_parmb; | ||
| 542 | memcpy(preqparm->subfunc_code, "US", 2); | ||
| 543 | preqparm->rule_array_len = sizeof(preqparm->rule_array_len); | ||
| 544 | preqparm->lv1.len = sizeof(struct lv1); | ||
| 545 | preqparm->lv1.attr_len = sizeof(struct lv1) - sizeof(preqparm->lv1.len); | ||
| 546 | preqparm->lv1.attr_flags = 0x0001; | ||
| 547 | preqparm->lv2.len = sizeof(struct lv2) + SECKEYBLOBSIZE; | ||
| 548 | preqparm->lv2.attr_len = sizeof(struct lv2) | ||
| 549 | - sizeof(preqparm->lv2.len) + SECKEYBLOBSIZE; | ||
| 550 | preqparm->lv2.attr_flags = 0x0000; | ||
| 551 | memcpy(preqparm->lv2.token, seckey->seckey, SECKEYBLOBSIZE); | ||
| 552 | preqcblk->req_parml = sizeof(struct uskreqparm) + SECKEYBLOBSIZE; | ||
| 553 | |||
| 554 | /* fill xcrb struct */ | ||
| 555 | prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk); | ||
| 556 | |||
| 557 | /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */ | ||
| 558 | rc = _zcrypt_send_cprb(&xcrb); | ||
| 559 | if (rc) { | ||
| 560 | DEBUG_ERR( | ||
| 561 | "pkey_sec2protkey zcrypt_send_cprb (cardnr=%d domain=%d) failed with errno %d\n", | ||
| 562 | (int) cardnr, (int) domain, rc); | ||
| 563 | goto out; | ||
| 564 | } | ||
| 565 | |||
| 566 | /* check response returncode and reasoncode */ | ||
| 567 | if (prepcblk->ccp_rtcode != 0) { | ||
| 568 | DEBUG_ERR( | ||
| 569 | "pkey_sec2protkey unwrap secure key failure, card response %d/%d\n", | ||
| 570 | (int) prepcblk->ccp_rtcode, | ||
| 571 | (int) prepcblk->ccp_rscode); | ||
| 572 | rc = -EIO; | ||
| 573 | goto out; | ||
| 574 | } | ||
| 575 | |||
| 576 | /* process response cprb param block */ | ||
| 577 | prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); | ||
| 578 | prepparm = (struct uskrepparm *) prepcblk->rpl_parmb; | ||
| 579 | |||
| 580 | /* check the returned keyblock */ | ||
| 581 | if (prepparm->lv3.keyblock.version != 0x01) { | ||
| 582 | DEBUG_ERR( | ||
| 583 | "pkey_sec2protkey reply param keyblock version mismatch 0x%02x != 0x01\n", | ||
| 584 | (int) prepparm->lv3.keyblock.version); | ||
| 585 | rc = -EIO; | ||
| 586 | goto out; | ||
| 587 | } | ||
| 588 | |||
| 589 | /* copy the tanslated protected key */ | ||
| 590 | switch (prepparm->lv3.keyblock.keylen) { | ||
| 591 | case 16+32: | ||
| 592 | protkey->type = PKEY_KEYTYPE_AES_128; | ||
| 593 | break; | ||
| 594 | case 24+32: | ||
| 595 | protkey->type = PKEY_KEYTYPE_AES_192; | ||
| 596 | break; | ||
| 597 | case 32+32: | ||
| 598 | protkey->type = PKEY_KEYTYPE_AES_256; | ||
| 599 | break; | ||
| 600 | default: | ||
| 601 | DEBUG_ERR("pkey_sec2protkey unknown/unsupported keytype %d\n", | ||
| 602 | prepparm->lv3.keyblock.keylen); | ||
| 603 | rc = -EIO; | ||
| 604 | goto out; | ||
| 605 | } | ||
| 606 | protkey->len = prepparm->lv3.keyblock.keylen; | ||
| 607 | memcpy(protkey->protkey, prepparm->lv3.keyblock.key, protkey->len); | ||
| 608 | |||
| 609 | out: | ||
| 610 | free_cprbmem(mem, PARMBSIZE, 0); | ||
| 611 | return rc; | ||
| 612 | } | ||
| 613 | EXPORT_SYMBOL(pkey_sec2protkey); | ||
| 614 | |||
| 615 | /* | ||
| 616 | * Create a protected key from a clear key value. | ||
| 617 | */ | ||
| 618 | int pkey_clr2protkey(u32 keytype, | ||
| 619 | const struct pkey_clrkey *clrkey, | ||
| 620 | struct pkey_protkey *protkey) | ||
| 621 | { | ||
| 622 | long fc; | ||
| 623 | int keysize; | ||
| 624 | u8 paramblock[64]; | ||
| 625 | |||
| 626 | switch (keytype) { | ||
| 627 | case PKEY_KEYTYPE_AES_128: | ||
| 628 | keysize = 16; | ||
| 629 | fc = CPACF_PCKMO_ENC_AES_128_KEY; | ||
| 630 | break; | ||
| 631 | case PKEY_KEYTYPE_AES_192: | ||
| 632 | keysize = 24; | ||
| 633 | fc = CPACF_PCKMO_ENC_AES_192_KEY; | ||
| 634 | break; | ||
| 635 | case PKEY_KEYTYPE_AES_256: | ||
| 636 | keysize = 32; | ||
| 637 | fc = CPACF_PCKMO_ENC_AES_256_KEY; | ||
| 638 | break; | ||
| 639 | default: | ||
| 640 | DEBUG_ERR("pkey_clr2protkey unknown/unsupported keytype %d\n", | ||
| 641 | keytype); | ||
| 642 | return -EINVAL; | ||
| 643 | } | ||
| 644 | |||
| 645 | /* prepare param block */ | ||
| 646 | memset(paramblock, 0, sizeof(paramblock)); | ||
| 647 | memcpy(paramblock, clrkey->clrkey, keysize); | ||
| 648 | |||
| 649 | /* call the pckmo instruction */ | ||
| 650 | cpacf_pckmo(fc, paramblock); | ||
| 651 | |||
| 652 | /* copy created protected key */ | ||
| 653 | protkey->type = keytype; | ||
| 654 | protkey->len = keysize + 32; | ||
| 655 | memcpy(protkey->protkey, paramblock, keysize + 32); | ||
| 656 | |||
| 657 | return 0; | ||
| 658 | } | ||
| 659 | EXPORT_SYMBOL(pkey_clr2protkey); | ||
| 660 | |||
| 661 | /* | ||
| 662 | * query cryptographic facility from adapter | ||
| 663 | */ | ||
| 664 | static int query_crypto_facility(u16 cardnr, u16 domain, | ||
| 665 | const char *keyword, | ||
| 666 | u8 *rarray, size_t *rarraylen, | ||
| 667 | u8 *varray, size_t *varraylen) | ||
| 668 | { | ||
| 669 | int rc; | ||
| 670 | u16 len; | ||
| 671 | u8 *mem, *ptr; | ||
| 672 | struct CPRBX *preqcblk, *prepcblk; | ||
| 673 | struct ica_xcRB xcrb; | ||
| 674 | struct fqreqparm { | ||
| 675 | u8 subfunc_code[2]; | ||
| 676 | u16 rule_array_len; | ||
| 677 | char rule_array[8]; | ||
| 678 | struct lv1 { | ||
| 679 | u16 len; | ||
| 680 | u8 data[VARDATASIZE]; | ||
| 681 | } lv1; | ||
| 682 | u16 dummylen; | ||
| 683 | } *preqparm; | ||
| 684 | size_t parmbsize = sizeof(struct fqreqparm); | ||
| 685 | struct fqrepparm { | ||
| 686 | u8 subfunc_code[2]; | ||
| 687 | u8 lvdata[0]; | ||
| 688 | } *prepparm; | ||
| 689 | |||
| 690 | /* get already prepared memory for 2 cprbs with param block each */ | ||
| 691 | rc = alloc_and_prep_cprbmem(parmbsize, &mem, &preqcblk, &prepcblk); | ||
| 692 | if (rc) | ||
| 693 | return rc; | ||
| 694 | |||
| 695 | /* fill request cprb struct */ | ||
| 696 | preqcblk->domain = domain; | ||
| 697 | |||
| 698 | /* fill request cprb param block with FQ request */ | ||
| 699 | preqparm = (struct fqreqparm *) preqcblk->req_parmb; | ||
| 700 | memcpy(preqparm->subfunc_code, "FQ", 2); | ||
| 701 | strncpy(preqparm->rule_array, keyword, sizeof(preqparm->rule_array)); | ||
| 702 | preqparm->rule_array_len = | ||
| 703 | sizeof(preqparm->rule_array_len) + sizeof(preqparm->rule_array); | ||
| 704 | preqparm->lv1.len = sizeof(preqparm->lv1); | ||
| 705 | preqparm->dummylen = sizeof(preqparm->dummylen); | ||
| 706 | preqcblk->req_parml = parmbsize; | ||
| 707 | |||
| 708 | /* fill xcrb struct */ | ||
| 709 | prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk); | ||
| 710 | |||
| 711 | /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */ | ||
| 712 | rc = _zcrypt_send_cprb(&xcrb); | ||
| 713 | if (rc) { | ||
| 714 | DEBUG_ERR( | ||
| 715 | "query_crypto_facility zcrypt_send_cprb (cardnr=%d domain=%d) failed with errno %d\n", | ||
| 716 | (int) cardnr, (int) domain, rc); | ||
| 717 | goto out; | ||
| 718 | } | ||
| 719 | |||
| 720 | /* check response returncode and reasoncode */ | ||
| 721 | if (prepcblk->ccp_rtcode != 0) { | ||
| 722 | DEBUG_ERR( | ||
| 723 | "query_crypto_facility unwrap secure key failure, card response %d/%d\n", | ||
| 724 | (int) prepcblk->ccp_rtcode, | ||
| 725 | (int) prepcblk->ccp_rscode); | ||
| 726 | rc = -EIO; | ||
| 727 | goto out; | ||
| 728 | } | ||
| 729 | |||
| 730 | /* process response cprb param block */ | ||
| 731 | prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); | ||
| 732 | prepparm = (struct fqrepparm *) prepcblk->rpl_parmb; | ||
| 733 | ptr = prepparm->lvdata; | ||
| 734 | |||
| 735 | /* check and possibly copy reply rule array */ | ||
| 736 | len = *((u16 *) ptr); | ||
| 737 | if (len > sizeof(u16)) { | ||
| 738 | ptr += sizeof(u16); | ||
| 739 | len -= sizeof(u16); | ||
| 740 | if (rarray && rarraylen && *rarraylen > 0) { | ||
| 741 | *rarraylen = (len > *rarraylen ? *rarraylen : len); | ||
| 742 | memcpy(rarray, ptr, *rarraylen); | ||
| 743 | } | ||
| 744 | ptr += len; | ||
| 745 | } | ||
| 746 | /* check and possible copy reply var array */ | ||
| 747 | len = *((u16 *) ptr); | ||
| 748 | if (len > sizeof(u16)) { | ||
| 749 | ptr += sizeof(u16); | ||
| 750 | len -= sizeof(u16); | ||
| 751 | if (varray && varraylen && *varraylen > 0) { | ||
| 752 | *varraylen = (len > *varraylen ? *varraylen : len); | ||
| 753 | memcpy(varray, ptr, *varraylen); | ||
| 754 | } | ||
| 755 | ptr += len; | ||
| 756 | } | ||
| 757 | |||
| 758 | out: | ||
| 759 | free_cprbmem(mem, parmbsize, 0); | ||
| 760 | return rc; | ||
| 761 | } | ||
| 762 | |||
| 763 | /* | ||
| 764 | * Fetch just the mkvp value via query_crypto_facility from adapter. | ||
| 765 | */ | ||
| 766 | static int fetch_mkvp(u16 cardnr, u16 domain, u64 *mkvp) | ||
| 767 | { | ||
| 768 | int rc, found = 0; | ||
| 769 | size_t rlen, vlen; | ||
| 770 | u8 *rarray, *varray, *pg; | ||
| 771 | |||
| 772 | pg = (u8 *) __get_free_page(GFP_KERNEL); | ||
| 773 | if (!pg) | ||
| 774 | return -ENOMEM; | ||
| 775 | rarray = pg; | ||
| 776 | varray = pg + PAGE_SIZE/2; | ||
| 777 | rlen = vlen = PAGE_SIZE/2; | ||
| 778 | |||
| 779 | rc = query_crypto_facility(cardnr, domain, "STATICSA", | ||
| 780 | rarray, &rlen, varray, &vlen); | ||
| 781 | if (rc == 0 && rlen > 8*8 && vlen > 184+8) { | ||
| 782 | if (rarray[64] == '2') { | ||
| 783 | /* current master key state is valid */ | ||
| 784 | *mkvp = *((u64 *)(varray + 184)); | ||
| 785 | found = 1; | ||
| 786 | } | ||
| 787 | } | ||
| 788 | |||
| 789 | free_page((unsigned long) pg); | ||
| 790 | |||
| 791 | return found ? 0 : -ENOENT; | ||
| 792 | } | ||
| 793 | |||
| 794 | /* struct to hold cached mkvp info for each card/domain */ | ||
| 795 | struct mkvp_info { | ||
| 796 | struct list_head list; | ||
| 797 | u16 cardnr; | ||
| 798 | u16 domain; | ||
| 799 | u64 mkvp; | ||
| 800 | }; | ||
| 801 | |||
| 802 | /* a list with mkvp_info entries */ | ||
| 803 | static LIST_HEAD(mkvp_list); | ||
| 804 | static DEFINE_SPINLOCK(mkvp_list_lock); | ||
| 805 | |||
| 806 | static int mkvp_cache_fetch(u16 cardnr, u16 domain, u64 *mkvp) | ||
| 807 | { | ||
| 808 | int rc = -ENOENT; | ||
| 809 | struct mkvp_info *ptr; | ||
| 810 | |||
| 811 | spin_lock_bh(&mkvp_list_lock); | ||
| 812 | list_for_each_entry(ptr, &mkvp_list, list) { | ||
| 813 | if (ptr->cardnr == cardnr && | ||
| 814 | ptr->domain == domain) { | ||
| 815 | *mkvp = ptr->mkvp; | ||
| 816 | rc = 0; | ||
| 817 | break; | ||
| 818 | } | ||
| 819 | } | ||
| 820 | spin_unlock_bh(&mkvp_list_lock); | ||
| 821 | |||
| 822 | return rc; | ||
| 823 | } | ||
| 824 | |||
| 825 | static void mkvp_cache_update(u16 cardnr, u16 domain, u64 mkvp) | ||
| 826 | { | ||
| 827 | int found = 0; | ||
| 828 | struct mkvp_info *ptr; | ||
| 829 | |||
| 830 | spin_lock_bh(&mkvp_list_lock); | ||
| 831 | list_for_each_entry(ptr, &mkvp_list, list) { | ||
| 832 | if (ptr->cardnr == cardnr && | ||
| 833 | ptr->domain == domain) { | ||
| 834 | ptr->mkvp = mkvp; | ||
| 835 | found = 1; | ||
| 836 | break; | ||
| 837 | } | ||
| 838 | } | ||
| 839 | if (!found) { | ||
| 840 | ptr = kmalloc(sizeof(*ptr), GFP_ATOMIC); | ||
| 841 | if (!ptr) { | ||
| 842 | spin_unlock_bh(&mkvp_list_lock); | ||
| 843 | return; | ||
| 844 | } | ||
| 845 | ptr->cardnr = cardnr; | ||
| 846 | ptr->domain = domain; | ||
| 847 | ptr->mkvp = mkvp; | ||
| 848 | list_add(&ptr->list, &mkvp_list); | ||
| 849 | } | ||
| 850 | spin_unlock_bh(&mkvp_list_lock); | ||
| 851 | } | ||
| 852 | |||
| 853 | static void mkvp_cache_scrub(u16 cardnr, u16 domain) | ||
| 854 | { | ||
| 855 | struct mkvp_info *ptr; | ||
| 856 | |||
| 857 | spin_lock_bh(&mkvp_list_lock); | ||
| 858 | list_for_each_entry(ptr, &mkvp_list, list) { | ||
| 859 | if (ptr->cardnr == cardnr && | ||
| 860 | ptr->domain == domain) { | ||
| 861 | list_del(&ptr->list); | ||
| 862 | kfree(ptr); | ||
| 863 | break; | ||
| 864 | } | ||
| 865 | } | ||
| 866 | spin_unlock_bh(&mkvp_list_lock); | ||
| 867 | } | ||
| 868 | |||
| 869 | static void __exit mkvp_cache_free(void) | ||
| 870 | { | ||
| 871 | struct mkvp_info *ptr, *pnext; | ||
| 872 | |||
| 873 | spin_lock_bh(&mkvp_list_lock); | ||
| 874 | list_for_each_entry_safe(ptr, pnext, &mkvp_list, list) { | ||
| 875 | list_del(&ptr->list); | ||
| 876 | kfree(ptr); | ||
| 877 | } | ||
| 878 | spin_unlock_bh(&mkvp_list_lock); | ||
| 879 | } | ||
| 880 | |||
| 881 | /* | ||
| 882 | * Search for a matching crypto card based on the Master Key | ||
| 883 | * Verification Pattern provided inside a secure key. | ||
| 884 | */ | ||
| 885 | int pkey_findcard(const struct pkey_seckey *seckey, | ||
| 886 | u16 *pcardnr, u16 *pdomain, int verify) | ||
| 887 | { | ||
| 888 | struct secaeskeytoken *t = (struct secaeskeytoken *) seckey; | ||
| 889 | struct zcrypt_device_matrix *device_matrix; | ||
| 890 | u16 card, dom; | ||
| 891 | u64 mkvp; | ||
| 892 | int i, rc; | ||
| 893 | |||
| 894 | /* mkvp must not be zero */ | ||
| 895 | if (t->mkvp == 0) | ||
| 896 | return -EINVAL; | ||
| 897 | |||
| 898 | /* fetch status of all crypto cards */ | ||
| 899 | device_matrix = kmalloc(sizeof(struct zcrypt_device_matrix), | ||
| 900 | GFP_KERNEL); | ||
| 901 | if (!device_matrix) | ||
| 902 | return -ENOMEM; | ||
| 903 | zcrypt_device_status_mask(device_matrix); | ||
| 904 | |||
| 905 | /* walk through all crypto cards */ | ||
| 906 | for (i = 0; i < MAX_ZDEV_ENTRIES; i++) { | ||
| 907 | card = AP_QID_CARD(device_matrix->device[i].qid); | ||
| 908 | dom = AP_QID_QUEUE(device_matrix->device[i].qid); | ||
| 909 | if (device_matrix->device[i].online && | ||
| 910 | device_matrix->device[i].functions & 0x04) { | ||
| 911 | /* an enabled CCA Coprocessor card */ | ||
| 912 | /* try cached mkvp */ | ||
| 913 | if (mkvp_cache_fetch(card, dom, &mkvp) == 0 && | ||
| 914 | t->mkvp == mkvp) { | ||
| 915 | if (!verify) | ||
| 916 | break; | ||
| 917 | /* verify: fetch mkvp from adapter */ | ||
| 918 | if (fetch_mkvp(card, dom, &mkvp) == 0) { | ||
| 919 | mkvp_cache_update(card, dom, mkvp); | ||
| 920 | if (t->mkvp == mkvp) | ||
| 921 | break; | ||
| 922 | } | ||
| 923 | } | ||
| 924 | } else { | ||
| 925 | /* Card is offline and/or not a CCA card. */ | ||
| 926 | /* del mkvp entry from cache if it exists */ | ||
| 927 | mkvp_cache_scrub(card, dom); | ||
| 928 | } | ||
| 929 | } | ||
| 930 | if (i >= MAX_ZDEV_ENTRIES) { | ||
| 931 | /* nothing found, so this time without cache */ | ||
| 932 | for (i = 0; i < MAX_ZDEV_ENTRIES; i++) { | ||
| 933 | if (!(device_matrix->device[i].online && | ||
| 934 | device_matrix->device[i].functions & 0x04)) | ||
| 935 | continue; | ||
| 936 | card = AP_QID_CARD(device_matrix->device[i].qid); | ||
| 937 | dom = AP_QID_QUEUE(device_matrix->device[i].qid); | ||
| 938 | /* fresh fetch mkvp from adapter */ | ||
| 939 | if (fetch_mkvp(card, dom, &mkvp) == 0) { | ||
| 940 | mkvp_cache_update(card, dom, mkvp); | ||
| 941 | if (t->mkvp == mkvp) | ||
| 942 | break; | ||
| 943 | } | ||
| 944 | } | ||
| 945 | } | ||
| 946 | if (i < MAX_ZDEV_ENTRIES) { | ||
| 947 | if (pcardnr) | ||
| 948 | *pcardnr = card; | ||
| 949 | if (pdomain) | ||
| 950 | *pdomain = dom; | ||
| 951 | rc = 0; | ||
| 952 | } else | ||
| 953 | rc = -ENODEV; | ||
| 954 | |||
| 955 | kfree(device_matrix); | ||
| 956 | return rc; | ||
| 957 | } | ||
| 958 | EXPORT_SYMBOL(pkey_findcard); | ||
| 959 | |||
| 960 | /* | ||
| 961 | * Find card and transform secure key into protected key. | ||
| 962 | */ | ||
| 963 | int pkey_skey2pkey(const struct pkey_seckey *seckey, | ||
| 964 | struct pkey_protkey *protkey) | ||
| 965 | { | ||
| 966 | u16 cardnr, domain; | ||
| 967 | int rc, verify; | ||
| 968 | |||
| 969 | /* | ||
| 970 | * The pkey_sec2protkey call may fail when a card has been | ||
| 971 | * addressed where the master key was changed after last fetch | ||
| 972 | * of the mkvp into the cache. So first try without verify then | ||
| 973 | * with verify enabled (thus refreshing the mkvp for each card). | ||
| 974 | */ | ||
| 975 | for (verify = 0; verify < 2; verify++) { | ||
| 976 | rc = pkey_findcard(seckey, &cardnr, &domain, verify); | ||
| 977 | if (rc) | ||
| 978 | continue; | ||
| 979 | rc = pkey_sec2protkey(cardnr, domain, seckey, protkey); | ||
| 980 | if (rc == 0) | ||
| 981 | break; | ||
| 982 | } | ||
| 983 | |||
| 984 | if (rc) | ||
| 985 | DEBUG_DBG("pkey_skey2pkey failed rc=%d\n", rc); | ||
| 986 | |||
| 987 | return rc; | ||
| 988 | } | ||
| 989 | EXPORT_SYMBOL(pkey_skey2pkey); | ||
| 990 | |||
| 991 | /* | ||
| 992 | * File io functions | ||
| 993 | */ | ||
| 994 | |||
| 995 | static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, | ||
| 996 | unsigned long arg) | ||
| 997 | { | ||
| 998 | int rc; | ||
| 999 | |||
| 1000 | switch (cmd) { | ||
| 1001 | case PKEY_GENSECK: { | ||
| 1002 | struct pkey_genseck __user *ugs = (void __user *) arg; | ||
| 1003 | struct pkey_genseck kgs; | ||
| 1004 | |||
| 1005 | if (copy_from_user(&kgs, ugs, sizeof(kgs))) | ||
| 1006 | return -EFAULT; | ||
| 1007 | rc = pkey_genseckey(kgs.cardnr, kgs.domain, | ||
| 1008 | kgs.keytype, &kgs.seckey); | ||
| 1009 | DEBUG_DBG("pkey_ioctl pkey_genseckey()=%d\n", rc); | ||
| 1010 | if (rc) | ||
| 1011 | break; | ||
| 1012 | if (copy_to_user(ugs, &kgs, sizeof(kgs))) | ||
| 1013 | return -EFAULT; | ||
| 1014 | break; | ||
| 1015 | } | ||
| 1016 | case PKEY_CLR2SECK: { | ||
| 1017 | struct pkey_clr2seck __user *ucs = (void __user *) arg; | ||
| 1018 | struct pkey_clr2seck kcs; | ||
| 1019 | |||
| 1020 | if (copy_from_user(&kcs, ucs, sizeof(kcs))) | ||
| 1021 | return -EFAULT; | ||
| 1022 | rc = pkey_clr2seckey(kcs.cardnr, kcs.domain, kcs.keytype, | ||
| 1023 | &kcs.clrkey, &kcs.seckey); | ||
| 1024 | DEBUG_DBG("pkey_ioctl pkey_clr2seckey()=%d\n", rc); | ||
| 1025 | if (rc) | ||
| 1026 | break; | ||
| 1027 | if (copy_to_user(ucs, &kcs, sizeof(kcs))) | ||
| 1028 | return -EFAULT; | ||
| 1029 | memzero_explicit(&kcs, sizeof(kcs)); | ||
| 1030 | break; | ||
| 1031 | } | ||
| 1032 | case PKEY_SEC2PROTK: { | ||
| 1033 | struct pkey_sec2protk __user *usp = (void __user *) arg; | ||
| 1034 | struct pkey_sec2protk ksp; | ||
| 1035 | |||
| 1036 | if (copy_from_user(&ksp, usp, sizeof(ksp))) | ||
| 1037 | return -EFAULT; | ||
| 1038 | rc = pkey_sec2protkey(ksp.cardnr, ksp.domain, | ||
| 1039 | &ksp.seckey, &ksp.protkey); | ||
| 1040 | DEBUG_DBG("pkey_ioctl pkey_sec2protkey()=%d\n", rc); | ||
| 1041 | if (rc) | ||
| 1042 | break; | ||
| 1043 | if (copy_to_user(usp, &ksp, sizeof(ksp))) | ||
| 1044 | return -EFAULT; | ||
| 1045 | break; | ||
| 1046 | } | ||
| 1047 | case PKEY_CLR2PROTK: { | ||
| 1048 | struct pkey_clr2protk __user *ucp = (void __user *) arg; | ||
| 1049 | struct pkey_clr2protk kcp; | ||
| 1050 | |||
| 1051 | if (copy_from_user(&kcp, ucp, sizeof(kcp))) | ||
| 1052 | return -EFAULT; | ||
| 1053 | rc = pkey_clr2protkey(kcp.keytype, | ||
| 1054 | &kcp.clrkey, &kcp.protkey); | ||
| 1055 | DEBUG_DBG("pkey_ioctl pkey_clr2protkey()=%d\n", rc); | ||
| 1056 | if (rc) | ||
| 1057 | break; | ||
| 1058 | if (copy_to_user(ucp, &kcp, sizeof(kcp))) | ||
| 1059 | return -EFAULT; | ||
| 1060 | memzero_explicit(&kcp, sizeof(kcp)); | ||
| 1061 | break; | ||
| 1062 | } | ||
| 1063 | case PKEY_FINDCARD: { | ||
| 1064 | struct pkey_findcard __user *ufc = (void __user *) arg; | ||
| 1065 | struct pkey_findcard kfc; | ||
| 1066 | |||
| 1067 | if (copy_from_user(&kfc, ufc, sizeof(kfc))) | ||
| 1068 | return -EFAULT; | ||
| 1069 | rc = pkey_findcard(&kfc.seckey, | ||
| 1070 | &kfc.cardnr, &kfc.domain, 1); | ||
| 1071 | DEBUG_DBG("pkey_ioctl pkey_findcard()=%d\n", rc); | ||
| 1072 | if (rc) | ||
| 1073 | break; | ||
| 1074 | if (copy_to_user(ufc, &kfc, sizeof(kfc))) | ||
| 1075 | return -EFAULT; | ||
| 1076 | break; | ||
| 1077 | } | ||
| 1078 | case PKEY_SKEY2PKEY: { | ||
| 1079 | struct pkey_skey2pkey __user *usp = (void __user *) arg; | ||
| 1080 | struct pkey_skey2pkey ksp; | ||
| 1081 | |||
| 1082 | if (copy_from_user(&ksp, usp, sizeof(ksp))) | ||
| 1083 | return -EFAULT; | ||
| 1084 | rc = pkey_skey2pkey(&ksp.seckey, &ksp.protkey); | ||
| 1085 | DEBUG_DBG("pkey_ioctl pkey_skey2pkey()=%d\n", rc); | ||
| 1086 | if (rc) | ||
| 1087 | break; | ||
| 1088 | if (copy_to_user(usp, &ksp, sizeof(ksp))) | ||
| 1089 | return -EFAULT; | ||
| 1090 | break; | ||
| 1091 | } | ||
| 1092 | default: | ||
| 1093 | /* unknown/unsupported ioctl cmd */ | ||
| 1094 | return -ENOTTY; | ||
| 1095 | } | ||
| 1096 | |||
| 1097 | return rc; | ||
| 1098 | } | ||
| 1099 | |||
| 1100 | /* | ||
| 1101 | * Sysfs and file io operations | ||
| 1102 | */ | ||
| 1103 | static const struct file_operations pkey_fops = { | ||
| 1104 | .owner = THIS_MODULE, | ||
| 1105 | .open = nonseekable_open, | ||
| 1106 | .llseek = no_llseek, | ||
| 1107 | .unlocked_ioctl = pkey_unlocked_ioctl, | ||
| 1108 | }; | ||
| 1109 | |||
| 1110 | static struct miscdevice pkey_dev = { | ||
| 1111 | .name = "pkey", | ||
| 1112 | .minor = MISC_DYNAMIC_MINOR, | ||
| 1113 | .mode = 0666, | ||
| 1114 | .fops = &pkey_fops, | ||
| 1115 | }; | ||
| 1116 | |||
| 1117 | /* | ||
| 1118 | * Module init | ||
| 1119 | */ | ||
| 1120 | int __init pkey_init(void) | ||
| 1121 | { | ||
| 1122 | cpacf_mask_t pckmo_functions; | ||
| 1123 | |||
| 1124 | /* check for pckmo instructions available */ | ||
| 1125 | if (!cpacf_query(CPACF_PCKMO, &pckmo_functions)) | ||
| 1126 | return -EOPNOTSUPP; | ||
| 1127 | if (!cpacf_test_func(&pckmo_functions, CPACF_PCKMO_ENC_AES_128_KEY) || | ||
| 1128 | !cpacf_test_func(&pckmo_functions, CPACF_PCKMO_ENC_AES_192_KEY) || | ||
| 1129 | !cpacf_test_func(&pckmo_functions, CPACF_PCKMO_ENC_AES_256_KEY)) | ||
| 1130 | return -EOPNOTSUPP; | ||
| 1131 | |||
| 1132 | pkey_debug_init(); | ||
| 1133 | |||
| 1134 | return misc_register(&pkey_dev); | ||
| 1135 | } | ||
| 1136 | |||
| 1137 | /* | ||
| 1138 | * Module exit | ||
| 1139 | */ | ||
| 1140 | static void __exit pkey_exit(void) | ||
| 1141 | { | ||
| 1142 | misc_deregister(&pkey_dev); | ||
| 1143 | mkvp_cache_free(); | ||
| 1144 | pkey_debug_exit(); | ||
| 1145 | } | ||
| 1146 | |||
| 1147 | module_init(pkey_init); | ||
| 1148 | module_exit(pkey_exit); | ||
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index 144a17941e6f..93015f85d4a6 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c | |||
| @@ -374,7 +374,7 @@ out: | |||
| 374 | return rc; | 374 | return rc; |
| 375 | } | 375 | } |
| 376 | 376 | ||
| 377 | static long zcrypt_send_cprb(struct ica_xcRB *xcRB) | 377 | long zcrypt_send_cprb(struct ica_xcRB *xcRB) |
| 378 | { | 378 | { |
| 379 | struct zcrypt_card *zc, *pref_zc; | 379 | struct zcrypt_card *zc, *pref_zc; |
| 380 | struct zcrypt_queue *zq, *pref_zq; | 380 | struct zcrypt_queue *zq, *pref_zq; |
| @@ -444,6 +444,7 @@ out: | |||
| 444 | AP_QID_CARD(qid), AP_QID_QUEUE(qid)); | 444 | AP_QID_CARD(qid), AP_QID_QUEUE(qid)); |
| 445 | return rc; | 445 | return rc; |
| 446 | } | 446 | } |
| 447 | EXPORT_SYMBOL(zcrypt_send_cprb); | ||
| 447 | 448 | ||
| 448 | static bool is_desired_ep11_card(unsigned int dev_id, | 449 | static bool is_desired_ep11_card(unsigned int dev_id, |
| 449 | unsigned short target_num, | 450 | unsigned short target_num, |
| @@ -619,7 +620,7 @@ out: | |||
| 619 | return rc; | 620 | return rc; |
| 620 | } | 621 | } |
| 621 | 622 | ||
| 622 | static void zcrypt_device_status_mask(struct zcrypt_device_matrix *matrix) | 623 | void zcrypt_device_status_mask(struct zcrypt_device_matrix *matrix) |
| 623 | { | 624 | { |
| 624 | struct zcrypt_card *zc; | 625 | struct zcrypt_card *zc; |
| 625 | struct zcrypt_queue *zq; | 626 | struct zcrypt_queue *zq; |
diff --git a/drivers/s390/crypto/zcrypt_api.h b/drivers/s390/crypto/zcrypt_api.h index 274a59051534..6c94efd23eac 100644 --- a/drivers/s390/crypto/zcrypt_api.h +++ b/drivers/s390/crypto/zcrypt_api.h | |||
| @@ -190,5 +190,7 @@ void zcrypt_msgtype_unregister(struct zcrypt_ops *); | |||
| 190 | struct zcrypt_ops *zcrypt_msgtype(unsigned char *, int); | 190 | struct zcrypt_ops *zcrypt_msgtype(unsigned char *, int); |
| 191 | int zcrypt_api_init(void); | 191 | int zcrypt_api_init(void); |
| 192 | void zcrypt_api_exit(void); | 192 | void zcrypt_api_exit(void); |
| 193 | long zcrypt_send_cprb(struct ica_xcRB *xcRB); | ||
| 194 | void zcrypt_device_status_mask(struct zcrypt_device_matrix *devstatus); | ||
| 193 | 195 | ||
| 194 | #endif /* _ZCRYPT_API_H_ */ | 196 | #endif /* _ZCRYPT_API_H_ */ |
