at v4.5 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 131/** 132 * mpi_read_buffer() - read MPI to a bufer provided by user (msb first) 133 * 134 * @a: a multi precision integer 135 * @buf: bufer to which the output will be written to. Needs to be at 136 * leaset mpi_get_size(a) long. 137 * @buf_len: size of the buf. 138 * @nbytes: receives the actual length of the data written on success and 139 * the data to-be-written on -EOVERFLOW in case buf_len was too 140 * small. 141 * @sign: if not NULL, it will be set to the sign of a. 142 * 143 * Return: 0 on success or error code in case of error 144 */ 145int mpi_read_buffer(MPI a, uint8_t *buf, unsigned buf_len, unsigned *nbytes, 146 int *sign) 147{ 148 uint8_t *p; 149 mpi_limb_t alimb; 150 unsigned int n = mpi_get_size(a); 151 int i, lzeros = 0; 152 153 if (!buf || !nbytes) 154 return -EINVAL; 155 156 if (sign) 157 *sign = a->sign; 158 159 p = (void *)&a->d[a->nlimbs] - 1; 160 161 for (i = a->nlimbs * sizeof(alimb) - 1; i >= 0; i--, p--) { 162 if (!*p) 163 lzeros++; 164 else 165 break; 166 } 167 168 if (buf_len < n - lzeros) { 169 *nbytes = n - lzeros; 170 return -EOVERFLOW; 171 } 172 173 p = buf; 174 *nbytes = n - lzeros; 175 176 for (i = a->nlimbs - 1; i >= 0; i--) { 177 alimb = a->d[i]; 178#if BYTES_PER_MPI_LIMB == 4 179 *p++ = alimb >> 24; 180 *p++ = alimb >> 16; 181 *p++ = alimb >> 8; 182 *p++ = alimb; 183#elif BYTES_PER_MPI_LIMB == 8 184 *p++ = alimb >> 56; 185 *p++ = alimb >> 48; 186 *p++ = alimb >> 40; 187 *p++ = alimb >> 32; 188 *p++ = alimb >> 24; 189 *p++ = alimb >> 16; 190 *p++ = alimb >> 8; 191 *p++ = alimb; 192#else 193#error please implement for this limb size. 194#endif 195 196 if (lzeros > 0) { 197 if (lzeros >= sizeof(alimb)) { 198 p -= sizeof(alimb); 199 } else { 200 mpi_limb_t *limb1 = (void *)p - sizeof(alimb); 201 mpi_limb_t *limb2 = (void *)p - sizeof(alimb) 202 + lzeros; 203 *limb1 = *limb2; 204 p -= lzeros; 205 } 206 lzeros -= sizeof(alimb); 207 } 208 } 209 return 0; 210} 211EXPORT_SYMBOL_GPL(mpi_read_buffer); 212 213/* 214 * mpi_get_buffer() - Returns an allocated buffer with the MPI (msb first). 215 * Caller must free the return string. 216 * This function does return a 0 byte buffer with nbytes set to zero if the 217 * value of A is zero. 218 * 219 * @a: a multi precision integer. 220 * @nbytes: receives the length of this buffer. 221 * @sign: if not NULL, it will be set to the sign of the a. 222 * 223 * Return: Pointer to MPI buffer or NULL on error 224 */ 225void *mpi_get_buffer(MPI a, unsigned *nbytes, int *sign) 226{ 227 uint8_t *buf; 228 unsigned int n; 229 int ret; 230 231 if (!nbytes) 232 return NULL; 233 234 n = mpi_get_size(a); 235 236 if (!n) 237 n++; 238 239 buf = kmalloc(n, GFP_KERNEL); 240 241 if (!buf) 242 return NULL; 243 244 ret = mpi_read_buffer(a, buf, n, nbytes, sign); 245 246 if (ret) { 247 kfree(buf); 248 return NULL; 249 } 250 return buf; 251} 252EXPORT_SYMBOL_GPL(mpi_get_buffer); 253 254/**************** 255 * Use BUFFER to update MPI. 256 */ 257int mpi_set_buffer(MPI a, const void *xbuffer, unsigned nbytes, int sign) 258{ 259 const uint8_t *buffer = xbuffer, *p; 260 mpi_limb_t alimb; 261 int nlimbs; 262 int i; 263 264 nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB); 265 if (RESIZE_IF_NEEDED(a, nlimbs) < 0) 266 return -ENOMEM; 267 a->sign = sign; 268 269 for (i = 0, p = buffer + nbytes - 1; p >= buffer + BYTES_PER_MPI_LIMB;) { 270#if BYTES_PER_MPI_LIMB == 4 271 alimb = (mpi_limb_t) *p--; 272 alimb |= (mpi_limb_t) *p-- << 8; 273 alimb |= (mpi_limb_t) *p-- << 16; 274 alimb |= (mpi_limb_t) *p-- << 24; 275#elif BYTES_PER_MPI_LIMB == 8 276 alimb = (mpi_limb_t) *p--; 277 alimb |= (mpi_limb_t) *p-- << 8; 278 alimb |= (mpi_limb_t) *p-- << 16; 279 alimb |= (mpi_limb_t) *p-- << 24; 280 alimb |= (mpi_limb_t) *p-- << 32; 281 alimb |= (mpi_limb_t) *p-- << 40; 282 alimb |= (mpi_limb_t) *p-- << 48; 283 alimb |= (mpi_limb_t) *p-- << 56; 284#else 285#error please implement for this limb size. 286#endif 287 a->d[i++] = alimb; 288 } 289 if (p >= buffer) { 290#if BYTES_PER_MPI_LIMB == 4 291 alimb = *p--; 292 if (p >= buffer) 293 alimb |= (mpi_limb_t) *p-- << 8; 294 if (p >= buffer) 295 alimb |= (mpi_limb_t) *p-- << 16; 296 if (p >= buffer) 297 alimb |= (mpi_limb_t) *p-- << 24; 298#elif BYTES_PER_MPI_LIMB == 8 299 alimb = (mpi_limb_t) *p--; 300 if (p >= buffer) 301 alimb |= (mpi_limb_t) *p-- << 8; 302 if (p >= buffer) 303 alimb |= (mpi_limb_t) *p-- << 16; 304 if (p >= buffer) 305 alimb |= (mpi_limb_t) *p-- << 24; 306 if (p >= buffer) 307 alimb |= (mpi_limb_t) *p-- << 32; 308 if (p >= buffer) 309 alimb |= (mpi_limb_t) *p-- << 40; 310 if (p >= buffer) 311 alimb |= (mpi_limb_t) *p-- << 48; 312 if (p >= buffer) 313 alimb |= (mpi_limb_t) *p-- << 56; 314#else 315#error please implement for this limb size. 316#endif 317 a->d[i++] = alimb; 318 } 319 a->nlimbs = i; 320 321 if (i != nlimbs) { 322 pr_emerg("MPI: mpi_set_buffer: Assertion failed (%d != %d)", i, 323 nlimbs); 324 BUG(); 325 } 326 return 0; 327} 328EXPORT_SYMBOL_GPL(mpi_set_buffer); 329 330/** 331 * mpi_write_to_sgl() - Funnction exports MPI to an sgl (msb first) 332 * 333 * This function works in the same way as the mpi_read_buffer, but it 334 * takes an sgl instead of u8 * buf. 335 * 336 * @a: a multi precision integer 337 * @sgl: scatterlist to write to. Needs to be at least 338 * mpi_get_size(a) long. 339 * @nbytes: in/out param - it has the be set to the maximum number of 340 * bytes that can be written to sgl. This has to be at least 341 * the size of the integer a. On return it receives the actual 342 * length of the data written on success or the data that would 343 * be written if buffer was too small. 344 * @sign: if not NULL, it will be set to the sign of a. 345 * 346 * Return: 0 on success or error code in case of error 347 */ 348int mpi_write_to_sgl(MPI a, struct scatterlist *sgl, unsigned *nbytes, 349 int *sign) 350{ 351 u8 *p, *p2; 352 mpi_limb_t alimb, alimb2; 353 unsigned int n = mpi_get_size(a); 354 int i, x, y = 0, lzeros = 0, buf_len; 355 356 if (!nbytes) 357 return -EINVAL; 358 359 if (sign) 360 *sign = a->sign; 361 362 p = (void *)&a->d[a->nlimbs] - 1; 363 364 for (i = a->nlimbs * sizeof(alimb) - 1; i >= 0; i--, p--) { 365 if (!*p) 366 lzeros++; 367 else 368 break; 369 } 370 371 if (*nbytes < n - lzeros) { 372 *nbytes = n - lzeros; 373 return -EOVERFLOW; 374 } 375 376 *nbytes = n - lzeros; 377 buf_len = sgl->length; 378 p2 = sg_virt(sgl); 379 380 for (i = a->nlimbs - 1; i >= 0; i--) { 381 alimb = a->d[i]; 382 p = (u8 *)&alimb2; 383#if BYTES_PER_MPI_LIMB == 4 384 *p++ = alimb >> 24; 385 *p++ = alimb >> 16; 386 *p++ = alimb >> 8; 387 *p++ = alimb; 388#elif BYTES_PER_MPI_LIMB == 8 389 *p++ = alimb >> 56; 390 *p++ = alimb >> 48; 391 *p++ = alimb >> 40; 392 *p++ = alimb >> 32; 393 *p++ = alimb >> 24; 394 *p++ = alimb >> 16; 395 *p++ = alimb >> 8; 396 *p++ = alimb; 397#else 398#error please implement for this limb size. 399#endif 400 if (lzeros > 0) { 401 if (lzeros >= sizeof(alimb)) { 402 p -= sizeof(alimb); 403 continue; 404 } else { 405 mpi_limb_t *limb1 = (void *)p - sizeof(alimb); 406 mpi_limb_t *limb2 = (void *)p - sizeof(alimb) 407 + lzeros; 408 *limb1 = *limb2; 409 p -= lzeros; 410 y = lzeros; 411 } 412 lzeros -= sizeof(alimb); 413 } 414 415 p = p - (sizeof(alimb) - y); 416 417 for (x = 0; x < sizeof(alimb) - y; x++) { 418 if (!buf_len) { 419 sgl = sg_next(sgl); 420 if (!sgl) 421 return -EINVAL; 422 buf_len = sgl->length; 423 p2 = sg_virt(sgl); 424 } 425 *p2++ = *p++; 426 buf_len--; 427 } 428 y = 0; 429 } 430 return 0; 431} 432EXPORT_SYMBOL_GPL(mpi_write_to_sgl); 433 434/* 435 * mpi_read_raw_from_sgl() - Function allocates an MPI and populates it with 436 * data from the sgl 437 * 438 * This function works in the same way as the mpi_read_raw_data, but it 439 * takes an sgl instead of void * buffer. i.e. it allocates 440 * a new MPI and reads the content of the sgl to the MPI. 441 * 442 * @sgl: scatterlist to read from 443 * @len: number of bytes to read 444 * 445 * Return: Pointer to a new MPI or NULL on error 446 */ 447MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int len) 448{ 449 struct scatterlist *sg; 450 int x, i, j, z, lzeros, ents; 451 unsigned int nbits, nlimbs, nbytes; 452 mpi_limb_t a; 453 MPI val = NULL; 454 455 lzeros = 0; 456 ents = sg_nents(sgl); 457 458 for_each_sg(sgl, sg, ents, i) { 459 const u8 *buff = sg_virt(sg); 460 int len = sg->length; 461 462 while (len && !*buff) { 463 lzeros++; 464 len--; 465 buff++; 466 } 467 468 if (len && *buff) 469 break; 470 471 ents--; 472 lzeros = 0; 473 } 474 475 sgl = sg; 476 477 if (!ents) 478 nbytes = 0; 479 else 480 nbytes = len - lzeros; 481 482 nbits = nbytes * 8; 483 if (nbits > MAX_EXTERN_MPI_BITS) { 484 pr_info("MPI: mpi too large (%u bits)\n", nbits); 485 return NULL; 486 } 487 488 if (nbytes > 0) 489 nbits -= count_leading_zeros(*(u8 *)(sg_virt(sgl) + lzeros)); 490 else 491 nbits = 0; 492 493 nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB); 494 val = mpi_alloc(nlimbs); 495 if (!val) 496 return NULL; 497 498 val->nbits = nbits; 499 val->sign = 0; 500 val->nlimbs = nlimbs; 501 502 if (nbytes == 0) 503 return val; 504 505 j = nlimbs - 1; 506 a = 0; 507 z = 0; 508 x = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; 509 x %= BYTES_PER_MPI_LIMB; 510 511 for_each_sg(sgl, sg, ents, i) { 512 const u8 *buffer = sg_virt(sg) + lzeros; 513 int len = sg->length - lzeros; 514 int buf_shift = x; 515 516 if (sg_is_last(sg) && (len % BYTES_PER_MPI_LIMB)) 517 len += BYTES_PER_MPI_LIMB - (len % BYTES_PER_MPI_LIMB); 518 519 for (; x < len + buf_shift; x++) { 520 a <<= 8; 521 a |= *buffer++; 522 if (((z + x + 1) % BYTES_PER_MPI_LIMB) == 0) { 523 val->d[j--] = a; 524 a = 0; 525 } 526 } 527 z += x; 528 x = 0; 529 lzeros = 0; 530 } 531 return val; 532} 533EXPORT_SYMBOL_GPL(mpi_read_raw_from_sgl);