Skip to content

Commit 030f4e9

Browse files
committed
crypto: nx - Fix reentrancy bugs
This patch fixes a host of reentrancy bugs in the nx driver. The following algorithms are affected: * CCM * GCM * CTR * XCBC * SHA256 * SHA512 The crypto API allows a single transform to be used by multiple threads simultaneously. For example, IPsec will use a single tfm to process packets for a given SA. As packets may arrive on multiple CPUs that tfm must be reentrant. The nx driver does try to deal with this by using a spin lock. Unfortunately only the basic AES/CBC/ECB algorithms do this in the correct way. The symptom of these bugs may range from the generation of incorrect output to memory corruption. Cc: stable@vger.kernel.org Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
1 parent acb33cc commit 030f4e9

File tree

8 files changed

+125
-79
lines changed

8 files changed

+125
-79
lines changed

drivers/crypto/nx/nx-aes-ccm.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -494,8 +494,9 @@ static int ccm_nx_encrypt(struct aead_request *req,
494494
static int ccm4309_aes_nx_encrypt(struct aead_request *req)
495495
{
496496
struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
497+
struct nx_gcm_rctx *rctx = aead_request_ctx(req);
497498
struct blkcipher_desc desc;
498-
u8 *iv = nx_ctx->priv.ccm.iv;
499+
u8 *iv = rctx->iv;
499500

500501
iv[0] = 3;
501502
memcpy(iv + 1, nx_ctx->priv.ccm.nonce, 3);
@@ -525,8 +526,9 @@ static int ccm_aes_nx_encrypt(struct aead_request *req)
525526
static int ccm4309_aes_nx_decrypt(struct aead_request *req)
526527
{
527528
struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
529+
struct nx_gcm_rctx *rctx = aead_request_ctx(req);
528530
struct blkcipher_desc desc;
529-
u8 *iv = nx_ctx->priv.ccm.iv;
531+
u8 *iv = rctx->iv;
530532

531533
iv[0] = 3;
532534
memcpy(iv + 1, nx_ctx->priv.ccm.nonce, 3);

drivers/crypto/nx/nx-aes-ctr.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ static int ctr3686_aes_nx_set_key(struct crypto_tfm *tfm,
7272
if (key_len < CTR_RFC3686_NONCE_SIZE)
7373
return -EINVAL;
7474

75-
memcpy(nx_ctx->priv.ctr.iv,
75+
memcpy(nx_ctx->priv.ctr.nonce,
7676
in_key + key_len - CTR_RFC3686_NONCE_SIZE,
7777
CTR_RFC3686_NONCE_SIZE);
7878

@@ -131,14 +131,15 @@ static int ctr3686_aes_nx_crypt(struct blkcipher_desc *desc,
131131
unsigned int nbytes)
132132
{
133133
struct nx_crypto_ctx *nx_ctx = crypto_blkcipher_ctx(desc->tfm);
134-
u8 *iv = nx_ctx->priv.ctr.iv;
134+
u8 iv[16];
135135

136+
memcpy(iv, nx_ctx->priv.ctr.nonce, CTR_RFC3686_IV_SIZE);
136137
memcpy(iv + CTR_RFC3686_NONCE_SIZE,
137138
desc->info, CTR_RFC3686_IV_SIZE);
138139
iv[12] = iv[13] = iv[14] = 0;
139140
iv[15] = 1;
140141

141-
desc->info = nx_ctx->priv.ctr.iv;
142+
desc->info = iv;
142143

143144
return ctr_aes_nx_crypt(desc, dst, src, nbytes);
144145
}

drivers/crypto/nx/nx-aes-gcm.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@ static int gcm_empty(struct aead_request *req, struct blkcipher_desc *desc,
317317
static int gcm_aes_nx_crypt(struct aead_request *req, int enc)
318318
{
319319
struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
320+
struct nx_gcm_rctx *rctx = aead_request_ctx(req);
320321
struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
321322
struct blkcipher_desc desc;
322323
unsigned int nbytes = req->cryptlen;
@@ -326,7 +327,7 @@ static int gcm_aes_nx_crypt(struct aead_request *req, int enc)
326327

327328
spin_lock_irqsave(&nx_ctx->lock, irq_flags);
328329

329-
desc.info = nx_ctx->priv.gcm.iv;
330+
desc.info = rctx->iv;
330331
/* initialize the counter */
331332
*(u32 *)(desc.info + NX_GCM_CTR_OFFSET) = 1;
332333

@@ -424,8 +425,8 @@ static int gcm_aes_nx_crypt(struct aead_request *req, int enc)
424425

425426
static int gcm_aes_nx_encrypt(struct aead_request *req)
426427
{
427-
struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
428-
char *iv = nx_ctx->priv.gcm.iv;
428+
struct nx_gcm_rctx *rctx = aead_request_ctx(req);
429+
char *iv = rctx->iv;
429430

430431
memcpy(iv, req->iv, 12);
431432

@@ -434,8 +435,8 @@ static int gcm_aes_nx_encrypt(struct aead_request *req)
434435

435436
static int gcm_aes_nx_decrypt(struct aead_request *req)
436437
{
437-
struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
438-
char *iv = nx_ctx->priv.gcm.iv;
438+
struct nx_gcm_rctx *rctx = aead_request_ctx(req);
439+
char *iv = rctx->iv;
439440

440441
memcpy(iv, req->iv, 12);
441442

@@ -445,7 +446,8 @@ static int gcm_aes_nx_decrypt(struct aead_request *req)
445446
static int gcm4106_aes_nx_encrypt(struct aead_request *req)
446447
{
447448
struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
448-
char *iv = nx_ctx->priv.gcm.iv;
449+
struct nx_gcm_rctx *rctx = aead_request_ctx(req);
450+
char *iv = rctx->iv;
449451
char *nonce = nx_ctx->priv.gcm.nonce;
450452

451453
memcpy(iv, nonce, NX_GCM4106_NONCE_LEN);
@@ -457,7 +459,8 @@ static int gcm4106_aes_nx_encrypt(struct aead_request *req)
457459
static int gcm4106_aes_nx_decrypt(struct aead_request *req)
458460
{
459461
struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(req->base.tfm);
460-
char *iv = nx_ctx->priv.gcm.iv;
462+
struct nx_gcm_rctx *rctx = aead_request_ctx(req);
463+
char *iv = rctx->iv;
461464
char *nonce = nx_ctx->priv.gcm.nonce;
462465

463466
memcpy(iv, nonce, NX_GCM4106_NONCE_LEN);

drivers/crypto/nx/nx-aes-xcbc.c

Lines changed: 44 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ static int nx_xcbc_set_key(struct crypto_shash *desc,
4242
unsigned int key_len)
4343
{
4444
struct nx_crypto_ctx *nx_ctx = crypto_shash_ctx(desc);
45+
struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
4546

4647
switch (key_len) {
4748
case AES_KEYSIZE_128:
@@ -51,7 +52,7 @@ static int nx_xcbc_set_key(struct crypto_shash *desc,
5152
return -EINVAL;
5253
}
5354

54-
memcpy(nx_ctx->priv.xcbc.key, in_key, key_len);
55+
memcpy(csbcpb->cpb.aes_xcbc.key, in_key, key_len);
5556

5657
return 0;
5758
}
@@ -148,32 +149,29 @@ static int nx_xcbc_empty(struct shash_desc *desc, u8 *out)
148149
return rc;
149150
}
150151

151-
static int nx_xcbc_init(struct shash_desc *desc)
152+
static int nx_crypto_ctx_aes_xcbc_init2(struct crypto_tfm *tfm)
152153
{
153-
struct xcbc_state *sctx = shash_desc_ctx(desc);
154-
struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
154+
struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(tfm);
155155
struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
156-
struct nx_sg *out_sg;
157-
int len;
156+
int err;
158157

159-
nx_ctx_init(nx_ctx, HCOP_FC_AES);
158+
err = nx_crypto_ctx_aes_xcbc_init(tfm);
159+
if (err)
160+
return err;
160161

161-
memset(sctx, 0, sizeof *sctx);
162+
nx_ctx_init(nx_ctx, HCOP_FC_AES);
162163

163164
NX_CPB_SET_KEY_SIZE(csbcpb, NX_KS_AES_128);
164165
csbcpb->cpb.hdr.mode = NX_MODE_AES_XCBC_MAC;
165166

166-
memcpy(csbcpb->cpb.aes_xcbc.key, nx_ctx->priv.xcbc.key, AES_BLOCK_SIZE);
167-
memset(nx_ctx->priv.xcbc.key, 0, sizeof *nx_ctx->priv.xcbc.key);
168-
169-
len = AES_BLOCK_SIZE;
170-
out_sg = nx_build_sg_list(nx_ctx->out_sg, (u8 *)sctx->state,
171-
&len, nx_ctx->ap->sglen);
167+
return 0;
168+
}
172169

173-
if (len != AES_BLOCK_SIZE)
174-
return -EINVAL;
170+
static int nx_xcbc_init(struct shash_desc *desc)
171+
{
172+
struct xcbc_state *sctx = shash_desc_ctx(desc);
175173

176-
nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg);
174+
memset(sctx, 0, sizeof *sctx);
177175

178176
return 0;
179177
}
@@ -186,6 +184,7 @@ static int nx_xcbc_update(struct shash_desc *desc,
186184
struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
187185
struct nx_csbcpb *csbcpb = nx_ctx->csbcpb;
188186
struct nx_sg *in_sg;
187+
struct nx_sg *out_sg;
189188
u32 to_process = 0, leftover, total;
190189
unsigned int max_sg_len;
191190
unsigned long irq_flags;
@@ -213,6 +212,17 @@ static int nx_xcbc_update(struct shash_desc *desc,
213212
max_sg_len = min_t(u64, max_sg_len,
214213
nx_ctx->ap->databytelen/NX_PAGE_SIZE);
215214

215+
data_len = AES_BLOCK_SIZE;
216+
out_sg = nx_build_sg_list(nx_ctx->out_sg, (u8 *)sctx->state,
217+
&len, nx_ctx->ap->sglen);
218+
219+
if (data_len != AES_BLOCK_SIZE) {
220+
rc = -EINVAL;
221+
goto out;
222+
}
223+
224+
nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg);
225+
216226
do {
217227
to_process = total - to_process;
218228
to_process = to_process & ~(AES_BLOCK_SIZE - 1);
@@ -235,8 +245,10 @@ static int nx_xcbc_update(struct shash_desc *desc,
235245
(u8 *) sctx->buffer,
236246
&data_len,
237247
max_sg_len);
238-
if (data_len != sctx->count)
239-
return -EINVAL;
248+
if (data_len != sctx->count) {
249+
rc = -EINVAL;
250+
goto out;
251+
}
240252
}
241253

242254
data_len = to_process - sctx->count;
@@ -245,8 +257,10 @@ static int nx_xcbc_update(struct shash_desc *desc,
245257
&data_len,
246258
max_sg_len);
247259

248-
if (data_len != to_process - sctx->count)
249-
return -EINVAL;
260+
if (data_len != to_process - sctx->count) {
261+
rc = -EINVAL;
262+
goto out;
263+
}
250264

251265
nx_ctx->op.inlen = (nx_ctx->in_sg - in_sg) *
252266
sizeof(struct nx_sg);
@@ -325,15 +339,19 @@ static int nx_xcbc_final(struct shash_desc *desc, u8 *out)
325339
in_sg = nx_build_sg_list(nx_ctx->in_sg, (u8 *)sctx->buffer,
326340
&len, nx_ctx->ap->sglen);
327341

328-
if (len != sctx->count)
329-
return -EINVAL;
342+
if (len != sctx->count) {
343+
rc = -EINVAL;
344+
goto out;
345+
}
330346

331347
len = AES_BLOCK_SIZE;
332348
out_sg = nx_build_sg_list(nx_ctx->out_sg, out, &len,
333349
nx_ctx->ap->sglen);
334350

335-
if (len != AES_BLOCK_SIZE)
336-
return -EINVAL;
351+
if (len != AES_BLOCK_SIZE) {
352+
rc = -EINVAL;
353+
goto out;
354+
}
337355

338356
nx_ctx->op.inlen = (nx_ctx->in_sg - in_sg) * sizeof(struct nx_sg);
339357
nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg);
@@ -372,7 +390,7 @@ struct shash_alg nx_shash_aes_xcbc_alg = {
372390
.cra_blocksize = AES_BLOCK_SIZE,
373391
.cra_module = THIS_MODULE,
374392
.cra_ctxsize = sizeof(struct nx_crypto_ctx),
375-
.cra_init = nx_crypto_ctx_aes_xcbc_init,
393+
.cra_init = nx_crypto_ctx_aes_xcbc_init2,
376394
.cra_exit = nx_crypto_ctx_exit,
377395
}
378396
};

drivers/crypto/nx/nx-sha256.c

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -29,34 +29,28 @@
2929
#include "nx.h"
3030

3131

32-
static int nx_sha256_init(struct shash_desc *desc)
32+
static int nx_crypto_ctx_sha256_init(struct crypto_tfm *tfm)
3333
{
34-
struct sha256_state *sctx = shash_desc_ctx(desc);
35-
struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
36-
struct nx_sg *out_sg;
37-
int len;
38-
u32 max_sg_len;
34+
struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(tfm);
35+
int err;
3936

40-
nx_ctx_init(nx_ctx, HCOP_FC_SHA);
37+
err = nx_crypto_ctx_sha_init(tfm);
38+
if (err)
39+
return err;
4140

42-
memset(sctx, 0, sizeof *sctx);
41+
nx_ctx_init(nx_ctx, HCOP_FC_SHA);
4342

4443
nx_ctx->ap = &nx_ctx->props[NX_PROPS_SHA256];
4544

4645
NX_CPB_SET_DIGEST_SIZE(nx_ctx->csbcpb, NX_DS_SHA256);
4746

48-
max_sg_len = min_t(u64, nx_ctx->ap->sglen,
49-
nx_driver.of.max_sg_len/sizeof(struct nx_sg));
50-
max_sg_len = min_t(u64, max_sg_len,
51-
nx_ctx->ap->databytelen/NX_PAGE_SIZE);
47+
return 0;
48+
}
5249

53-
len = SHA256_DIGEST_SIZE;
54-
out_sg = nx_build_sg_list(nx_ctx->out_sg, (u8 *)sctx->state,
55-
&len, max_sg_len);
56-
nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg);
50+
static int nx_sha256_init(struct shash_desc *desc) {
51+
struct sha256_state *sctx = shash_desc_ctx(desc);
5752

58-
if (len != SHA256_DIGEST_SIZE)
59-
return -EINVAL;
53+
memset(sctx, 0, sizeof *sctx);
6054

6155
sctx->state[0] = __cpu_to_be32(SHA256_H0);
6256
sctx->state[1] = __cpu_to_be32(SHA256_H1);
@@ -78,6 +72,7 @@ static int nx_sha256_update(struct shash_desc *desc, const u8 *data,
7872
struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
7973
struct nx_csbcpb *csbcpb = (struct nx_csbcpb *)nx_ctx->csbcpb;
8074
struct nx_sg *in_sg;
75+
struct nx_sg *out_sg;
8176
u64 to_process = 0, leftover, total;
8277
unsigned long irq_flags;
8378
int rc = 0;
@@ -108,6 +103,16 @@ static int nx_sha256_update(struct shash_desc *desc, const u8 *data,
108103
max_sg_len = min_t(u64, max_sg_len,
109104
nx_ctx->ap->databytelen/NX_PAGE_SIZE);
110105

106+
data_len = SHA256_DIGEST_SIZE;
107+
out_sg = nx_build_sg_list(nx_ctx->out_sg, (u8 *)sctx->state,
108+
&data_len, max_sg_len);
109+
nx_ctx->op.outlen = (nx_ctx->out_sg - out_sg) * sizeof(struct nx_sg);
110+
111+
if (data_len != SHA256_DIGEST_SIZE) {
112+
rc = -EINVAL;
113+
goto out;
114+
}
115+
111116
do {
112117
/*
113118
* to_process: the SHA256_BLOCK_SIZE data chunk to process in
@@ -282,7 +287,7 @@ struct shash_alg nx_shash_sha256_alg = {
282287
.cra_blocksize = SHA256_BLOCK_SIZE,
283288
.cra_module = THIS_MODULE,
284289
.cra_ctxsize = sizeof(struct nx_crypto_ctx),
285-
.cra_init = nx_crypto_ctx_sha_init,
290+
.cra_init = nx_crypto_ctx_sha256_init,
286291
.cra_exit = nx_crypto_ctx_exit,
287292
}
288293
};

0 commit comments

Comments
 (0)