aboutsummaryrefslogtreecommitdiffstats
path: root/lib/mpi/mpicoder.c
diff options
context:
space:
mode:
authorChris Zankel <chris@zankel.net>2016-01-21 00:16:13 -0500
committerChris Zankel <chris@zankel.net>2016-01-21 00:16:13 -0500
commitd1208404dd477c142680437137c9996b95bfd508 (patch)
tree0cba53f59f487c0de2b1a0d9fb1b11ae27de96ec /lib/mpi/mpicoder.c
parentafaa7c542cc9c4d8a99ba252a8ea5e8bc7c897e2 (diff)
parentafd2ff9b7e1b367172f18ba7f693dfb62bdcb2dc (diff)
Merge tag 'v4.4'
Linux 4.4
Diffstat (limited to 'lib/mpi/mpicoder.c')
-rw-r--r--lib/mpi/mpicoder.c201
1 files changed, 200 insertions, 1 deletions
diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c
index 95c52a95259e..3db76b8c1115 100644
--- a/lib/mpi/mpicoder.c
+++ b/lib/mpi/mpicoder.c
@@ -19,7 +19,7 @@
19 */ 19 */
20 20
21#include <linux/bitops.h> 21#include <linux/bitops.h>
22#include <asm-generic/bitops/count_zeros.h> 22#include <linux/count_zeros.h>
23#include "mpi-internal.h" 23#include "mpi-internal.h"
24 24
25#define MAX_EXTERN_MPI_BITS 16384 25#define MAX_EXTERN_MPI_BITS 16384
@@ -319,3 +319,202 @@ int mpi_set_buffer(MPI a, const void *xbuffer, unsigned nbytes, int sign)
319 return 0; 319 return 0;
320} 320}
321EXPORT_SYMBOL_GPL(mpi_set_buffer); 321EXPORT_SYMBOL_GPL(mpi_set_buffer);
322
323/**
324 * mpi_write_to_sgl() - Funnction exports MPI to an sgl (msb first)
325 *
326 * This function works in the same way as the mpi_read_buffer, but it
327 * takes an sgl instead of u8 * buf.
328 *
329 * @a: a multi precision integer
330 * @sgl: scatterlist to write to. Needs to be at least
331 * mpi_get_size(a) long.
332 * @nbytes: in/out param - it has the be set to the maximum number of
333 * bytes that can be written to sgl. This has to be at least
334 * the size of the integer a. On return it receives the actual
335 * length of the data written.
336 * @sign: if not NULL, it will be set to the sign of a.
337 *
338 * Return: 0 on success or error code in case of error
339 */
340int mpi_write_to_sgl(MPI a, struct scatterlist *sgl, unsigned *nbytes,
341 int *sign)
342{
343 u8 *p, *p2;
344 mpi_limb_t alimb, alimb2;
345 unsigned int n = mpi_get_size(a);
346 int i, x, y = 0, lzeros = 0, buf_len;
347
348 if (!nbytes || *nbytes < n)
349 return -EINVAL;
350
351 if (sign)
352 *sign = a->sign;
353
354 p = (void *)&a->d[a->nlimbs] - 1;
355
356 for (i = a->nlimbs * sizeof(alimb) - 1; i >= 0; i--, p--) {
357 if (!*p)
358 lzeros++;
359 else
360 break;
361 }
362
363 *nbytes = n - lzeros;
364 buf_len = sgl->length;
365 p2 = sg_virt(sgl);
366
367 for (i = a->nlimbs - 1; i >= 0; i--) {
368 alimb = a->d[i];
369 p = (u8 *)&alimb2;
370#if BYTES_PER_MPI_LIMB == 4
371 *p++ = alimb >> 24;
372 *p++ = alimb >> 16;
373 *p++ = alimb >> 8;
374 *p++ = alimb;
375#elif BYTES_PER_MPI_LIMB == 8
376 *p++ = alimb >> 56;
377 *p++ = alimb >> 48;
378 *p++ = alimb >> 40;
379 *p++ = alimb >> 32;
380 *p++ = alimb >> 24;
381 *p++ = alimb >> 16;
382 *p++ = alimb >> 8;
383 *p++ = alimb;
384#else
385#error please implement for this limb size.
386#endif
387 if (lzeros > 0) {
388 if (lzeros >= sizeof(alimb)) {
389 p -= sizeof(alimb);
390 continue;
391 } else {
392 mpi_limb_t *limb1 = (void *)p - sizeof(alimb);
393 mpi_limb_t *limb2 = (void *)p - sizeof(alimb)
394 + lzeros;
395 *limb1 = *limb2;
396 p -= lzeros;
397 y = lzeros;
398 }
399 lzeros -= sizeof(alimb);
400 }
401
402 p = p - (sizeof(alimb) - y);
403
404 for (x = 0; x < sizeof(alimb) - y; x++) {
405 if (!buf_len) {
406 sgl = sg_next(sgl);
407 if (!sgl)
408 return -EINVAL;
409 buf_len = sgl->length;
410 p2 = sg_virt(sgl);
411 }
412 *p2++ = *p++;
413 buf_len--;
414 }
415 y = 0;
416 }
417 return 0;
418}
419EXPORT_SYMBOL_GPL(mpi_write_to_sgl);
420
421/*
422 * mpi_read_raw_from_sgl() - Function allocates an MPI and populates it with
423 * data from the sgl
424 *
425 * This function works in the same way as the mpi_read_raw_data, but it
426 * takes an sgl instead of void * buffer. i.e. it allocates
427 * a new MPI and reads the content of the sgl to the MPI.
428 *
429 * @sgl: scatterlist to read from
430 * @len: number of bytes to read
431 *
432 * Return: Pointer to a new MPI or NULL on error
433 */
434MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int len)
435{
436 struct scatterlist *sg;
437 int x, i, j, z, lzeros, ents;
438 unsigned int nbits, nlimbs, nbytes;
439 mpi_limb_t a;
440 MPI val = NULL;
441
442 lzeros = 0;
443 ents = sg_nents(sgl);
444
445 for_each_sg(sgl, sg, ents, i) {
446 const u8 *buff = sg_virt(sg);
447 int len = sg->length;
448
449 while (len && !*buff) {
450 lzeros++;
451 len--;
452 buff++;
453 }
454
455 if (len && *buff)
456 break;
457
458 ents--;
459 lzeros = 0;
460 }
461
462 sgl = sg;
463
464 if (!ents)
465 nbytes = 0;
466 else
467 nbytes = len - lzeros;
468
469 nbits = nbytes * 8;
470 if (nbits > MAX_EXTERN_MPI_BITS) {
471 pr_info("MPI: mpi too large (%u bits)\n", nbits);
472 return NULL;
473 }
474
475 if (nbytes > 0)
476 nbits -= count_leading_zeros(*(u8 *)(sg_virt(sgl) + lzeros));
477 else
478 nbits = 0;
479
480 nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB);
481 val = mpi_alloc(nlimbs);
482 if (!val)
483 return NULL;
484
485 val->nbits = nbits;
486 val->sign = 0;
487 val->nlimbs = nlimbs;
488
489 if (nbytes == 0)
490 return val;
491
492 j = nlimbs - 1;
493 a = 0;
494 z = 0;
495 x = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
496 x %= BYTES_PER_MPI_LIMB;
497
498 for_each_sg(sgl, sg, ents, i) {
499 const u8 *buffer = sg_virt(sg) + lzeros;
500 int len = sg->length - lzeros;
501 int buf_shift = x;
502
503 if (sg_is_last(sg) && (len % BYTES_PER_MPI_LIMB))
504 len += BYTES_PER_MPI_LIMB - (len % BYTES_PER_MPI_LIMB);
505
506 for (; x < len + buf_shift; x++) {
507 a <<= 8;
508 a |= *buffer++;
509 if (((z + x + 1) % BYTES_PER_MPI_LIMB) == 0) {
510 val->d[j--] = a;
511 a = 0;
512 }
513 }
514 z += x;
515 x = 0;
516 lzeros = 0;
517 }
518 return val;
519}
520EXPORT_SYMBOL_GPL(mpi_read_raw_from_sgl);