diff options
Diffstat (limited to 'lib/mpi/mpicoder.c')
-rw-r--r-- | lib/mpi/mpicoder.c | 86 |
1 files changed, 50 insertions, 36 deletions
diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c index 7150e5c23604..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 | ||
@@ -255,7 +256,9 @@ int mpi_write_to_sgl(MPI a, struct scatterlist *sgl, unsigned nbytes, | |||
255 | #error please implement for this limb size. | 256 | #error please implement for this limb size. |
256 | #endif | 257 | #endif |
257 | unsigned int n = mpi_get_size(a); | 258 | unsigned int n = mpi_get_size(a); |
259 | struct sg_mapping_iter miter; | ||
258 | int i, x, buf_len; | 260 | int i, x, buf_len; |
261 | int nents; | ||
259 | 262 | ||
260 | if (sign) | 263 | if (sign) |
261 | *sign = a->sign; | 264 | *sign = a->sign; |
@@ -263,23 +266,27 @@ int mpi_write_to_sgl(MPI a, struct scatterlist *sgl, unsigned nbytes, | |||
263 | if (nbytes < n) | 266 | if (nbytes < n) |
264 | return -EOVERFLOW; | 267 | return -EOVERFLOW; |
265 | 268 | ||
266 | buf_len = sgl->length; | 269 | nents = sg_nents_for_len(sgl, nbytes); |
267 | p2 = sg_virt(sgl); | 270 | if (nents < 0) |
271 | return -EINVAL; | ||
268 | 272 | ||
269 | while (nbytes > n) { | 273 | sg_miter_start(&miter, sgl, nents, SG_MITER_ATOMIC | SG_MITER_TO_SG); |
270 | if (!buf_len) { | 274 | sg_miter_next(&miter); |
271 | sgl = sg_next(sgl); | 275 | buf_len = miter.length; |
272 | if (!sgl) | 276 | p2 = miter.addr; |
273 | return -EINVAL; | ||
274 | buf_len = sgl->length; | ||
275 | p2 = sg_virt(sgl); | ||
276 | } | ||
277 | 277 | ||
278 | while (nbytes > n) { | ||
278 | i = min_t(unsigned, nbytes - n, buf_len); | 279 | i = min_t(unsigned, nbytes - n, buf_len); |
279 | memset(p2, 0, i); | 280 | memset(p2, 0, i); |
280 | p2 += i; | 281 | p2 += i; |
281 | buf_len -= i; | ||
282 | nbytes -= 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 | } | ||
283 | } | 290 | } |
284 | 291 | ||
285 | for (i = a->nlimbs - 1; i >= 0; i--) { | 292 | for (i = a->nlimbs - 1; i >= 0; i--) { |
@@ -293,17 +300,16 @@ int mpi_write_to_sgl(MPI a, struct scatterlist *sgl, unsigned nbytes, | |||
293 | p = (u8 *)&alimb; | 300 | p = (u8 *)&alimb; |
294 | 301 | ||
295 | for (x = 0; x < sizeof(alimb); x++) { | 302 | for (x = 0; x < sizeof(alimb); x++) { |
296 | if (!buf_len) { | ||
297 | sgl = sg_next(sgl); | ||
298 | if (!sgl) | ||
299 | return -EINVAL; | ||
300 | buf_len = sgl->length; | ||
301 | p2 = sg_virt(sgl); | ||
302 | } | ||
303 | *p2++ = *p++; | 303 | *p2++ = *p++; |
304 | buf_len--; | 304 | if (!--buf_len) { |
305 | sg_miter_next(&miter); | ||
306 | buf_len = miter.length; | ||
307 | p2 = miter.addr; | ||
308 | } | ||
305 | } | 309 | } |
306 | } | 310 | } |
311 | |||
312 | sg_miter_stop(&miter); | ||
307 | return 0; | 313 | return 0; |
308 | } | 314 | } |
309 | EXPORT_SYMBOL_GPL(mpi_write_to_sgl); | 315 | EXPORT_SYMBOL_GPL(mpi_write_to_sgl); |
@@ -323,19 +329,23 @@ EXPORT_SYMBOL_GPL(mpi_write_to_sgl); | |||
323 | */ | 329 | */ |
324 | MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int nbytes) | 330 | MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int nbytes) |
325 | { | 331 | { |
326 | struct scatterlist *sg; | 332 | struct sg_mapping_iter miter; |
327 | int x, i, j, z, lzeros, ents; | ||
328 | unsigned int nbits, nlimbs; | 333 | unsigned int nbits, nlimbs; |
334 | int x, j, z, lzeros, ents; | ||
335 | unsigned int len; | ||
336 | const u8 *buff; | ||
329 | mpi_limb_t a; | 337 | mpi_limb_t a; |
330 | MPI val = NULL; | 338 | MPI val = NULL; |
331 | 339 | ||
332 | lzeros = 0; | 340 | ents = sg_nents_for_len(sgl, nbytes); |
333 | ents = sg_nents(sgl); | 341 | if (ents < 0) |
342 | return NULL; | ||
334 | 343 | ||
335 | for_each_sg(sgl, sg, ents, i) { | 344 | sg_miter_start(&miter, sgl, ents, SG_MITER_ATOMIC | SG_MITER_FROM_SG); |
336 | const u8 *buff = sg_virt(sg); | ||
337 | int len = sg->length; | ||
338 | 345 | ||
346 | lzeros = 0; | ||
347 | len = 0; | ||
348 | while (nbytes > 0) { | ||
339 | while (len && !*buff) { | 349 | while (len && !*buff) { |
340 | lzeros++; | 350 | lzeros++; |
341 | len--; | 351 | len--; |
@@ -345,12 +355,14 @@ MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int nbytes) | |||
345 | if (len && *buff) | 355 | if (len && *buff) |
346 | break; | 356 | break; |
347 | 357 | ||
348 | ents--; | 358 | sg_miter_next(&miter); |
359 | buff = miter.addr; | ||
360 | len = miter.length; | ||
361 | |||
349 | nbytes -= lzeros; | 362 | nbytes -= lzeros; |
350 | lzeros = 0; | 363 | lzeros = 0; |
351 | } | 364 | } |
352 | 365 | ||
353 | sgl = sg; | ||
354 | nbytes -= lzeros; | 366 | nbytes -= lzeros; |
355 | nbits = nbytes * 8; | 367 | nbits = nbytes * 8; |
356 | if (nbits > MAX_EXTERN_MPI_BITS) { | 368 | if (nbits > MAX_EXTERN_MPI_BITS) { |
@@ -359,8 +371,7 @@ MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int nbytes) | |||
359 | } | 371 | } |
360 | 372 | ||
361 | if (nbytes > 0) | 373 | if (nbytes > 0) |
362 | nbits -= count_leading_zeros(*(u8 *)(sg_virt(sgl) + lzeros)) - | 374 | nbits -= count_leading_zeros(*buff) - (BITS_PER_LONG - 8); |
363 | (BITS_PER_LONG - 8); | ||
364 | 375 | ||
365 | nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB); | 376 | nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB); |
366 | val = mpi_alloc(nlimbs); | 377 | val = mpi_alloc(nlimbs); |
@@ -379,21 +390,24 @@ MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int nbytes) | |||
379 | z = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; | 390 | z = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; |
380 | z %= BYTES_PER_MPI_LIMB; | 391 | z %= BYTES_PER_MPI_LIMB; |
381 | 392 | ||
382 | for_each_sg(sgl, sg, ents, i) { | 393 | for (;;) { |
383 | const u8 *buffer = sg_virt(sg) + lzeros; | ||
384 | int len = sg->length - lzeros; | ||
385 | |||
386 | for (x = 0; x < len; x++) { | 394 | for (x = 0; x < len; x++) { |
387 | a <<= 8; | 395 | a <<= 8; |
388 | a |= *buffer++; | 396 | a |= *buff++; |
389 | if (((z + x + 1) % BYTES_PER_MPI_LIMB) == 0) { | 397 | if (((z + x + 1) % BYTES_PER_MPI_LIMB) == 0) { |
390 | val->d[j--] = a; | 398 | val->d[j--] = a; |
391 | a = 0; | 399 | a = 0; |
392 | } | 400 | } |
393 | } | 401 | } |
394 | z += x; | 402 | z += x; |
395 | lzeros = 0; | 403 | |
404 | if (!sg_miter_next(&miter)) | ||
405 | break; | ||
406 | |||
407 | buff = miter.addr; | ||
408 | len = miter.length; | ||
396 | } | 409 | } |
410 | |||
397 | return val; | 411 | return val; |
398 | } | 412 | } |
399 | EXPORT_SYMBOL_GPL(mpi_read_raw_from_sgl); | 413 | EXPORT_SYMBOL_GPL(mpi_read_raw_from_sgl); |