at v4.4 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. 139 * @sign: if not NULL, it will be set to the sign of a. 140 * 141 * Return: 0 on success or error code in case of error 142 */ 143int mpi_read_buffer(MPI a, uint8_t *buf, unsigned buf_len, unsigned *nbytes, 144 int *sign) 145{ 146 uint8_t *p; 147 mpi_limb_t alimb; 148 unsigned int n = mpi_get_size(a); 149 int i, lzeros = 0; 150 151 if (buf_len < n || !buf || !nbytes) 152 return -EINVAL; 153 154 if (sign) 155 *sign = a->sign; 156 157 p = (void *)&a->d[a->nlimbs] - 1; 158 159 for (i = a->nlimbs * sizeof(alimb) - 1; i >= 0; i--, p--) { 160 if (!*p) 161 lzeros++; 162 else 163 break; 164 } 165 166 p = buf; 167 *nbytes = n - lzeros; 168 169 for (i = a->nlimbs - 1; i >= 0; i--) { 170 alimb = a->d[i]; 171#if BYTES_PER_MPI_LIMB == 4 172 *p++ = alimb >> 24; 173 *p++ = alimb >> 16; 174 *p++ = alimb >> 8; 175 *p++ = alimb; 176#elif BYTES_PER_MPI_LIMB == 8 177 *p++ = alimb >> 56; 178 *p++ = alimb >> 48; 179 *p++ = alimb >> 40; 180 *p++ = alimb >> 32; 181 *p++ = alimb >> 24; 182 *p++ = alimb >> 16; 183 *p++ = alimb >> 8; 184 *p++ = alimb; 185#else 186#error please implement for this limb size. 187#endif 188 189 if (lzeros > 0) { 190 if (lzeros >= sizeof(alimb)) { 191 p -= sizeof(alimb); 192 } else { 193 mpi_limb_t *limb1 = (void *)p - sizeof(alimb); 194 mpi_limb_t *limb2 = (void *)p - sizeof(alimb) 195 + lzeros; 196 *limb1 = *limb2; 197 p -= lzeros; 198 } 199 lzeros -= sizeof(alimb); 200 } 201 } 202 return 0; 203} 204EXPORT_SYMBOL_GPL(mpi_read_buffer); 205 206/* 207 * mpi_get_buffer() - Returns an allocated buffer with the MPI (msb first). 208 * Caller must free the return string. 209 * This function does return a 0 byte buffer with nbytes set to zero if the 210 * value of A is zero. 211 * 212 * @a: a multi precision integer. 213 * @nbytes: receives the length of this buffer. 214 * @sign: if not NULL, it will be set to the sign of the a. 215 * 216 * Return: Pointer to MPI buffer or NULL on error 217 */ 218void *mpi_get_buffer(MPI a, unsigned *nbytes, int *sign) 219{ 220 uint8_t *buf; 221 unsigned int n; 222 int ret; 223 224 if (!nbytes) 225 return NULL; 226 227 n = mpi_get_size(a); 228 229 if (!n) 230 n++; 231 232 buf = kmalloc(n, GFP_KERNEL); 233 234 if (!buf) 235 return NULL; 236 237 ret = mpi_read_buffer(a, buf, n, nbytes, sign); 238 239 if (ret) { 240 kfree(buf); 241 return NULL; 242 } 243 return buf; 244} 245EXPORT_SYMBOL_GPL(mpi_get_buffer); 246 247/**************** 248 * Use BUFFER to update MPI. 249 */ 250int mpi_set_buffer(MPI a, const void *xbuffer, unsigned nbytes, int sign) 251{ 252 const uint8_t *buffer = xbuffer, *p; 253 mpi_limb_t alimb; 254 int nlimbs; 255 int i; 256 257 nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB); 258 if (RESIZE_IF_NEEDED(a, nlimbs) < 0) 259 return -ENOMEM; 260 a->sign = sign; 261 262 for (i = 0, p = buffer + nbytes - 1; p >= buffer + BYTES_PER_MPI_LIMB;) { 263#if BYTES_PER_MPI_LIMB == 4 264 alimb = (mpi_limb_t) *p--; 265 alimb |= (mpi_limb_t) *p-- << 8; 266 alimb |= (mpi_limb_t) *p-- << 16; 267 alimb |= (mpi_limb_t) *p-- << 24; 268#elif BYTES_PER_MPI_LIMB == 8 269 alimb = (mpi_limb_t) *p--; 270 alimb |= (mpi_limb_t) *p-- << 8; 271 alimb |= (mpi_limb_t) *p-- << 16; 272 alimb |= (mpi_limb_t) *p-- << 24; 273 alimb |= (mpi_limb_t) *p-- << 32; 274 alimb |= (mpi_limb_t) *p-- << 40; 275 alimb |= (mpi_limb_t) *p-- << 48; 276 alimb |= (mpi_limb_t) *p-- << 56; 277#else 278#error please implement for this limb size. 279#endif 280 a->d[i++] = alimb; 281 } 282 if (p >= buffer) { 283#if BYTES_PER_MPI_LIMB == 4 284 alimb = *p--; 285 if (p >= buffer) 286 alimb |= (mpi_limb_t) *p-- << 8; 287 if (p >= buffer) 288 alimb |= (mpi_limb_t) *p-- << 16; 289 if (p >= buffer) 290 alimb |= (mpi_limb_t) *p-- << 24; 291#elif BYTES_PER_MPI_LIMB == 8 292 alimb = (mpi_limb_t) *p--; 293 if (p >= buffer) 294 alimb |= (mpi_limb_t) *p-- << 8; 295 if (p >= buffer) 296 alimb |= (mpi_limb_t) *p-- << 16; 297 if (p >= buffer) 298 alimb |= (mpi_limb_t) *p-- << 24; 299 if (p >= buffer) 300 alimb |= (mpi_limb_t) *p-- << 32; 301 if (p >= buffer) 302 alimb |= (mpi_limb_t) *p-- << 40; 303 if (p >= buffer) 304 alimb |= (mpi_limb_t) *p-- << 48; 305 if (p >= buffer) 306 alimb |= (mpi_limb_t) *p-- << 56; 307#else 308#error please implement for this limb size. 309#endif 310 a->d[i++] = alimb; 311 } 312 a->nlimbs = i; 313 314 if (i != nlimbs) { 315 pr_emerg("MPI: mpi_set_buffer: Assertion failed (%d != %d)", i, 316 nlimbs); 317 BUG(); 318 } 319 return 0; 320} 321EXPORT_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 */ 340int 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} 419EXPORT_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 */ 434MPI 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 len--; 452 buff++; 453 } 454 455 if (len && *buff) 456 break; 457 458 ents--; 459 lzeros = 0; 460 } 461 462 sgl = sg; 463 464 if (!ents) 465 nbytes = 0; 466 else 467 nbytes = len - lzeros; 468 469 nbits = nbytes * 8; 470 if (nbits > MAX_EXTERN_MPI_BITS) { 471 pr_info("MPI: mpi too large (%u bits)\n", nbits); 472 return NULL; 473 } 474 475 if (nbytes > 0) 476 nbits -= count_leading_zeros(*(u8 *)(sg_virt(sgl) + lzeros)); 477 else 478 nbits = 0; 479 480 nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB); 481 val = mpi_alloc(nlimbs); 482 if (!val) 483 return NULL; 484 485 val->nbits = nbits; 486 val->sign = 0; 487 val->nlimbs = nlimbs; 488 489 if (nbytes == 0) 490 return val; 491 492 j = nlimbs - 1; 493 a = 0; 494 z = 0; 495 x = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; 496 x %= BYTES_PER_MPI_LIMB; 497 498 for_each_sg(sgl, sg, ents, i) { 499 const u8 *buffer = sg_virt(sg) + lzeros; 500 int len = sg->length - lzeros; 501 int buf_shift = x; 502 503 if (sg_is_last(sg) && (len % BYTES_PER_MPI_LIMB)) 504 len += BYTES_PER_MPI_LIMB - (len % BYTES_PER_MPI_LIMB); 505 506 for (; x < len + buf_shift; x++) { 507 a <<= 8; 508 a |= *buffer++; 509 if (((z + x + 1) % BYTES_PER_MPI_LIMB) == 0) { 510 val->d[j--] = a; 511 a = 0; 512 } 513 } 514 z += x; 515 x = 0; 516 lzeros = 0; 517 } 518 return val; 519} 520EXPORT_SYMBOL_GPL(mpi_read_raw_from_sgl);