aboutsummaryrefslogtreecommitdiffstats
path: root/lib/mpi/mpicoder.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-07-26 16:40:17 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-07-26 16:40:17 -0400
commitbbce2ad2d711c12d93145a7bbdf086e73f414bcd (patch)
tree35432a39f68f4c5df44ed38037cbf05adadb923e /lib/mpi/mpicoder.c
parent0f776dc377f6c87f4e4d4a5f63602f33fb93b31e (diff)
parent0f95e2ffc58f5d32a90eb1051d17aeebc21cf91d (diff)
Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
Pull crypto updates from Herbert Xu: "Here is the crypto update for 4.8: API: - first part of skcipher low-level conversions - add KPP (Key-agreement Protocol Primitives) interface. Algorithms: - fix IPsec/cryptd reordering issues that affects aesni - RSA no longer does explicit leading zero removal - add SHA3 - add DH - add ECDH - improve DRBG performance by not doing CTR by hand Drivers: - add x86 AVX2 multibuffer SHA256/512 - add POWER8 optimised crc32c - add xts support to vmx - add DH support to qat - add RSA support to caam - add Layerscape support to caam - add SEC1 AEAD support to talitos - improve performance by chaining requests in marvell/cesa - add support for Araneus Alea I USB RNG - add support for Broadcom BCM5301 RNG - add support for Amlogic Meson RNG - add support Broadcom NSP SoC RNG" * 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6: (180 commits) crypto: vmx - Fix aes_p8_xts_decrypt build failure crypto: vmx - Ignore generated files crypto: vmx - Adding support for XTS crypto: vmx - Adding asm subroutines for XTS crypto: skcipher - add comment for skcipher_alg->base crypto: testmgr - Print akcipher algorithm name crypto: marvell - Fix wrong flag used for GFP in mv_cesa_dma_add_iv_op crypto: nx - off by one bug in nx_of_update_msc() crypto: rsa-pkcs1pad - fix rsa-pkcs1pad request struct crypto: scatterwalk - Inline start/map/done crypto: scatterwalk - Remove unnecessary BUG in scatterwalk_start crypto: scatterwalk - Remove unnecessary advance in scatterwalk_pagedone crypto: scatterwalk - Fix test in scatterwalk_done crypto: api - Optimise away crypto_yield when hard preemption is on crypto: scatterwalk - add no-copy support to copychunks crypto: scatterwalk - Remove scatterwalk_bytes_sglen crypto: omap - Stop using crypto scatterwalk_bytes_sglen crypto: skcipher - Remove top-level givcipher interface crypto: user - Remove crypto_lookup_skcipher call crypto: cts - Convert to skcipher ...
Diffstat (limited to 'lib/mpi/mpicoder.c')
-rw-r--r--lib/mpi/mpicoder.c249
1 files changed, 81 insertions, 168 deletions
diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c
index 747606f9e4a3..c6272ae2015e 100644
--- a/lib/mpi/mpicoder.c
+++ b/lib/mpi/mpicoder.c
@@ -21,6 +21,7 @@
21#include <linux/bitops.h> 21#include <linux/bitops.h>
22#include <linux/count_zeros.h> 22#include <linux/count_zeros.h>
23#include <linux/byteorder/generic.h> 23#include <linux/byteorder/generic.h>
24#include <linux/scatterlist.h>
24#include <linux/string.h> 25#include <linux/string.h>
25#include "mpi-internal.h" 26#include "mpi-internal.h"
26 27
@@ -50,9 +51,7 @@ MPI mpi_read_raw_data(const void *xbuffer, size_t nbytes)
50 return NULL; 51 return NULL;
51 } 52 }
52 if (nbytes > 0) 53 if (nbytes > 0)
53 nbits -= count_leading_zeros(buffer[0]); 54 nbits -= count_leading_zeros(buffer[0]) - (BITS_PER_LONG - 8);
54 else
55 nbits = 0;
56 55
57 nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB); 56 nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB);
58 val = mpi_alloc(nlimbs); 57 val = mpi_alloc(nlimbs);
@@ -82,50 +81,30 @@ EXPORT_SYMBOL_GPL(mpi_read_raw_data);
82MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread) 81MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread)
83{ 82{
84 const uint8_t *buffer = xbuffer; 83 const uint8_t *buffer = xbuffer;
85 int i, j; 84 unsigned int nbits, nbytes;
86 unsigned nbits, nbytes, nlimbs, nread = 0; 85 MPI val;
87 mpi_limb_t a;
88 MPI val = NULL;
89 86
90 if (*ret_nread < 2) 87 if (*ret_nread < 2)
91 goto leave; 88 return ERR_PTR(-EINVAL);
92 nbits = buffer[0] << 8 | buffer[1]; 89 nbits = buffer[0] << 8 | buffer[1];
93 90
94 if (nbits > MAX_EXTERN_MPI_BITS) { 91 if (nbits > MAX_EXTERN_MPI_BITS) {
95 pr_info("MPI: mpi too large (%u bits)\n", nbits); 92 pr_info("MPI: mpi too large (%u bits)\n", nbits);
96 goto leave; 93 return ERR_PTR(-EINVAL);
97 } 94 }
98 buffer += 2;
99 nread = 2;
100 95
101 nbytes = DIV_ROUND_UP(nbits, 8); 96 nbytes = DIV_ROUND_UP(nbits, 8);
102 nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB); 97 if (nbytes + 2 > *ret_nread) {
103 val = mpi_alloc(nlimbs); 98 pr_info("MPI: mpi larger than buffer nbytes=%u ret_nread=%u\n",
104 if (!val) 99 nbytes, *ret_nread);
105 return NULL; 100 return ERR_PTR(-EINVAL);
106 i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
107 i %= BYTES_PER_MPI_LIMB;
108 val->nbits = nbits;
109 j = val->nlimbs = nlimbs;
110 val->sign = 0;
111 for (; j > 0; j--) {
112 a = 0;
113 for (; i < BYTES_PER_MPI_LIMB; i++) {
114 if (++nread > *ret_nread) {
115 printk
116 ("MPI: mpi larger than buffer nread=%d ret_nread=%d\n",
117 nread, *ret_nread);
118 goto leave;
119 }
120 a <<= 8;
121 a |= *buffer++;
122 }
123 i = 0;
124 val->d[j - 1] = a;
125 } 101 }
126 102
127leave: 103 val = mpi_read_raw_data(buffer + 2, nbytes);
128 *ret_nread = nread; 104 if (!val)
105 return ERR_PTR(-ENOMEM);
106
107 *ret_nread = nbytes + 2;
129 return val; 108 return val;
130} 109}
131EXPORT_SYMBOL_GPL(mpi_read_from_buffer); 110EXPORT_SYMBOL_GPL(mpi_read_from_buffer);
@@ -250,82 +229,6 @@ void *mpi_get_buffer(MPI a, unsigned *nbytes, int *sign)
250} 229}
251EXPORT_SYMBOL_GPL(mpi_get_buffer); 230EXPORT_SYMBOL_GPL(mpi_get_buffer);
252 231
253/****************
254 * Use BUFFER to update MPI.
255 */
256int mpi_set_buffer(MPI a, const void *xbuffer, unsigned nbytes, int sign)
257{
258 const uint8_t *buffer = xbuffer, *p;
259 mpi_limb_t alimb;
260 int nlimbs;
261 int i;
262
263 nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB);
264 if (RESIZE_IF_NEEDED(a, nlimbs) < 0)
265 return -ENOMEM;
266 a->sign = sign;
267
268 for (i = 0, p = buffer + nbytes - 1; p >= buffer + BYTES_PER_MPI_LIMB;) {
269#if BYTES_PER_MPI_LIMB == 4
270 alimb = (mpi_limb_t) *p--;
271 alimb |= (mpi_limb_t) *p-- << 8;
272 alimb |= (mpi_limb_t) *p-- << 16;
273 alimb |= (mpi_limb_t) *p-- << 24;
274#elif BYTES_PER_MPI_LIMB == 8
275 alimb = (mpi_limb_t) *p--;
276 alimb |= (mpi_limb_t) *p-- << 8;
277 alimb |= (mpi_limb_t) *p-- << 16;
278 alimb |= (mpi_limb_t) *p-- << 24;
279 alimb |= (mpi_limb_t) *p-- << 32;
280 alimb |= (mpi_limb_t) *p-- << 40;
281 alimb |= (mpi_limb_t) *p-- << 48;
282 alimb |= (mpi_limb_t) *p-- << 56;
283#else
284#error please implement for this limb size.
285#endif
286 a->d[i++] = alimb;
287 }
288 if (p >= buffer) {
289#if BYTES_PER_MPI_LIMB == 4
290 alimb = *p--;
291 if (p >= buffer)
292 alimb |= (mpi_limb_t) *p-- << 8;
293 if (p >= buffer)
294 alimb |= (mpi_limb_t) *p-- << 16;
295 if (p >= buffer)
296 alimb |= (mpi_limb_t) *p-- << 24;
297#elif BYTES_PER_MPI_LIMB == 8
298 alimb = (mpi_limb_t) *p--;
299 if (p >= buffer)
300 alimb |= (mpi_limb_t) *p-- << 8;
301 if (p >= buffer)
302 alimb |= (mpi_limb_t) *p-- << 16;
303 if (p >= buffer)
304 alimb |= (mpi_limb_t) *p-- << 24;
305 if (p >= buffer)
306 alimb |= (mpi_limb_t) *p-- << 32;
307 if (p >= buffer)
308 alimb |= (mpi_limb_t) *p-- << 40;
309 if (p >= buffer)
310 alimb |= (mpi_limb_t) *p-- << 48;
311 if (p >= buffer)
312 alimb |= (mpi_limb_t) *p-- << 56;
313#else
314#error please implement for this limb size.
315#endif
316 a->d[i++] = alimb;
317 }
318 a->nlimbs = i;
319
320 if (i != nlimbs) {
321 pr_emerg("MPI: mpi_set_buffer: Assertion failed (%d != %d)", i,
322 nlimbs);
323 BUG();
324 }
325 return 0;
326}
327EXPORT_SYMBOL_GPL(mpi_set_buffer);
328
329/** 232/**
330 * mpi_write_to_sgl() - Funnction exports MPI to an sgl (msb first) 233 * mpi_write_to_sgl() - Funnction exports MPI to an sgl (msb first)
331 * 234 *
@@ -335,16 +238,13 @@ EXPORT_SYMBOL_GPL(mpi_set_buffer);
335 * @a: a multi precision integer 238 * @a: a multi precision integer
336 * @sgl: scatterlist to write to. Needs to be at least 239 * @sgl: scatterlist to write to. Needs to be at least
337 * mpi_get_size(a) long. 240 * mpi_get_size(a) long.
338 * @nbytes: in/out param - it has the be set to the maximum number of 241 * @nbytes: the number of bytes to write. Leading bytes will be
339 * bytes that can be written to sgl. This has to be at least 242 * filled with zero.
340 * the size of the integer a. On return it receives the actual
341 * length of the data written on success or the data that would
342 * be written if buffer was too small.
343 * @sign: if not NULL, it will be set to the sign of a. 243 * @sign: if not NULL, it will be set to the sign of a.
344 * 244 *
345 * Return: 0 on success or error code in case of error 245 * Return: 0 on success or error code in case of error
346 */ 246 */
347int mpi_write_to_sgl(MPI a, struct scatterlist *sgl, unsigned *nbytes, 247int mpi_write_to_sgl(MPI a, struct scatterlist *sgl, unsigned nbytes,
348 int *sign) 248 int *sign)
349{ 249{
350 u8 *p, *p2; 250 u8 *p, *p2;
@@ -356,55 +256,60 @@ int mpi_write_to_sgl(MPI a, struct scatterlist *sgl, unsigned *nbytes,
356#error please implement for this limb size. 256#error please implement for this limb size.
357#endif 257#endif
358 unsigned int n = mpi_get_size(a); 258 unsigned int n = mpi_get_size(a);
359 int i, x, y = 0, lzeros, buf_len; 259 struct sg_mapping_iter miter;
360 260 int i, x, buf_len;
361 if (!nbytes) 261 int nents;
362 return -EINVAL;
363 262
364 if (sign) 263 if (sign)
365 *sign = a->sign; 264 *sign = a->sign;
366 265
367 lzeros = count_lzeros(a); 266 if (nbytes < n)
368
369 if (*nbytes < n - lzeros) {
370 *nbytes = n - lzeros;
371 return -EOVERFLOW; 267 return -EOVERFLOW;
372 }
373 268
374 *nbytes = n - lzeros; 269 nents = sg_nents_for_len(sgl, nbytes);
375 buf_len = sgl->length; 270 if (nents < 0)
376 p2 = sg_virt(sgl); 271 return -EINVAL;
377 272
378 for (i = a->nlimbs - 1 - lzeros / BYTES_PER_MPI_LIMB, 273 sg_miter_start(&miter, sgl, nents, SG_MITER_ATOMIC | SG_MITER_TO_SG);
379 lzeros %= BYTES_PER_MPI_LIMB; 274 sg_miter_next(&miter);
380 i >= 0; i--) { 275 buf_len = miter.length;
276 p2 = miter.addr;
277
278 while (nbytes > n) {
279 i = min_t(unsigned, nbytes - n, buf_len);
280 memset(p2, 0, i);
281 p2 += i;
282 nbytes -= i;
283
284 buf_len -= i;
285 if (!buf_len) {
286 sg_miter_next(&miter);
287 buf_len = miter.length;
288 p2 = miter.addr;
289 }
290 }
291
292 for (i = a->nlimbs - 1; i >= 0; i--) {
381#if BYTES_PER_MPI_LIMB == 4 293#if BYTES_PER_MPI_LIMB == 4
382 alimb = cpu_to_be32(a->d[i]); 294 alimb = a->d[i] ? cpu_to_be32(a->d[i]) : 0;
383#elif BYTES_PER_MPI_LIMB == 8 295#elif BYTES_PER_MPI_LIMB == 8
384 alimb = cpu_to_be64(a->d[i]); 296 alimb = a->d[i] ? cpu_to_be64(a->d[i]) : 0;
385#else 297#else
386#error please implement for this limb size. 298#error please implement for this limb size.
387#endif 299#endif
388 if (lzeros) { 300 p = (u8 *)&alimb;
389 y = lzeros;
390 lzeros = 0;
391 }
392 301
393 p = (u8 *)&alimb + y; 302 for (x = 0; x < sizeof(alimb); x++) {
394
395 for (x = 0; x < sizeof(alimb) - y; x++) {
396 if (!buf_len) {
397 sgl = sg_next(sgl);
398 if (!sgl)
399 return -EINVAL;
400 buf_len = sgl->length;
401 p2 = sg_virt(sgl);
402 }
403 *p2++ = *p++; 303 *p2++ = *p++;
404 buf_len--; 304 if (!--buf_len) {
305 sg_miter_next(&miter);
306 buf_len = miter.length;
307 p2 = miter.addr;
308 }
405 } 309 }
406 y = 0;
407 } 310 }
311
312 sg_miter_stop(&miter);
408 return 0; 313 return 0;
409} 314}
410EXPORT_SYMBOL_GPL(mpi_write_to_sgl); 315EXPORT_SYMBOL_GPL(mpi_write_to_sgl);
@@ -424,19 +329,23 @@ EXPORT_SYMBOL_GPL(mpi_write_to_sgl);
424 */ 329 */
425MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int nbytes) 330MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int nbytes)
426{ 331{
427 struct scatterlist *sg; 332 struct sg_mapping_iter miter;
428 int x, i, j, z, lzeros, ents;
429 unsigned int nbits, nlimbs; 333 unsigned int nbits, nlimbs;
334 int x, j, z, lzeros, ents;
335 unsigned int len;
336 const u8 *buff;
430 mpi_limb_t a; 337 mpi_limb_t a;
431 MPI val = NULL; 338 MPI val = NULL;
432 339
433 lzeros = 0; 340 ents = sg_nents_for_len(sgl, nbytes);
434 ents = sg_nents(sgl); 341 if (ents < 0)
342 return NULL;
435 343
436 for_each_sg(sgl, sg, ents, i) { 344 sg_miter_start(&miter, sgl, ents, SG_MITER_ATOMIC | SG_MITER_FROM_SG);
437 const u8 *buff = sg_virt(sg);
438 int len = sg->length;
439 345
346 lzeros = 0;
347 len = 0;
348 while (nbytes > 0) {
440 while (len && !*buff) { 349 while (len && !*buff) {
441 lzeros++; 350 lzeros++;
442 len--; 351 len--;
@@ -446,12 +355,14 @@ MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int nbytes)
446 if (len && *buff) 355 if (len && *buff)
447 break; 356 break;
448 357
449 ents--; 358 sg_miter_next(&miter);
359 buff = miter.addr;
360 len = miter.length;
361
450 nbytes -= lzeros; 362 nbytes -= lzeros;
451 lzeros = 0; 363 lzeros = 0;
452 } 364 }
453 365
454 sgl = sg;
455 nbytes -= lzeros; 366 nbytes -= lzeros;
456 nbits = nbytes * 8; 367 nbits = nbytes * 8;
457 if (nbits > MAX_EXTERN_MPI_BITS) { 368 if (nbits > MAX_EXTERN_MPI_BITS) {
@@ -460,8 +371,7 @@ MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int nbytes)
460 } 371 }
461 372
462 if (nbytes > 0) 373 if (nbytes > 0)
463 nbits -= count_leading_zeros(*(u8 *)(sg_virt(sgl) + lzeros)) - 374 nbits -= count_leading_zeros(*buff) - (BITS_PER_LONG - 8);
464 (BITS_PER_LONG - 8);
465 375
466 nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB); 376 nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB);
467 val = mpi_alloc(nlimbs); 377 val = mpi_alloc(nlimbs);
@@ -480,21 +390,24 @@ MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int nbytes)
480 z = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; 390 z = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
481 z %= BYTES_PER_MPI_LIMB; 391 z %= BYTES_PER_MPI_LIMB;
482 392
483 for_each_sg(sgl, sg, ents, i) { 393 for (;;) {
484 const u8 *buffer = sg_virt(sg) + lzeros;
485 int len = sg->length - lzeros;
486
487 for (x = 0; x < len; x++) { 394 for (x = 0; x < len; x++) {
488 a <<= 8; 395 a <<= 8;
489 a |= *buffer++; 396 a |= *buff++;
490 if (((z + x + 1) % BYTES_PER_MPI_LIMB) == 0) { 397 if (((z + x + 1) % BYTES_PER_MPI_LIMB) == 0) {
491 val->d[j--] = a; 398 val->d[j--] = a;
492 a = 0; 399 a = 0;
493 } 400 }
494 } 401 }
495 z += x; 402 z += x;
496 lzeros = 0; 403
404 if (!sg_miter_next(&miter))
405 break;
406
407 buff = miter.addr;
408 len = miter.length;
497 } 409 }
410
498 return val; 411 return val;
499} 412}
500EXPORT_SYMBOL_GPL(mpi_read_raw_from_sgl); 413EXPORT_SYMBOL_GPL(mpi_read_raw_from_sgl);