aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/crypto
diff options
context:
space:
mode:
authorLeonidas S. Barbosa <leosilva@linux.vnet.ibm.com>2014-10-28 13:44:30 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2014-11-06 10:15:00 -0500
commit9247f0b05572da01721b105558a25d3a413ca0a1 (patch)
tree1562bd20096159db88b5946425ec90d3192345b2 /drivers/crypto
parentac0f0a8a87642bc0dd589a6ead58d273a02d98e4 (diff)
crypto: nx - Moving NX-AES-CCM to be processed logic and sg_list bounds
The previous limits were estimated locally in a single step basead on bound values, however it was not correct since when given certain scatterlist the function nx_build_sg_lists was consuming more sg entries than allocated causing a memory corruption and crashes. This patch removes the old logic and replaces it into nx_sg_build_lists in order to build a correct nx_sg list using the correct sg_max limit and bounds. Signed-off-by: Leonidas S. Barbosa <leosilva@linux.vnet.ibm.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'drivers/crypto')
-rw-r--r--drivers/crypto/nx/nx-aes-ccm.c61
1 files changed, 27 insertions, 34 deletions
diff --git a/drivers/crypto/nx/nx-aes-ccm.c b/drivers/crypto/nx/nx-aes-ccm.c
index 5ecd4c2414aa..67f80813a06f 100644
--- a/drivers/crypto/nx/nx-aes-ccm.c
+++ b/drivers/crypto/nx/nx-aes-ccm.c
@@ -181,6 +181,7 @@ static int generate_pat(u8 *iv,
181 unsigned int iauth_len = 0; 181 unsigned int iauth_len = 0;
182 u8 tmp[16], *b1 = NULL, *b0 = NULL, *result = NULL; 182 u8 tmp[16], *b1 = NULL, *b0 = NULL, *result = NULL;
183 int rc; 183 int rc;
184 unsigned int max_sg_len;
184 185
185 /* zero the ctr value */ 186 /* zero the ctr value */
186 memset(iv + 15 - iv[0], 0, iv[0] + 1); 187 memset(iv + 15 - iv[0], 0, iv[0] + 1);
@@ -248,10 +249,19 @@ static int generate_pat(u8 *iv,
248 if (!req->assoclen) { 249 if (!req->assoclen) {
249 return rc; 250 return rc;
250 } else if (req->assoclen <= 14) { 251 } else if (req->assoclen <= 14) {
251 nx_insg = nx_build_sg_list(nx_insg, b1, 16, nx_ctx->ap->sglen); 252 unsigned int len = 16;
252 nx_outsg = nx_build_sg_list(nx_outsg, tmp, 16, 253
254 nx_insg = nx_build_sg_list(nx_insg, b1, &len, nx_ctx->ap->sglen);
255
256 if (len != 16)
257 return -EINVAL;
258
259 nx_outsg = nx_build_sg_list(nx_outsg, tmp, &len,
253 nx_ctx->ap->sglen); 260 nx_ctx->ap->sglen);
254 261
262 if (len != 16)
263 return -EINVAL;
264
255 /* inlen should be negative, indicating to phyp that its a 265 /* inlen should be negative, indicating to phyp that its a
256 * pointer to an sg list */ 266 * pointer to an sg list */
257 nx_ctx->op.inlen = (nx_ctx->in_sg - nx_insg) * 267 nx_ctx->op.inlen = (nx_ctx->in_sg - nx_insg) *
@@ -273,21 +283,24 @@ static int generate_pat(u8 *iv,
273 atomic64_add(req->assoclen, &(nx_ctx->stats->aes_bytes)); 283 atomic64_add(req->assoclen, &(nx_ctx->stats->aes_bytes));
274 284
275 } else { 285 } else {
276 u32 max_sg_len;
277 unsigned int processed = 0, to_process; 286 unsigned int processed = 0, to_process;
278 287
279 /* page_limit: number of sg entries that fit on one page */
280 max_sg_len = min_t(u32,
281 nx_driver.of.max_sg_len/sizeof(struct nx_sg),
282 nx_ctx->ap->sglen);
283
284 processed += iauth_len; 288 processed += iauth_len;
285 289
290 /* page_limit: number of sg entries that fit on one page */
291 max_sg_len = min_t(u64, nx_ctx->ap->sglen,
292 nx_driver.of.max_sg_len/sizeof(struct nx_sg));
293 max_sg_len = min_t(u64, max_sg_len,
294 nx_ctx->ap->databytelen/NX_PAGE_SIZE);
295
286 do { 296 do {
287 to_process = min_t(u32, req->assoclen - processed, 297 to_process = min_t(u32, req->assoclen - processed,
288 nx_ctx->ap->databytelen); 298 nx_ctx->ap->databytelen);
289 to_process = min_t(u64, to_process, 299
290 NX_PAGE_SIZE * (max_sg_len - 1)); 300 nx_insg = nx_walk_and_build(nx_ctx->in_sg,
301 nx_ctx->ap->sglen,
302 req->assoc, processed,
303 &to_process);
291 304
292 if ((to_process + processed) < req->assoclen) { 305 if ((to_process + processed) < req->assoclen) {
293 NX_CPB_FDM(nx_ctx->csbcpb_aead) |= 306 NX_CPB_FDM(nx_ctx->csbcpb_aead) |=
@@ -297,10 +310,6 @@ static int generate_pat(u8 *iv,
297 ~NX_FDM_INTERMEDIATE; 310 ~NX_FDM_INTERMEDIATE;
298 } 311 }
299 312
300 nx_insg = nx_walk_and_build(nx_ctx->in_sg,
301 nx_ctx->ap->sglen,
302 req->assoc, processed,
303 to_process);
304 313
305 nx_ctx->op_aead.inlen = (nx_ctx->in_sg - nx_insg) * 314 nx_ctx->op_aead.inlen = (nx_ctx->in_sg - nx_insg) *
306 sizeof(struct nx_sg); 315 sizeof(struct nx_sg);
@@ -343,7 +352,6 @@ static int ccm_nx_decrypt(struct aead_request *req,
343 struct nx_ccm_priv *priv = &nx_ctx->priv.ccm; 352 struct nx_ccm_priv *priv = &nx_ctx->priv.ccm;
344 unsigned long irq_flags; 353 unsigned long irq_flags;
345 unsigned int processed = 0, to_process; 354 unsigned int processed = 0, to_process;
346 u32 max_sg_len;
347 int rc = -1; 355 int rc = -1;
348 356
349 spin_lock_irqsave(&nx_ctx->lock, irq_flags); 357 spin_lock_irqsave(&nx_ctx->lock, irq_flags);
@@ -360,19 +368,12 @@ static int ccm_nx_decrypt(struct aead_request *req,
360 if (rc) 368 if (rc)
361 goto out; 369 goto out;
362 370
363 /* page_limit: number of sg entries that fit on one page */
364 max_sg_len = min_t(u32, nx_driver.of.max_sg_len/sizeof(struct nx_sg),
365 nx_ctx->ap->sglen);
366
367 do { 371 do {
368 372
369 /* to_process: the AES_BLOCK_SIZE data chunk to process in this 373 /* to_process: the AES_BLOCK_SIZE data chunk to process in this
370 * update. This value is bound by sg list limits. 374 * update. This value is bound by sg list limits.
371 */ 375 */
372 to_process = min_t(u64, nbytes - processed, 376 to_process = nbytes - processed;
373 nx_ctx->ap->databytelen);
374 to_process = min_t(u64, to_process,
375 NX_PAGE_SIZE * (max_sg_len - 1));
376 377
377 if ((to_process + processed) < nbytes) 378 if ((to_process + processed) < nbytes)
378 NX_CPB_FDM(csbcpb) |= NX_FDM_INTERMEDIATE; 379 NX_CPB_FDM(csbcpb) |= NX_FDM_INTERMEDIATE;
@@ -382,7 +383,7 @@ static int ccm_nx_decrypt(struct aead_request *req,
382 NX_CPB_FDM(nx_ctx->csbcpb) &= ~NX_FDM_ENDE_ENCRYPT; 383 NX_CPB_FDM(nx_ctx->csbcpb) &= ~NX_FDM_ENDE_ENCRYPT;
383 384
384 rc = nx_build_sg_lists(nx_ctx, desc, req->dst, req->src, 385 rc = nx_build_sg_lists(nx_ctx, desc, req->dst, req->src,
385 to_process, processed, 386 &to_process, processed,
386 csbcpb->cpb.aes_ccm.iv_or_ctr); 387 csbcpb->cpb.aes_ccm.iv_or_ctr);
387 if (rc) 388 if (rc)
388 goto out; 389 goto out;
@@ -427,7 +428,6 @@ static int ccm_nx_encrypt(struct aead_request *req,
427 unsigned int authsize = crypto_aead_authsize(crypto_aead_reqtfm(req)); 428 unsigned int authsize = crypto_aead_authsize(crypto_aead_reqtfm(req));
428 unsigned long irq_flags; 429 unsigned long irq_flags;
429 unsigned int processed = 0, to_process; 430 unsigned int processed = 0, to_process;
430 u32 max_sg_len;
431 int rc = -1; 431 int rc = -1;
432 432
433 spin_lock_irqsave(&nx_ctx->lock, irq_flags); 433 spin_lock_irqsave(&nx_ctx->lock, irq_flags);
@@ -437,18 +437,11 @@ static int ccm_nx_encrypt(struct aead_request *req,
437 if (rc) 437 if (rc)
438 goto out; 438 goto out;
439 439
440 /* page_limit: number of sg entries that fit on one page */
441 max_sg_len = min_t(u32, nx_driver.of.max_sg_len/sizeof(struct nx_sg),
442 nx_ctx->ap->sglen);
443
444 do { 440 do {
445 /* to process: the AES_BLOCK_SIZE data chunk to process in this 441 /* to process: the AES_BLOCK_SIZE data chunk to process in this
446 * update. This value is bound by sg list limits. 442 * update. This value is bound by sg list limits.
447 */ 443 */
448 to_process = min_t(u64, nbytes - processed, 444 to_process = nbytes - processed;
449 nx_ctx->ap->databytelen);
450 to_process = min_t(u64, to_process,
451 NX_PAGE_SIZE * (max_sg_len - 1));
452 445
453 if ((to_process + processed) < nbytes) 446 if ((to_process + processed) < nbytes)
454 NX_CPB_FDM(csbcpb) |= NX_FDM_INTERMEDIATE; 447 NX_CPB_FDM(csbcpb) |= NX_FDM_INTERMEDIATE;
@@ -458,7 +451,7 @@ static int ccm_nx_encrypt(struct aead_request *req,
458 NX_CPB_FDM(csbcpb) |= NX_FDM_ENDE_ENCRYPT; 451 NX_CPB_FDM(csbcpb) |= NX_FDM_ENDE_ENCRYPT;
459 452
460 rc = nx_build_sg_lists(nx_ctx, desc, req->dst, req->src, 453 rc = nx_build_sg_lists(nx_ctx, desc, req->dst, req->src,
461 to_process, processed, 454 &to_process, processed,
462 csbcpb->cpb.aes_ccm.iv_or_ctr); 455 csbcpb->cpb.aes_ccm.iv_or_ctr);
463 if (rc) 456 if (rc)
464 goto out; 457 goto out;