at v4.6 12 kB view raw
1/* mpicoder.c - Coder for the external representation of MPIs 2 * Copyright (C) 1998, 1999 Free Software Foundation, Inc. 3 * 4 * This file is part of GnuPG. 5 * 6 * GnuPG is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * GnuPG is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 19 */ 20 21#include <linux/bitops.h> 22#include <linux/count_zeros.h> 23#include "mpi-internal.h" 24 25#define MAX_EXTERN_MPI_BITS 16384 26 27/** 28 * mpi_read_raw_data - Read a raw byte stream as a positive integer 29 * @xbuffer: The data to read 30 * @nbytes: The amount of data to read 31 */ 32MPI mpi_read_raw_data(const void *xbuffer, size_t nbytes) 33{ 34 const uint8_t *buffer = xbuffer; 35 int i, j; 36 unsigned nbits, nlimbs; 37 mpi_limb_t a; 38 MPI val = NULL; 39 40 while (nbytes > 0 && buffer[0] == 0) { 41 buffer++; 42 nbytes--; 43 } 44 45 nbits = nbytes * 8; 46 if (nbits > MAX_EXTERN_MPI_BITS) { 47 pr_info("MPI: mpi too large (%u bits)\n", nbits); 48 return NULL; 49 } 50 if (nbytes > 0) 51 nbits -= count_leading_zeros(buffer[0]); 52 else 53 nbits = 0; 54 55 nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB); 56 val = mpi_alloc(nlimbs); 57 if (!val) 58 return NULL; 59 val->nbits = nbits; 60 val->sign = 0; 61 val->nlimbs = nlimbs; 62 63 if (nbytes > 0) { 64 i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; 65 i %= BYTES_PER_MPI_LIMB; 66 for (j = nlimbs; j > 0; j--) { 67 a = 0; 68 for (; i < BYTES_PER_MPI_LIMB; i++) { 69 a <<= 8; 70 a |= *buffer++; 71 } 72 i = 0; 73 val->d[j - 1] = a; 74 } 75 } 76 return val; 77} 78EXPORT_SYMBOL_GPL(mpi_read_raw_data); 79 80MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread) 81{ 82 const uint8_t *buffer = xbuffer; 83 int i, j; 84 unsigned nbits, nbytes, nlimbs, nread = 0; 85 mpi_limb_t a; 86 MPI val = NULL; 87 88 if (*ret_nread < 2) 89 goto leave; 90 nbits = buffer[0] << 8 | buffer[1]; 91 92 if (nbits > MAX_EXTERN_MPI_BITS) { 93 pr_info("MPI: mpi too large (%u bits)\n", nbits); 94 goto leave; 95 } 96 buffer += 2; 97 nread = 2; 98 99 nbytes = DIV_ROUND_UP(nbits, 8); 100 nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB); 101 val = mpi_alloc(nlimbs); 102 if (!val) 103 return NULL; 104 i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; 105 i %= BYTES_PER_MPI_LIMB; 106 val->nbits = nbits; 107 j = val->nlimbs = nlimbs; 108 val->sign = 0; 109 for (; j > 0; j--) { 110 a = 0; 111 for (; i < BYTES_PER_MPI_LIMB; i++) { 112 if (++nread > *ret_nread) { 113 printk 114 ("MPI: mpi larger than buffer nread=%d ret_nread=%d\n", 115 nread, *ret_nread); 116 goto leave; 117 } 118 a <<= 8; 119 a |= *buffer++; 120 } 121 i = 0; 122 val->d[j - 1] = a; 123 } 124 125leave: 126 *ret_nread = nread; 127 return val; 128} 129EXPORT_SYMBOL_GPL(mpi_read_from_buffer); 130 131static int count_lzeros(MPI a) 132{ 133 mpi_limb_t alimb; 134 int i, lzeros = 0; 135 136 for (i = a->nlimbs - 1; i >= 0; i--) { 137 alimb = a->d[i]; 138 if (alimb == 0) { 139 lzeros += sizeof(mpi_limb_t); 140 } else { 141 lzeros += count_leading_zeros(alimb) / 8; 142 break; 143 } 144 } 145 return lzeros; 146} 147 148/** 149 * mpi_read_buffer() - read MPI to a bufer provided by user (msb first) 150 * 151 * @a: a multi precision integer 152 * @buf: bufer to which the output will be written to. Needs to be at 153 * leaset mpi_get_size(a) long. 154 * @buf_len: size of the buf. 155 * @nbytes: receives the actual length of the data written on success and 156 * the data to-be-written on -EOVERFLOW in case buf_len was too 157 * small. 158 * @sign: if not NULL, it will be set to the sign of a. 159 * 160 * Return: 0 on success or error code in case of error 161 */ 162int mpi_read_buffer(MPI a, uint8_t *buf, unsigned buf_len, unsigned *nbytes, 163 int *sign) 164{ 165 uint8_t *p; 166 mpi_limb_t alimb; 167 unsigned int n = mpi_get_size(a); 168 int i, lzeros; 169 170 if (!buf || !nbytes) 171 return -EINVAL; 172 173 if (sign) 174 *sign = a->sign; 175 176 lzeros = count_lzeros(a); 177 178 if (buf_len < n - lzeros) { 179 *nbytes = n - lzeros; 180 return -EOVERFLOW; 181 } 182 183 p = buf; 184 *nbytes = n - lzeros; 185 186 for (i = a->nlimbs - 1; i >= 0; i--) { 187 alimb = a->d[i]; 188#if BYTES_PER_MPI_LIMB == 4 189 *p++ = alimb >> 24; 190 *p++ = alimb >> 16; 191 *p++ = alimb >> 8; 192 *p++ = alimb; 193#elif BYTES_PER_MPI_LIMB == 8 194 *p++ = alimb >> 56; 195 *p++ = alimb >> 48; 196 *p++ = alimb >> 40; 197 *p++ = alimb >> 32; 198 *p++ = alimb >> 24; 199 *p++ = alimb >> 16; 200 *p++ = alimb >> 8; 201 *p++ = alimb; 202#else 203#error please implement for this limb size. 204#endif 205 206 if (lzeros > 0) { 207 if (lzeros >= sizeof(alimb)) { 208 p -= sizeof(alimb); 209 } else { 210 mpi_limb_t *limb1 = (void *)p - sizeof(alimb); 211 mpi_limb_t *limb2 = (void *)p - sizeof(alimb) 212 + lzeros; 213 *limb1 = *limb2; 214 p -= lzeros; 215 } 216 lzeros -= sizeof(alimb); 217 } 218 } 219 return 0; 220} 221EXPORT_SYMBOL_GPL(mpi_read_buffer); 222 223/* 224 * mpi_get_buffer() - Returns an allocated buffer with the MPI (msb first). 225 * Caller must free the return string. 226 * This function does return a 0 byte buffer with nbytes set to zero if the 227 * value of A is zero. 228 * 229 * @a: a multi precision integer. 230 * @nbytes: receives the length of this buffer. 231 * @sign: if not NULL, it will be set to the sign of the a. 232 * 233 * Return: Pointer to MPI buffer or NULL on error 234 */ 235void *mpi_get_buffer(MPI a, unsigned *nbytes, int *sign) 236{ 237 uint8_t *buf; 238 unsigned int n; 239 int ret; 240 241 if (!nbytes) 242 return NULL; 243 244 n = mpi_get_size(a); 245 246 if (!n) 247 n++; 248 249 buf = kmalloc(n, GFP_KERNEL); 250 251 if (!buf) 252 return NULL; 253 254 ret = mpi_read_buffer(a, buf, n, nbytes, sign); 255 256 if (ret) { 257 kfree(buf); 258 return NULL; 259 } 260 return buf; 261} 262EXPORT_SYMBOL_GPL(mpi_get_buffer); 263 264/**************** 265 * Use BUFFER to update MPI. 266 */ 267int mpi_set_buffer(MPI a, const void *xbuffer, unsigned nbytes, int sign) 268{ 269 const uint8_t *buffer = xbuffer, *p; 270 mpi_limb_t alimb; 271 int nlimbs; 272 int i; 273 274 nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB); 275 if (RESIZE_IF_NEEDED(a, nlimbs) < 0) 276 return -ENOMEM; 277 a->sign = sign; 278 279 for (i = 0, p = buffer + nbytes - 1; p >= buffer + BYTES_PER_MPI_LIMB;) { 280#if BYTES_PER_MPI_LIMB == 4 281 alimb = (mpi_limb_t) *p--; 282 alimb |= (mpi_limb_t) *p-- << 8; 283 alimb |= (mpi_limb_t) *p-- << 16; 284 alimb |= (mpi_limb_t) *p-- << 24; 285#elif BYTES_PER_MPI_LIMB == 8 286 alimb = (mpi_limb_t) *p--; 287 alimb |= (mpi_limb_t) *p-- << 8; 288 alimb |= (mpi_limb_t) *p-- << 16; 289 alimb |= (mpi_limb_t) *p-- << 24; 290 alimb |= (mpi_limb_t) *p-- << 32; 291 alimb |= (mpi_limb_t) *p-- << 40; 292 alimb |= (mpi_limb_t) *p-- << 48; 293 alimb |= (mpi_limb_t) *p-- << 56; 294#else 295#error please implement for this limb size. 296#endif 297 a->d[i++] = alimb; 298 } 299 if (p >= buffer) { 300#if BYTES_PER_MPI_LIMB == 4 301 alimb = *p--; 302 if (p >= buffer) 303 alimb |= (mpi_limb_t) *p-- << 8; 304 if (p >= buffer) 305 alimb |= (mpi_limb_t) *p-- << 16; 306 if (p >= buffer) 307 alimb |= (mpi_limb_t) *p-- << 24; 308#elif BYTES_PER_MPI_LIMB == 8 309 alimb = (mpi_limb_t) *p--; 310 if (p >= buffer) 311 alimb |= (mpi_limb_t) *p-- << 8; 312 if (p >= buffer) 313 alimb |= (mpi_limb_t) *p-- << 16; 314 if (p >= buffer) 315 alimb |= (mpi_limb_t) *p-- << 24; 316 if (p >= buffer) 317 alimb |= (mpi_limb_t) *p-- << 32; 318 if (p >= buffer) 319 alimb |= (mpi_limb_t) *p-- << 40; 320 if (p >= buffer) 321 alimb |= (mpi_limb_t) *p-- << 48; 322 if (p >= buffer) 323 alimb |= (mpi_limb_t) *p-- << 56; 324#else 325#error please implement for this limb size. 326#endif 327 a->d[i++] = alimb; 328 } 329 a->nlimbs = i; 330 331 if (i != nlimbs) { 332 pr_emerg("MPI: mpi_set_buffer: Assertion failed (%d != %d)", i, 333 nlimbs); 334 BUG(); 335 } 336 return 0; 337} 338EXPORT_SYMBOL_GPL(mpi_set_buffer); 339 340/** 341 * mpi_write_to_sgl() - Funnction exports MPI to an sgl (msb first) 342 * 343 * This function works in the same way as the mpi_read_buffer, but it 344 * takes an sgl instead of u8 * buf. 345 * 346 * @a: a multi precision integer 347 * @sgl: scatterlist to write to. Needs to be at least 348 * mpi_get_size(a) long. 349 * @nbytes: in/out param - it has the be set to the maximum number of 350 * bytes that can be written to sgl. This has to be at least 351 * the size of the integer a. On return it receives the actual 352 * length of the data written on success or the data that would 353 * be written if buffer was too small. 354 * @sign: if not NULL, it will be set to the sign of a. 355 * 356 * Return: 0 on success or error code in case of error 357 */ 358int mpi_write_to_sgl(MPI a, struct scatterlist *sgl, unsigned *nbytes, 359 int *sign) 360{ 361 u8 *p, *p2; 362 mpi_limb_t alimb, alimb2; 363 unsigned int n = mpi_get_size(a); 364 int i, x, y = 0, lzeros, buf_len; 365 366 if (!nbytes) 367 return -EINVAL; 368 369 if (sign) 370 *sign = a->sign; 371 372 lzeros = count_lzeros(a); 373 374 if (*nbytes < n - lzeros) { 375 *nbytes = n - lzeros; 376 return -EOVERFLOW; 377 } 378 379 *nbytes = n - lzeros; 380 buf_len = sgl->length; 381 p2 = sg_virt(sgl); 382 383 for (i = a->nlimbs - 1; i >= 0; i--) { 384 alimb = a->d[i]; 385 p = (u8 *)&alimb2; 386#if BYTES_PER_MPI_LIMB == 4 387 *p++ = alimb >> 24; 388 *p++ = alimb >> 16; 389 *p++ = alimb >> 8; 390 *p++ = alimb; 391#elif BYTES_PER_MPI_LIMB == 8 392 *p++ = alimb >> 56; 393 *p++ = alimb >> 48; 394 *p++ = alimb >> 40; 395 *p++ = alimb >> 32; 396 *p++ = alimb >> 24; 397 *p++ = alimb >> 16; 398 *p++ = alimb >> 8; 399 *p++ = alimb; 400#else 401#error please implement for this limb size. 402#endif 403 if (lzeros > 0) { 404 if (lzeros >= sizeof(alimb)) { 405 p -= sizeof(alimb); 406 continue; 407 } else { 408 mpi_limb_t *limb1 = (void *)p - sizeof(alimb); 409 mpi_limb_t *limb2 = (void *)p - sizeof(alimb) 410 + lzeros; 411 *limb1 = *limb2; 412 p -= lzeros; 413 y = lzeros; 414 } 415 lzeros -= sizeof(alimb); 416 } 417 418 p = p - (sizeof(alimb) - y); 419 420 for (x = 0; x < sizeof(alimb) - y; x++) { 421 if (!buf_len) { 422 sgl = sg_next(sgl); 423 if (!sgl) 424 return -EINVAL; 425 buf_len = sgl->length; 426 p2 = sg_virt(sgl); 427 } 428 *p2++ = *p++; 429 buf_len--; 430 } 431 y = 0; 432 } 433 return 0; 434} 435EXPORT_SYMBOL_GPL(mpi_write_to_sgl); 436 437/* 438 * mpi_read_raw_from_sgl() - Function allocates an MPI and populates it with 439 * data from the sgl 440 * 441 * This function works in the same way as the mpi_read_raw_data, but it 442 * takes an sgl instead of void * buffer. i.e. it allocates 443 * a new MPI and reads the content of the sgl to the MPI. 444 * 445 * @sgl: scatterlist to read from 446 * @len: number of bytes to read 447 * 448 * Return: Pointer to a new MPI or NULL on error 449 */ 450MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int len) 451{ 452 struct scatterlist *sg; 453 int x, i, j, z, lzeros, ents; 454 unsigned int nbits, nlimbs, nbytes; 455 mpi_limb_t a; 456 MPI val = NULL; 457 458 lzeros = 0; 459 ents = sg_nents(sgl); 460 461 for_each_sg(sgl, sg, ents, i) { 462 const u8 *buff = sg_virt(sg); 463 int len = sg->length; 464 465 while (len && !*buff) { 466 lzeros++; 467 len--; 468 buff++; 469 } 470 471 if (len && *buff) 472 break; 473 474 ents--; 475 lzeros = 0; 476 } 477 478 sgl = sg; 479 480 if (!ents) 481 nbytes = 0; 482 else 483 nbytes = len - lzeros; 484 485 nbits = nbytes * 8; 486 if (nbits > MAX_EXTERN_MPI_BITS) { 487 pr_info("MPI: mpi too large (%u bits)\n", nbits); 488 return NULL; 489 } 490 491 if (nbytes > 0) 492 nbits -= count_leading_zeros(*(u8 *)(sg_virt(sgl) + lzeros)); 493 else 494 nbits = 0; 495 496 nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB); 497 val = mpi_alloc(nlimbs); 498 if (!val) 499 return NULL; 500 501 val->nbits = nbits; 502 val->sign = 0; 503 val->nlimbs = nlimbs; 504 505 if (nbytes == 0) 506 return val; 507 508 j = nlimbs - 1; 509 a = 0; 510 z = 0; 511 x = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; 512 x %= BYTES_PER_MPI_LIMB; 513 514 for_each_sg(sgl, sg, ents, i) { 515 const u8 *buffer = sg_virt(sg) + lzeros; 516 int len = sg->length - lzeros; 517 int buf_shift = x; 518 519 if (sg_is_last(sg) && (len % BYTES_PER_MPI_LIMB)) 520 len += BYTES_PER_MPI_LIMB - (len % BYTES_PER_MPI_LIMB); 521 522 for (; x < len + buf_shift; x++) { 523 a <<= 8; 524 a |= *buffer++; 525 if (((z + x + 1) % BYTES_PER_MPI_LIMB) == 0) { 526 val->d[j--] = a; 527 a = 0; 528 } 529 } 530 z += x; 531 x = 0; 532 lzeros = 0; 533 } 534 return val; 535} 536EXPORT_SYMBOL_GPL(mpi_read_raw_from_sgl);