diff options
Diffstat (limited to 'lib/mpi/mpicoder.c')
| -rw-r--r-- | lib/mpi/mpicoder.c | 247 |
1 files changed, 80 insertions, 167 deletions
diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c index 747606f9e4a3..5a0f75a3bf01 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); | |||
| 82 | MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread) | 81 | MPI 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 | ||
| 127 | leave: | 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 | } |
| 131 | EXPORT_SYMBOL_GPL(mpi_read_from_buffer); | 110 | EXPORT_SYMBOL_GPL(mpi_read_from_buffer); |
| @@ -250,82 +229,6 @@ void *mpi_get_buffer(MPI a, unsigned *nbytes, int *sign) | |||
| 250 | } | 229 | } |
| 251 | EXPORT_SYMBOL_GPL(mpi_get_buffer); | 230 | EXPORT_SYMBOL_GPL(mpi_get_buffer); |
| 252 | 231 | ||
| 253 | /**************** | ||
| 254 | * Use BUFFER to update MPI. | ||
| 255 | */ | ||
| 256 | int 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 | } | ||
| 327 | EXPORT_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 | */ |
| 347 | int mpi_write_to_sgl(MPI a, struct scatterlist *sgl, unsigned *nbytes, | 247 | int 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 | |||
| 393 | p = (u8 *)&alimb + y; | ||
| 394 | 301 | ||
| 395 | for (x = 0; x < sizeof(alimb) - y; x++) { | 302 | for (x = 0; x < sizeof(alimb); 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 | } |
| 410 | EXPORT_SYMBOL_GPL(mpi_write_to_sgl); | 315 | EXPORT_SYMBOL_GPL(mpi_write_to_sgl); |
| @@ -424,19 +329,23 @@ EXPORT_SYMBOL_GPL(mpi_write_to_sgl); | |||
| 424 | */ | 329 | */ |
| 425 | 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) |
| 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,17 @@ 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; | 366 | miter.consumed = lzeros; |
| 367 | sg_miter_stop(&miter); | ||
| 368 | |||
| 455 | nbytes -= lzeros; | 369 | nbytes -= lzeros; |
| 456 | nbits = nbytes * 8; | 370 | nbits = nbytes * 8; |
| 457 | if (nbits > MAX_EXTERN_MPI_BITS) { | 371 | if (nbits > MAX_EXTERN_MPI_BITS) { |
| @@ -460,8 +374,7 @@ MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int nbytes) | |||
| 460 | } | 374 | } |
| 461 | 375 | ||
| 462 | if (nbytes > 0) | 376 | if (nbytes > 0) |
| 463 | nbits -= count_leading_zeros(*(u8 *)(sg_virt(sgl) + lzeros)) - | 377 | nbits -= count_leading_zeros(*buff) - (BITS_PER_LONG - 8); |
| 464 | (BITS_PER_LONG - 8); | ||
| 465 | 378 | ||
| 466 | nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB); | 379 | nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB); |
| 467 | val = mpi_alloc(nlimbs); | 380 | val = mpi_alloc(nlimbs); |
| @@ -480,21 +393,21 @@ MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int nbytes) | |||
| 480 | z = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; | 393 | z = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; |
| 481 | z %= BYTES_PER_MPI_LIMB; | 394 | z %= BYTES_PER_MPI_LIMB; |
| 482 | 395 | ||
| 483 | for_each_sg(sgl, sg, ents, i) { | 396 | while (sg_miter_next(&miter)) { |
| 484 | const u8 *buffer = sg_virt(sg) + lzeros; | 397 | buff = miter.addr; |
| 485 | int len = sg->length - lzeros; | 398 | len = miter.length; |
| 486 | 399 | ||
| 487 | for (x = 0; x < len; x++) { | 400 | for (x = 0; x < len; x++) { |
| 488 | a <<= 8; | 401 | a <<= 8; |
| 489 | a |= *buffer++; | 402 | a |= *buff++; |
| 490 | if (((z + x + 1) % BYTES_PER_MPI_LIMB) == 0) { | 403 | if (((z + x + 1) % BYTES_PER_MPI_LIMB) == 0) { |
| 491 | val->d[j--] = a; | 404 | val->d[j--] = a; |
| 492 | a = 0; | 405 | a = 0; |
| 493 | } | 406 | } |
| 494 | } | 407 | } |
| 495 | z += x; | 408 | z += x; |
| 496 | lzeros = 0; | ||
| 497 | } | 409 | } |
| 410 | |||
| 498 | return val; | 411 | return val; |
| 499 | } | 412 | } |
| 500 | EXPORT_SYMBOL_GPL(mpi_read_raw_from_sgl); | 413 | EXPORT_SYMBOL_GPL(mpi_read_raw_from_sgl); |
