@@ -319,3 +319,199 @@ int mpi_set_buffer(MPI a, const void *xbuffer, unsigned nbytes, int sign)
319
319
return 0 ;
320
320
}
321
321
EXPORT_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
+ */
340
+ int 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
+ }
419
+ EXPORT_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
+ */
434
+ MPI 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
+ }
517
+ EXPORT_SYMBOL_GPL (mpi_read_raw_from_sgl );
0 commit comments