diff options
| author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-02-18 11:09:40 -0500 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-02-18 11:09:40 -0500 |
| commit | ba4b60e85d6c5fc2242fd24e131a47fb922e5d89 (patch) | |
| tree | 6be918ce3924d0677bc1029f7d1255fef48a8f85 /arch/s390/crypto/des_s390.c | |
| parent | 5dba4c56dfa660a85dc8e897990948cdec3734bf (diff) | |
| parent | 6d0abeca3242a88cab8232e4acd7e2bf088f3bc2 (diff) | |
Merge 3.14-rc3 into char-misc-next
We need the fixes here for future mei and other patches.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'arch/s390/crypto/des_s390.c')
| -rw-r--r-- | arch/s390/crypto/des_s390.c | 95 |
1 files changed, 62 insertions, 33 deletions
diff --git a/arch/s390/crypto/des_s390.c b/arch/s390/crypto/des_s390.c index 200f2a1b599d..0a5aac8a9412 100644 --- a/arch/s390/crypto/des_s390.c +++ b/arch/s390/crypto/des_s390.c | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | #define DES3_KEY_SIZE (3 * DES_KEY_SIZE) | 25 | #define DES3_KEY_SIZE (3 * DES_KEY_SIZE) |
| 26 | 26 | ||
| 27 | static u8 *ctrblk; | 27 | static u8 *ctrblk; |
| 28 | static DEFINE_SPINLOCK(ctrblk_lock); | ||
| 28 | 29 | ||
| 29 | struct s390_des_ctx { | 30 | struct s390_des_ctx { |
| 30 | u8 iv[DES_BLOCK_SIZE]; | 31 | u8 iv[DES_BLOCK_SIZE]; |
| @@ -105,29 +106,35 @@ static int ecb_desall_crypt(struct blkcipher_desc *desc, long func, | |||
| 105 | } | 106 | } |
| 106 | 107 | ||
| 107 | static int cbc_desall_crypt(struct blkcipher_desc *desc, long func, | 108 | static int cbc_desall_crypt(struct blkcipher_desc *desc, long func, |
| 108 | u8 *iv, struct blkcipher_walk *walk) | 109 | struct blkcipher_walk *walk) |
| 109 | { | 110 | { |
| 111 | struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); | ||
| 110 | int ret = blkcipher_walk_virt(desc, walk); | 112 | int ret = blkcipher_walk_virt(desc, walk); |
| 111 | unsigned int nbytes = walk->nbytes; | 113 | unsigned int nbytes = walk->nbytes; |
| 114 | struct { | ||
| 115 | u8 iv[DES_BLOCK_SIZE]; | ||
| 116 | u8 key[DES3_KEY_SIZE]; | ||
| 117 | } param; | ||
| 112 | 118 | ||
| 113 | if (!nbytes) | 119 | if (!nbytes) |
| 114 | goto out; | 120 | goto out; |
| 115 | 121 | ||
| 116 | memcpy(iv, walk->iv, DES_BLOCK_SIZE); | 122 | memcpy(param.iv, walk->iv, DES_BLOCK_SIZE); |
| 123 | memcpy(param.key, ctx->key, DES3_KEY_SIZE); | ||
| 117 | do { | 124 | do { |
| 118 | /* only use complete blocks */ | 125 | /* only use complete blocks */ |
| 119 | unsigned int n = nbytes & ~(DES_BLOCK_SIZE - 1); | 126 | unsigned int n = nbytes & ~(DES_BLOCK_SIZE - 1); |
| 120 | u8 *out = walk->dst.virt.addr; | 127 | u8 *out = walk->dst.virt.addr; |
| 121 | u8 *in = walk->src.virt.addr; | 128 | u8 *in = walk->src.virt.addr; |
| 122 | 129 | ||
| 123 | ret = crypt_s390_kmc(func, iv, out, in, n); | 130 | ret = crypt_s390_kmc(func, ¶m, out, in, n); |
| 124 | if (ret < 0 || ret != n) | 131 | if (ret < 0 || ret != n) |
| 125 | return -EIO; | 132 | return -EIO; |
| 126 | 133 | ||
| 127 | nbytes &= DES_BLOCK_SIZE - 1; | 134 | nbytes &= DES_BLOCK_SIZE - 1; |
| 128 | ret = blkcipher_walk_done(desc, walk, nbytes); | 135 | ret = blkcipher_walk_done(desc, walk, nbytes); |
| 129 | } while ((nbytes = walk->nbytes)); | 136 | } while ((nbytes = walk->nbytes)); |
| 130 | memcpy(walk->iv, iv, DES_BLOCK_SIZE); | 137 | memcpy(walk->iv, param.iv, DES_BLOCK_SIZE); |
| 131 | 138 | ||
| 132 | out: | 139 | out: |
| 133 | return ret; | 140 | return ret; |
| @@ -179,22 +186,20 @@ static int cbc_des_encrypt(struct blkcipher_desc *desc, | |||
| 179 | struct scatterlist *dst, struct scatterlist *src, | 186 | struct scatterlist *dst, struct scatterlist *src, |
| 180 | unsigned int nbytes) | 187 | unsigned int nbytes) |
| 181 | { | 188 | { |
| 182 | struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); | ||
| 183 | struct blkcipher_walk walk; | 189 | struct blkcipher_walk walk; |
| 184 | 190 | ||
| 185 | blkcipher_walk_init(&walk, dst, src, nbytes); | 191 | blkcipher_walk_init(&walk, dst, src, nbytes); |
| 186 | return cbc_desall_crypt(desc, KMC_DEA_ENCRYPT, ctx->iv, &walk); | 192 | return cbc_desall_crypt(desc, KMC_DEA_ENCRYPT, &walk); |
| 187 | } | 193 | } |
| 188 | 194 | ||
| 189 | static int cbc_des_decrypt(struct blkcipher_desc *desc, | 195 | static int cbc_des_decrypt(struct blkcipher_desc *desc, |
| 190 | struct scatterlist *dst, struct scatterlist *src, | 196 | struct scatterlist *dst, struct scatterlist *src, |
| 191 | unsigned int nbytes) | 197 | unsigned int nbytes) |
| 192 | { | 198 | { |
| 193 | struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); | ||
| 194 | struct blkcipher_walk walk; | 199 | struct blkcipher_walk walk; |
| 195 | 200 | ||
| 196 | blkcipher_walk_init(&walk, dst, src, nbytes); | 201 | blkcipher_walk_init(&walk, dst, src, nbytes); |
| 197 | return cbc_desall_crypt(desc, KMC_DEA_DECRYPT, ctx->iv, &walk); | 202 | return cbc_desall_crypt(desc, KMC_DEA_DECRYPT, &walk); |
| 198 | } | 203 | } |
| 199 | 204 | ||
| 200 | static struct crypto_alg cbc_des_alg = { | 205 | static struct crypto_alg cbc_des_alg = { |
| @@ -327,22 +332,20 @@ static int cbc_des3_encrypt(struct blkcipher_desc *desc, | |||
| 327 | struct scatterlist *dst, struct scatterlist *src, | 332 | struct scatterlist *dst, struct scatterlist *src, |
| 328 | unsigned int nbytes) | 333 | unsigned int nbytes) |
| 329 | { | 334 | { |
| 330 | struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); | ||
| 331 | struct blkcipher_walk walk; | 335 | struct blkcipher_walk walk; |
| 332 | 336 | ||
| 333 | blkcipher_walk_init(&walk, dst, src, nbytes); | 337 | blkcipher_walk_init(&walk, dst, src, nbytes); |
| 334 | return cbc_desall_crypt(desc, KMC_TDEA_192_ENCRYPT, ctx->iv, &walk); | 338 | return cbc_desall_crypt(desc, KMC_TDEA_192_ENCRYPT, &walk); |
| 335 | } | 339 | } |
| 336 | 340 | ||
| 337 | static int cbc_des3_decrypt(struct blkcipher_desc *desc, | 341 | static int cbc_des3_decrypt(struct blkcipher_desc *desc, |
| 338 | struct scatterlist *dst, struct scatterlist *src, | 342 | struct scatterlist *dst, struct scatterlist *src, |
| 339 | unsigned int nbytes) | 343 | unsigned int nbytes) |
| 340 | { | 344 | { |
| 341 | struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); | ||
| 342 | struct blkcipher_walk walk; | 345 | struct blkcipher_walk walk; |
| 343 | 346 | ||
| 344 | blkcipher_walk_init(&walk, dst, src, nbytes); | 347 | blkcipher_walk_init(&walk, dst, src, nbytes); |
| 345 | return cbc_desall_crypt(desc, KMC_TDEA_192_DECRYPT, ctx->iv, &walk); | 348 | return cbc_desall_crypt(desc, KMC_TDEA_192_DECRYPT, &walk); |
| 346 | } | 349 | } |
| 347 | 350 | ||
| 348 | static struct crypto_alg cbc_des3_alg = { | 351 | static struct crypto_alg cbc_des3_alg = { |
| @@ -366,54 +369,80 @@ static struct crypto_alg cbc_des3_alg = { | |||
| 366 | } | 369 | } |
| 367 | }; | 370 | }; |
| 368 | 371 | ||
| 372 | static unsigned int __ctrblk_init(u8 *ctrptr, unsigned int nbytes) | ||
| 373 | { | ||
| 374 | unsigned int i, n; | ||
| 375 | |||
| 376 | /* align to block size, max. PAGE_SIZE */ | ||
| 377 | n = (nbytes > PAGE_SIZE) ? PAGE_SIZE : nbytes & ~(DES_BLOCK_SIZE - 1); | ||
| 378 | for (i = DES_BLOCK_SIZE; i < n; i += DES_BLOCK_SIZE) { | ||
| 379 | memcpy(ctrptr + i, ctrptr + i - DES_BLOCK_SIZE, DES_BLOCK_SIZE); | ||
| 380 | crypto_inc(ctrptr + i, DES_BLOCK_SIZE); | ||
| 381 | } | ||
| 382 | return n; | ||
| 383 | } | ||
| 384 | |||
| 369 | static int ctr_desall_crypt(struct blkcipher_desc *desc, long func, | 385 | static int ctr_desall_crypt(struct blkcipher_desc *desc, long func, |
| 370 | struct s390_des_ctx *ctx, struct blkcipher_walk *walk) | 386 | struct s390_des_ctx *ctx, |
| 387 | struct blkcipher_walk *walk) | ||
| 371 | { | 388 | { |
| 372 | int ret = blkcipher_walk_virt_block(desc, walk, DES_BLOCK_SIZE); | 389 | int ret = blkcipher_walk_virt_block(desc, walk, DES_BLOCK_SIZE); |
| 373 | unsigned int i, n, nbytes; | 390 | unsigned int n, nbytes; |
| 374 | u8 buf[DES_BLOCK_SIZE]; | 391 | u8 buf[DES_BLOCK_SIZE], ctrbuf[DES_BLOCK_SIZE]; |
| 375 | u8 *out, *in; | 392 | u8 *out, *in, *ctrptr = ctrbuf; |
| 393 | |||
| 394 | if (!walk->nbytes) | ||
| 395 | return ret; | ||
| 376 | 396 | ||
| 377 | memcpy(ctrblk, walk->iv, DES_BLOCK_SIZE); | 397 | if (spin_trylock(&ctrblk_lock)) |
| 398 | ctrptr = ctrblk; | ||
| 399 | |||
| 400 | memcpy(ctrptr, walk->iv, DES_BLOCK_SIZE); | ||
| 378 | while ((nbytes = walk->nbytes) >= DES_BLOCK_SIZE) { | 401 | while ((nbytes = walk->nbytes) >= DES_BLOCK_SIZE) { |
| 379 | out = walk->dst.virt.addr; | 402 | out = walk->dst.virt.addr; |
| 380 | in = walk->src.virt.addr; | 403 | in = walk->src.virt.addr; |
| 381 | while (nbytes >= DES_BLOCK_SIZE) { | 404 | while (nbytes >= DES_BLOCK_SIZE) { |
| 382 | /* align to block size, max. PAGE_SIZE */ | 405 | if (ctrptr == ctrblk) |
| 383 | n = (nbytes > PAGE_SIZE) ? PAGE_SIZE : | 406 | n = __ctrblk_init(ctrptr, nbytes); |
| 384 | nbytes & ~(DES_BLOCK_SIZE - 1); | 407 | else |
| 385 | for (i = DES_BLOCK_SIZE; i < n; i += DES_BLOCK_SIZE) { | 408 | n = DES_BLOCK_SIZE; |
| 386 | memcpy(ctrblk + i, ctrblk + i - DES_BLOCK_SIZE, | 409 | ret = crypt_s390_kmctr(func, ctx->key, out, in, |
| 387 | DES_BLOCK_SIZE); | 410 | n, ctrptr); |
| 388 | crypto_inc(ctrblk + i, DES_BLOCK_SIZE); | 411 | if (ret < 0 || ret != n) { |
| 389 | } | 412 | if (ctrptr == ctrblk) |
| 390 | ret = crypt_s390_kmctr(func, ctx->key, out, in, n, ctrblk); | 413 | spin_unlock(&ctrblk_lock); |
| 391 | if (ret < 0 || ret != n) | ||
| 392 | return -EIO; | 414 | return -EIO; |
| 415 | } | ||
| 393 | if (n > DES_BLOCK_SIZE) | 416 | if (n > DES_BLOCK_SIZE) |
| 394 | memcpy(ctrblk, ctrblk + n - DES_BLOCK_SIZE, | 417 | memcpy(ctrptr, ctrptr + n - DES_BLOCK_SIZE, |
| 395 | DES_BLOCK_SIZE); | 418 | DES_BLOCK_SIZE); |
| 396 | crypto_inc(ctrblk, DES_BLOCK_SIZE); | 419 | crypto_inc(ctrptr, DES_BLOCK_SIZE); |
| 397 | out += n; | 420 | out += n; |
| 398 | in += n; | 421 | in += n; |
| 399 | nbytes -= n; | 422 | nbytes -= n; |
| 400 | } | 423 | } |
| 401 | ret = blkcipher_walk_done(desc, walk, nbytes); | 424 | ret = blkcipher_walk_done(desc, walk, nbytes); |
| 402 | } | 425 | } |
| 403 | 426 | if (ctrptr == ctrblk) { | |
| 427 | if (nbytes) | ||
| 428 | memcpy(ctrbuf, ctrptr, DES_BLOCK_SIZE); | ||
| 429 | else | ||
| 430 | memcpy(walk->iv, ctrptr, DES_BLOCK_SIZE); | ||
| 431 | spin_unlock(&ctrblk_lock); | ||
| 432 | } | ||
| 404 | /* final block may be < DES_BLOCK_SIZE, copy only nbytes */ | 433 | /* final block may be < DES_BLOCK_SIZE, copy only nbytes */ |
| 405 | if (nbytes) { | 434 | if (nbytes) { |
| 406 | out = walk->dst.virt.addr; | 435 | out = walk->dst.virt.addr; |
| 407 | in = walk->src.virt.addr; | 436 | in = walk->src.virt.addr; |
| 408 | ret = crypt_s390_kmctr(func, ctx->key, buf, in, | 437 | ret = crypt_s390_kmctr(func, ctx->key, buf, in, |
| 409 | DES_BLOCK_SIZE, ctrblk); | 438 | DES_BLOCK_SIZE, ctrbuf); |
| 410 | if (ret < 0 || ret != DES_BLOCK_SIZE) | 439 | if (ret < 0 || ret != DES_BLOCK_SIZE) |
| 411 | return -EIO; | 440 | return -EIO; |
| 412 | memcpy(out, buf, nbytes); | 441 | memcpy(out, buf, nbytes); |
| 413 | crypto_inc(ctrblk, DES_BLOCK_SIZE); | 442 | crypto_inc(ctrbuf, DES_BLOCK_SIZE); |
| 414 | ret = blkcipher_walk_done(desc, walk, 0); | 443 | ret = blkcipher_walk_done(desc, walk, 0); |
| 444 | memcpy(walk->iv, ctrbuf, DES_BLOCK_SIZE); | ||
| 415 | } | 445 | } |
| 416 | memcpy(walk->iv, ctrblk, DES_BLOCK_SIZE); | ||
| 417 | return ret; | 446 | return ret; |
| 418 | } | 447 | } |
| 419 | 448 | ||
