summaryrefslogtreecommitdiffstats
path: root/crypto/rsa-pkcs1pad.c
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2016-06-29 07:32:28 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2016-07-01 11:45:20 -0400
commitd858b0713849be51406fe84722d0877fb57d201c (patch)
tree416d9d206fbcbf0e4a12f8b0ce5e3c1746fa713a /crypto/rsa-pkcs1pad.c
parent73f79189603b3cd8af1ba1ad2d71f1b3f0aa796d (diff)
crypto: rsa-pkcs1pad - Avoid copying output when possible
In the vast majority of cases (2^-32 on 32-bit and 2^-64 on 64-bit) cases, the result from encryption/signing will require no padding. This patch makes these two operations write their output directly to the final destination. Only in the exceedingly rare cases where fixup is needed to we copy it out and back to add the leading zeroes. This patch also makes use of the crypto_akcipher_set_crypt API instead of writing the akcipher request directly. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto/rsa-pkcs1pad.c')
-rw-r--r--crypto/rsa-pkcs1pad.c112
1 files changed, 45 insertions, 67 deletions
diff --git a/crypto/rsa-pkcs1pad.c b/crypto/rsa-pkcs1pad.c
index ebd851474a9d..8ccfdd7c926e 100644
--- a/crypto/rsa-pkcs1pad.c
+++ b/crypto/rsa-pkcs1pad.c
@@ -185,37 +185,36 @@ static int pkcs1pad_encrypt_sign_complete(struct akcipher_request *req, int err)
185 struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); 185 struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
186 struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm); 186 struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
187 struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req); 187 struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req);
188 size_t pad_len = ctx->key_size - req_ctx->child_req.dst_len; 188 unsigned int pad_len;
189 size_t chunk_len, pad_left; 189 unsigned int len;
190 struct sg_mapping_iter miter; 190 u8 *out_buf;
191 191
192 if (!err) { 192 if (err)
193 if (pad_len) { 193 goto out;
194 sg_miter_start(&miter, req->dst, 194
195 sg_nents_for_len(req->dst, pad_len), 195 len = req_ctx->child_req.dst_len;
196 SG_MITER_ATOMIC | SG_MITER_TO_SG); 196 pad_len = ctx->key_size - len;
197 197
198 pad_left = pad_len; 198 /* Four billion to one */
199 while (pad_left) { 199 if (likely(!pad_len))
200 sg_miter_next(&miter); 200 goto out;
201 201
202 chunk_len = min(miter.length, pad_left); 202 out_buf = kzalloc(ctx->key_size, GFP_ATOMIC);
203 memset(miter.addr, 0, chunk_len); 203 err = -ENOMEM;
204 pad_left -= chunk_len; 204 if (!out_buf)
205 } 205 goto out;
206 206
207 sg_miter_stop(&miter); 207 sg_copy_to_buffer(req->dst, sg_nents_for_len(req->dst, len),
208 } 208 out_buf + pad_len, len);
209 209 sg_copy_from_buffer(req->dst,
210 sg_pcopy_from_buffer(req->dst, 210 sg_nents_for_len(req->dst, ctx->key_size),
211 sg_nents_for_len(req->dst, ctx->key_size), 211 out_buf, ctx->key_size);
212 req_ctx->out_buf, req_ctx->child_req.dst_len, 212 kzfree(out_buf);
213 pad_len); 213
214 } 214out:
215 req->dst_len = ctx->key_size; 215 req->dst_len = ctx->key_size;
216 216
217 kfree(req_ctx->in_buf); 217 kfree(req_ctx->in_buf);
218 kzfree(req_ctx->out_buf);
219 218
220 return err; 219 return err;
221} 220}
@@ -255,15 +254,6 @@ static int pkcs1pad_encrypt(struct akcipher_request *req)
255 return -EOVERFLOW; 254 return -EOVERFLOW;
256 } 255 }
257 256
258 /*
259 * Replace both input and output to add the padding in the input and
260 * the potential missing leading zeros in the output.
261 */
262 req_ctx->child_req.src = req_ctx->in_sg;
263 req_ctx->child_req.src_len = ctx->key_size - 1;
264 req_ctx->child_req.dst = req_ctx->out_sg;
265 req_ctx->child_req.dst_len = ctx->key_size;
266
267 req_ctx->in_buf = kmalloc(ctx->key_size - 1 - req->src_len, 257 req_ctx->in_buf = kmalloc(ctx->key_size - 1 - req->src_len,
268 GFP_KERNEL); 258 GFP_KERNEL);
269 if (!req_ctx->in_buf) 259 if (!req_ctx->in_buf)
@@ -291,6 +281,10 @@ static int pkcs1pad_encrypt(struct akcipher_request *req)
291 akcipher_request_set_callback(&req_ctx->child_req, req->base.flags, 281 akcipher_request_set_callback(&req_ctx->child_req, req->base.flags,
292 pkcs1pad_encrypt_sign_complete_cb, req); 282 pkcs1pad_encrypt_sign_complete_cb, req);
293 283
284 /* Reuse output buffer */
285 akcipher_request_set_crypt(&req_ctx->child_req, req_ctx->in_sg,
286 req->dst, ctx->key_size - 1, req->dst_len);
287
294 err = crypto_akcipher_encrypt(&req_ctx->child_req); 288 err = crypto_akcipher_encrypt(&req_ctx->child_req);
295 if (err != -EINPROGRESS && 289 if (err != -EINPROGRESS &&
296 (err != -EBUSY || 290 (err != -EBUSY ||
@@ -372,12 +366,6 @@ static int pkcs1pad_decrypt(struct akcipher_request *req)
372 if (!ctx->key_size || req->src_len != ctx->key_size) 366 if (!ctx->key_size || req->src_len != ctx->key_size)
373 return -EINVAL; 367 return -EINVAL;
374 368
375 /* Reuse input buffer, output to a new buffer */
376 req_ctx->child_req.src = req->src;
377 req_ctx->child_req.src_len = req->src_len;
378 req_ctx->child_req.dst = req_ctx->out_sg;
379 req_ctx->child_req.dst_len = ctx->key_size ;
380
381 req_ctx->out_buf = kmalloc(ctx->key_size, GFP_KERNEL); 369 req_ctx->out_buf = kmalloc(ctx->key_size, GFP_KERNEL);
382 if (!req_ctx->out_buf) 370 if (!req_ctx->out_buf)
383 return -ENOMEM; 371 return -ENOMEM;
@@ -389,6 +377,11 @@ static int pkcs1pad_decrypt(struct akcipher_request *req)
389 akcipher_request_set_callback(&req_ctx->child_req, req->base.flags, 377 akcipher_request_set_callback(&req_ctx->child_req, req->base.flags,
390 pkcs1pad_decrypt_complete_cb, req); 378 pkcs1pad_decrypt_complete_cb, req);
391 379
380 /* Reuse input buffer, output to a new buffer */
381 akcipher_request_set_crypt(&req_ctx->child_req, req->src,
382 req_ctx->out_sg, req->src_len,
383 ctx->key_size);
384
392 err = crypto_akcipher_decrypt(&req_ctx->child_req); 385 err = crypto_akcipher_decrypt(&req_ctx->child_req);
393 if (err != -EINPROGRESS && 386 if (err != -EINPROGRESS &&
394 (err != -EBUSY || 387 (err != -EBUSY ||
@@ -422,15 +415,6 @@ static int pkcs1pad_sign(struct akcipher_request *req)
422 return -EOVERFLOW; 415 return -EOVERFLOW;
423 } 416 }
424 417
425 /*
426 * Replace both input and output to add the padding in the input and
427 * the potential missing leading zeros in the output.
428 */
429 req_ctx->child_req.src = req_ctx->in_sg;
430 req_ctx->child_req.src_len = ctx->key_size - 1;
431 req_ctx->child_req.dst = req_ctx->out_sg;
432 req_ctx->child_req.dst_len = ctx->key_size;
433
434 req_ctx->in_buf = kmalloc(ctx->key_size - 1 - req->src_len, 418 req_ctx->in_buf = kmalloc(ctx->key_size - 1 - req->src_len,
435 GFP_KERNEL); 419 GFP_KERNEL);
436 if (!req_ctx->in_buf) 420 if (!req_ctx->in_buf)
@@ -447,19 +431,14 @@ static int pkcs1pad_sign(struct akcipher_request *req)
447 pkcs1pad_sg_set_buf(req_ctx->in_sg, req_ctx->in_buf, 431 pkcs1pad_sg_set_buf(req_ctx->in_sg, req_ctx->in_buf,
448 ctx->key_size - 1 - req->src_len, req->src); 432 ctx->key_size - 1 - req->src_len, req->src);
449 433
450 req_ctx->out_buf = kmalloc(ctx->key_size, GFP_KERNEL);
451 if (!req_ctx->out_buf) {
452 kfree(req_ctx->in_buf);
453 return -ENOMEM;
454 }
455
456 pkcs1pad_sg_set_buf(req_ctx->out_sg, req_ctx->out_buf,
457 ctx->key_size, NULL);
458
459 akcipher_request_set_tfm(&req_ctx->child_req, ctx->child); 434 akcipher_request_set_tfm(&req_ctx->child_req, ctx->child);
460 akcipher_request_set_callback(&req_ctx->child_req, req->base.flags, 435 akcipher_request_set_callback(&req_ctx->child_req, req->base.flags,
461 pkcs1pad_encrypt_sign_complete_cb, req); 436 pkcs1pad_encrypt_sign_complete_cb, req);
462 437
438 /* Reuse output buffer */
439 akcipher_request_set_crypt(&req_ctx->child_req, req_ctx->in_sg,
440 req->dst, ctx->key_size - 1, req->dst_len);
441
463 err = crypto_akcipher_sign(&req_ctx->child_req); 442 err = crypto_akcipher_sign(&req_ctx->child_req);
464 if (err != -EINPROGRESS && 443 if (err != -EINPROGRESS &&
465 (err != -EBUSY || 444 (err != -EBUSY ||
@@ -559,12 +538,6 @@ static int pkcs1pad_verify(struct akcipher_request *req)
559 if (!ctx->key_size || req->src_len < ctx->key_size) 538 if (!ctx->key_size || req->src_len < ctx->key_size)
560 return -EINVAL; 539 return -EINVAL;
561 540
562 /* Reuse input buffer, output to a new buffer */
563 req_ctx->child_req.src = req->src;
564 req_ctx->child_req.src_len = req->src_len;
565 req_ctx->child_req.dst = req_ctx->out_sg;
566 req_ctx->child_req.dst_len = ctx->key_size;
567
568 req_ctx->out_buf = kmalloc(ctx->key_size, GFP_KERNEL); 541 req_ctx->out_buf = kmalloc(ctx->key_size, GFP_KERNEL);
569 if (!req_ctx->out_buf) 542 if (!req_ctx->out_buf)
570 return -ENOMEM; 543 return -ENOMEM;
@@ -576,6 +549,11 @@ static int pkcs1pad_verify(struct akcipher_request *req)
576 akcipher_request_set_callback(&req_ctx->child_req, req->base.flags, 549 akcipher_request_set_callback(&req_ctx->child_req, req->base.flags,
577 pkcs1pad_verify_complete_cb, req); 550 pkcs1pad_verify_complete_cb, req);
578 551
552 /* Reuse input buffer, output to a new buffer */
553 akcipher_request_set_crypt(&req_ctx->child_req, req->src,
554 req_ctx->out_sg, req->src_len,
555 ctx->key_size);
556
579 err = crypto_akcipher_verify(&req_ctx->child_req); 557 err = crypto_akcipher_verify(&req_ctx->child_req);
580 if (err != -EINPROGRESS && 558 if (err != -EINPROGRESS &&
581 (err != -EBUSY || 559 (err != -EBUSY ||