aboutsummaryrefslogtreecommitdiffstats
path: root/lib/mpi
diff options
context:
space:
mode:
authorTadeusz Struk <tadeusz.struk@intel.com>2015-10-08 12:26:50 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2015-10-14 10:23:00 -0400
commit2d4d1eea540b27c72488fd1914674c42473d53df (patch)
tree104068ce8d5e084fcb2ed7eb0fd626c15b4311f0 /lib/mpi
parent9ad92bdff7062d9925754607f5a92b4f651fc7d3 (diff)
lib/mpi: Add mpi sgl helpers
Add mpi_read_raw_from_sgl and mpi_write_to_sgl helpers. Signed-off-by: Tadeusz Struk <tadeusz.struk@intel.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'lib/mpi')
-rw-r--r--lib/mpi/mpicoder.c196
1 files changed, 196 insertions, 0 deletions
diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c
index 95c52a95259e..c20ef27ad876 100644
--- a/lib/mpi/mpicoder.c
+++ b/lib/mpi/mpicoder.c
@@ -319,3 +319,199 @@ 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
452 if (len && *buff)
453 break;
454
455 ents--;
456 lzeros = 0;
457 }
458
459 sgl = sg;
460
461 if (!ents)
462 nbytes = 0;
463 else
464 nbytes = len - lzeros;
465
466 nbits = nbytes * 8;
467 if (nbits > MAX_EXTERN_MPI_BITS) {
468 pr_info("MPI: mpi too large (%u bits)\n", nbits);
469 return NULL;
470 }
471
472 if (nbytes > 0)
473 nbits -= count_leading_zeros(*(u8 *)(sg_virt(sgl) + lzeros));
474 else
475 nbits = 0;
476
477 nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB);
478 val = mpi_alloc(nlimbs);
479 if (!val)
480 return NULL;
481
482 val->nbits = nbits;
483 val->sign = 0;
484 val->nlimbs = nlimbs;
485
486 if (nbytes == 0)
487 return val;
488
489 j = nlimbs - 1;
490 a = 0;
491 z = 0;
492 x = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
493 x %= BYTES_PER_MPI_LIMB;
494
495 for_each_sg(sgl, sg, ents, i) {
496 const u8 *buffer = sg_virt(sg) + lzeros;
497 int len = sg->length - lzeros;
498 int buf_shift = x;
499
500 if (sg_is_last(sg) && (len % BYTES_PER_MPI_LIMB))
501 len += BYTES_PER_MPI_LIMB - (len % BYTES_PER_MPI_LIMB);
502
503 for (; x < len + buf_shift; x++) {
504 a <<= 8;
505 a |= *buffer++;
506 if (((z + x + 1) % BYTES_PER_MPI_LIMB) == 0) {
507 val->d[j--] = a;
508 a = 0;
509 }
510 }
511 z += x;
512 x = 0;
513 lzeros = 0;
514 }
515 return val;
516}
517EXPORT_SYMBOL_GPL(mpi_read_raw_from_sgl);