linux/lib/mpi/mpicoder.c
<<
>>
Prefs
   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);
 537