aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
authorHarald Freudenberger <freude@linux.vnet.ibm.com>2014-01-22 07:00:04 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2014-01-30 08:45:11 -0500
commitadc3fcf1552b6e406d172fd9690bbd1395053d13 (patch)
treed10b74782748dade0df03c287f3d52455ef9493b /arch/s390
parent0519e9ad89e5cd6e6b08398f57c6a71d9580564c (diff)
crypto: s390 - fix des and des3_ede cbc concurrency issue
In s390 des and des3_ede cbc mode the iv value is not protected against concurrency access and modifications from another running en/decrypt operation which is using the very same tfm struct instance. This fix copies the iv to the local stack before the crypto operation and stores the value back when done. Cc: stable@vger.kernel.org Signed-off-by: Harald Freudenberger <freude@linux.vnet.ibm.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/crypto/des_s390.c26
1 files changed, 14 insertions, 12 deletions
diff --git a/arch/s390/crypto/des_s390.c b/arch/s390/crypto/des_s390.c
index 200f2a1b599d..82a0a2ad2494 100644
--- a/arch/s390/crypto/des_s390.c
+++ b/arch/s390/crypto/des_s390.c
@@ -105,29 +105,35 @@ static int ecb_desall_crypt(struct blkcipher_desc *desc, long func,
105} 105}
106 106
107static int cbc_desall_crypt(struct blkcipher_desc *desc, long func, 107static int cbc_desall_crypt(struct blkcipher_desc *desc, long func,
108 u8 *iv, struct blkcipher_walk *walk) 108 struct blkcipher_walk *walk)
109{ 109{
110 struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
110 int ret = blkcipher_walk_virt(desc, walk); 111 int ret = blkcipher_walk_virt(desc, walk);
111 unsigned int nbytes = walk->nbytes; 112 unsigned int nbytes = walk->nbytes;
113 struct {
114 u8 iv[DES_BLOCK_SIZE];
115 u8 key[DES3_KEY_SIZE];
116 } param;
112 117
113 if (!nbytes) 118 if (!nbytes)
114 goto out; 119 goto out;
115 120
116 memcpy(iv, walk->iv, DES_BLOCK_SIZE); 121 memcpy(param.iv, walk->iv, DES_BLOCK_SIZE);
122 memcpy(param.key, ctx->key, DES3_KEY_SIZE);
117 do { 123 do {
118 /* only use complete blocks */ 124 /* only use complete blocks */
119 unsigned int n = nbytes & ~(DES_BLOCK_SIZE - 1); 125 unsigned int n = nbytes & ~(DES_BLOCK_SIZE - 1);
120 u8 *out = walk->dst.virt.addr; 126 u8 *out = walk->dst.virt.addr;
121 u8 *in = walk->src.virt.addr; 127 u8 *in = walk->src.virt.addr;
122 128
123 ret = crypt_s390_kmc(func, iv, out, in, n); 129 ret = crypt_s390_kmc(func, &param, out, in, n);
124 if (ret < 0 || ret != n) 130 if (ret < 0 || ret != n)
125 return -EIO; 131 return -EIO;
126 132
127 nbytes &= DES_BLOCK_SIZE - 1; 133 nbytes &= DES_BLOCK_SIZE - 1;
128 ret = blkcipher_walk_done(desc, walk, nbytes); 134 ret = blkcipher_walk_done(desc, walk, nbytes);
129 } while ((nbytes = walk->nbytes)); 135 } while ((nbytes = walk->nbytes));
130 memcpy(walk->iv, iv, DES_BLOCK_SIZE); 136 memcpy(walk->iv, param.iv, DES_BLOCK_SIZE);
131 137
132out: 138out:
133 return ret; 139 return ret;
@@ -179,22 +185,20 @@ static int cbc_des_encrypt(struct blkcipher_desc *desc,
179 struct scatterlist *dst, struct scatterlist *src, 185 struct scatterlist *dst, struct scatterlist *src,
180 unsigned int nbytes) 186 unsigned int nbytes)
181{ 187{
182 struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
183 struct blkcipher_walk walk; 188 struct blkcipher_walk walk;
184 189
185 blkcipher_walk_init(&walk, dst, src, nbytes); 190 blkcipher_walk_init(&walk, dst, src, nbytes);
186 return cbc_desall_crypt(desc, KMC_DEA_ENCRYPT, ctx->iv, &walk); 191 return cbc_desall_crypt(desc, KMC_DEA_ENCRYPT, &walk);
187} 192}
188 193
189static int cbc_des_decrypt(struct blkcipher_desc *desc, 194static int cbc_des_decrypt(struct blkcipher_desc *desc,
190 struct scatterlist *dst, struct scatterlist *src, 195 struct scatterlist *dst, struct scatterlist *src,
191 unsigned int nbytes) 196 unsigned int nbytes)
192{ 197{
193 struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
194 struct blkcipher_walk walk; 198 struct blkcipher_walk walk;
195 199
196 blkcipher_walk_init(&walk, dst, src, nbytes); 200 blkcipher_walk_init(&walk, dst, src, nbytes);
197 return cbc_desall_crypt(desc, KMC_DEA_DECRYPT, ctx->iv, &walk); 201 return cbc_desall_crypt(desc, KMC_DEA_DECRYPT, &walk);
198} 202}
199 203
200static struct crypto_alg cbc_des_alg = { 204static struct crypto_alg cbc_des_alg = {
@@ -327,22 +331,20 @@ static int cbc_des3_encrypt(struct blkcipher_desc *desc,
327 struct scatterlist *dst, struct scatterlist *src, 331 struct scatterlist *dst, struct scatterlist *src,
328 unsigned int nbytes) 332 unsigned int nbytes)
329{ 333{
330 struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
331 struct blkcipher_walk walk; 334 struct blkcipher_walk walk;
332 335
333 blkcipher_walk_init(&walk, dst, src, nbytes); 336 blkcipher_walk_init(&walk, dst, src, nbytes);
334 return cbc_desall_crypt(desc, KMC_TDEA_192_ENCRYPT, ctx->iv, &walk); 337 return cbc_desall_crypt(desc, KMC_TDEA_192_ENCRYPT, &walk);
335} 338}
336 339
337static int cbc_des3_decrypt(struct blkcipher_desc *desc, 340static int cbc_des3_decrypt(struct blkcipher_desc *desc,
338 struct scatterlist *dst, struct scatterlist *src, 341 struct scatterlist *dst, struct scatterlist *src,
339 unsigned int nbytes) 342 unsigned int nbytes)
340{ 343{
341 struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
342 struct blkcipher_walk walk; 344 struct blkcipher_walk walk;
343 345
344 blkcipher_walk_init(&walk, dst, src, nbytes); 346 blkcipher_walk_init(&walk, dst, src, nbytes);
345 return cbc_desall_crypt(desc, KMC_TDEA_192_DECRYPT, ctx->iv, &walk); 347 return cbc_desall_crypt(desc, KMC_TDEA_192_DECRYPT, &walk);
346} 348}
347 349
348static struct crypto_alg cbc_des3_alg = { 350static struct crypto_alg cbc_des3_alg = {