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 <linux/byteorder/generic.h>
  24#include <linux/scatterlist.h>
  25#include <linux/string.h>
  26#include "mpi-internal.h"
  27
  28#define MAX_EXTERN_SCAN_BYTES (16*1024*1024)
  29#define MAX_EXTERN_MPI_BITS 16384
  30
  31/**
  32 * mpi_read_raw_data - Read a raw byte stream as a positive integer
  33 * @xbuffer: The data to read
  34 * @nbytes: The amount of data to read
  35 */
  36MPI mpi_read_raw_data(const void *xbuffer, size_t nbytes)
  37{
  38        const uint8_t *buffer = xbuffer;
  39        int i, j;
  40        unsigned nbits, nlimbs;
  41        mpi_limb_t a;
  42        MPI val = NULL;
  43
  44        while (nbytes > 0 && buffer[0] == 0) {
  45                buffer++;
  46                nbytes--;
  47        }
  48
  49        nbits = nbytes * 8;
  50        if (nbits > MAX_EXTERN_MPI_BITS) {
  51                pr_info("MPI: mpi too large (%u bits)\n", nbits);
  52                return NULL;
  53        }
  54        if (nbytes > 0)
  55                nbits -= count_leading_zeros(buffer[0]) - (BITS_PER_LONG - 8);
  56
  57        nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB);
  58        val = mpi_alloc(nlimbs);
  59        if (!val)
  60                return NULL;
  61        val->nbits = nbits;
  62        val->sign = 0;
  63        val->nlimbs = nlimbs;
  64
  65        if (nbytes > 0) {
  66                i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
  67                i %= BYTES_PER_MPI_LIMB;
  68                for (j = nlimbs; j > 0; j--) {
  69                        a = 0;
  70                        for (; i < BYTES_PER_MPI_LIMB; i++) {
  71                                a <<= 8;
  72                                a |= *buffer++;
  73                        }
  74                        i = 0;
  75                        val->d[j - 1] = a;
  76                }
  77        }
  78        return val;
  79}
  80EXPORT_SYMBOL_GPL(mpi_read_raw_data);
  81
  82MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread)
  83{
  84        const uint8_t *buffer = xbuffer;
  85        unsigned int nbits, nbytes;
  86        MPI val;
  87
  88        if (*ret_nread < 2)
  89                return ERR_PTR(-EINVAL);
  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                return ERR_PTR(-EINVAL);
  95        }
  96
  97        nbytes = DIV_ROUND_UP(nbits, 8);
  98        if (nbytes + 2 > *ret_nread) {
  99                pr_info("MPI: mpi larger than buffer nbytes=%u ret_nread=%u\n",
 100                                nbytes, *ret_nread);
 101                return ERR_PTR(-EINVAL);
 102        }
 103
 104        val = mpi_read_raw_data(buffer + 2, nbytes);
 105        if (!val)
 106                return ERR_PTR(-ENOMEM);
 107
 108        *ret_nread = nbytes + 2;
 109        return val;
 110}
 111EXPORT_SYMBOL_GPL(mpi_read_from_buffer);
 112
 113/****************
 114 * Fill the mpi VAL from the hex string in STR.
 115 */
 116int mpi_fromstr(MPI val, const char *str)
 117{
 118        int sign = 0;
 119        int prepend_zero = 0;
 120        int i, j, c, c1, c2;
 121        unsigned int nbits, nbytes, nlimbs;
 122        mpi_limb_t a;
 123
 124        if (*str == '-') {
 125                sign = 1;
 126                str++;
 127        }
 128
 129        /* Skip optional hex prefix.  */
 130        if (*str == '0' && str[1] == 'x')
 131                str += 2;
 132
 133        nbits = strlen(str);
 134        if (nbits > MAX_EXTERN_SCAN_BYTES) {
 135                mpi_clear(val);
 136                return -EINVAL;
 137        }
 138        nbits *= 4;
 139        if ((nbits % 8))
 140                prepend_zero = 1;
 141
 142        nbytes = (nbits+7) / 8;
 143        nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB;
 144
 145        if (val->alloced < nlimbs)
 146                mpi_resize(val, nlimbs);
 147
 148        i = BYTES_PER_MPI_LIMB - (nbytes % BYTES_PER_MPI_LIMB);
 149        i %= BYTES_PER_MPI_LIMB;
 150        j = val->nlimbs = nlimbs;
 151        val->sign = sign;
 152        for (; j > 0; j--) {
 153                a = 0;
 154                for (; i < BYTES_PER_MPI_LIMB; i++) {
 155                        if (prepend_zero) {
 156                                c1 = '0';
 157                                prepend_zero = 0;
 158                        } else
 159                                c1 = *str++;
 160
 161                        if (!c1) {
 162                                mpi_clear(val);
 163                                return -EINVAL;
 164                        }
 165                        c2 = *str++;
 166                        if (!c2) {
 167                                mpi_clear(val);
 168                                return -EINVAL;
 169                        }
 170                        if (c1 >= '0' && c1 <= '9')
 171                                c = c1 - '0';
 172                        else if (c1 >= 'a' && c1 <= 'f')
 173                                c = c1 - 'a' + 10;
 174                        else if (c1 >= 'A' && c1 <= 'F')
 175                                c = c1 - 'A' + 10;
 176                        else {
 177                                mpi_clear(val);
 178                                return -EINVAL;
 179                        }
 180                        c <<= 4;
 181                        if (c2 >= '0' && c2 <= '9')
 182                                c |= c2 - '0';
 183                        else if (c2 >= 'a' && c2 <= 'f')
 184                                c |= c2 - 'a' + 10;
 185                        else if (c2 >= 'A' && c2 <= 'F')
 186                                c |= c2 - 'A' + 10;
 187                        else {
 188                                mpi_clear(val);
 189                                return -EINVAL;
 190                        }
 191                        a <<= 8;
 192                        a |= c;
 193                }
 194                i = 0;
 195                val->d[j-1] = a;
 196        }
 197
 198        return 0;
 199}
 200EXPORT_SYMBOL_GPL(mpi_fromstr);
 201
 202MPI mpi_scanval(const char *string)
 203{
 204        MPI a;
 205
 206        a = mpi_alloc(0);
 207        if (!a)
 208                return NULL;
 209
 210        if (mpi_fromstr(a, string)) {
 211                mpi_free(a);
 212                return NULL;
 213        }
 214        mpi_normalize(a);
 215        return a;
 216}
 217EXPORT_SYMBOL_GPL(mpi_scanval);
 218
 219static int count_lzeros(MPI a)
 220{
 221        mpi_limb_t alimb;
 222        int i, lzeros = 0;
 223
 224        for (i = a->nlimbs - 1; i >= 0; i--) {
 225                alimb = a->d[i];
 226                if (alimb == 0) {
 227                        lzeros += sizeof(mpi_limb_t);
 228                } else {
 229                        lzeros += count_leading_zeros(alimb) / 8;
 230                        break;
 231                }
 232        }
 233        return lzeros;
 234}
 235
 236/**
 237 * mpi_read_buffer() - read MPI to a buffer provided by user (msb first)
 238 *
 239 * @a:          a multi precision integer
 240 * @buf:        buffer to which the output will be written to. Needs to be at
 241 *              least mpi_get_size(a) long.
 242 * @buf_len:    size of the buf.
 243 * @nbytes:     receives the actual length of the data written on success and
 244 *              the data to-be-written on -EOVERFLOW in case buf_len was too
 245 *              small.
 246 * @sign:       if not NULL, it will be set to the sign of a.
 247 *
 248 * Return:      0 on success or error code in case of error
 249 */
 250int mpi_read_buffer(MPI a, uint8_t *buf, unsigned buf_len, unsigned *nbytes,
 251                    int *sign)
 252{
 253        uint8_t *p;
 254#if BYTES_PER_MPI_LIMB == 4
 255        __be32 alimb;
 256#elif BYTES_PER_MPI_LIMB == 8
 257        __be64 alimb;
 258#else
 259#error please implement for this limb size.
 260#endif
 261        unsigned int n = mpi_get_size(a);
 262        int i, lzeros;
 263
 264        if (!buf || !nbytes)
 265                return -EINVAL;
 266
 267        if (sign)
 268                *sign = a->sign;
 269
 270        lzeros = count_lzeros(a);
 271
 272        if (buf_len < n - lzeros) {
 273                *nbytes = n - lzeros;
 274                return -EOVERFLOW;
 275        }
 276
 277        p = buf;
 278        *nbytes = n - lzeros;
 279
 280        for (i = a->nlimbs - 1 - lzeros / BYTES_PER_MPI_LIMB,
 281                        lzeros %= BYTES_PER_MPI_LIMB;
 282                i >= 0; i--) {
 283#if BYTES_PER_MPI_LIMB == 4
 284                alimb = cpu_to_be32(a->d[i]);
 285#elif BYTES_PER_MPI_LIMB == 8
 286                alimb = cpu_to_be64(a->d[i]);
 287#else
 288#error please implement for this limb size.
 289#endif
 290                memcpy(p, (u8 *)&alimb + lzeros, BYTES_PER_MPI_LIMB - lzeros);
 291                p += BYTES_PER_MPI_LIMB - lzeros;
 292                lzeros = 0;
 293        }
 294        return 0;
 295}
 296EXPORT_SYMBOL_GPL(mpi_read_buffer);
 297
 298/*
 299 * mpi_get_buffer() - Returns an allocated buffer with the MPI (msb first).
 300 * Caller must free the return string.
 301 * This function does return a 0 byte buffer with nbytes set to zero if the
 302 * value of A is zero.
 303 *
 304 * @a:          a multi precision integer.
 305 * @nbytes:     receives the length of this buffer.
 306 * @sign:       if not NULL, it will be set to the sign of the a.
 307 *
 308 * Return:      Pointer to MPI buffer or NULL on error
 309 */
 310void *mpi_get_buffer(MPI a, unsigned *nbytes, int *sign)
 311{
 312        uint8_t *buf;
 313        unsigned int n;
 314        int ret;
 315
 316        if (!nbytes)
 317                return NULL;
 318
 319        n = mpi_get_size(a);
 320
 321        if (!n)
 322                n++;
 323
 324        buf = kmalloc(n, GFP_KERNEL);
 325
 326        if (!buf)
 327                return NULL;
 328
 329        ret = mpi_read_buffer(a, buf, n, nbytes, sign);
 330
 331        if (ret) {
 332                kfree(buf);
 333                return NULL;
 334        }
 335        return buf;
 336}
 337EXPORT_SYMBOL_GPL(mpi_get_buffer);
 338
 339/**
 340 * mpi_write_to_sgl() - Funnction exports MPI to an sgl (msb first)
 341 *
 342 * This function works in the same way as the mpi_read_buffer, but it
 343 * takes an sgl instead of u8 * buf.
 344 *
 345 * @a:          a multi precision integer
 346 * @sgl:        scatterlist to write to. Needs to be at least
 347 *              mpi_get_size(a) long.
 348 * @nbytes:     the number of bytes to write.  Leading bytes will be
 349 *              filled with zero.
 350 * @sign:       if not NULL, it will be set to the sign of a.
 351 *
 352 * Return:      0 on success or error code in case of error
 353 */
 354int mpi_write_to_sgl(MPI a, struct scatterlist *sgl, unsigned nbytes,
 355                     int *sign)
 356{
 357        u8 *p, *p2;
 358#if BYTES_PER_MPI_LIMB == 4
 359        __be32 alimb;
 360#elif BYTES_PER_MPI_LIMB == 8
 361        __be64 alimb;
 362#else
 363#error please implement for this limb size.
 364#endif
 365        unsigned int n = mpi_get_size(a);
 366        struct sg_mapping_iter miter;
 367        int i, x, buf_len;
 368        int nents;
 369
 370        if (sign)
 371                *sign = a->sign;
 372
 373        if (nbytes < n)
 374                return -EOVERFLOW;
 375
 376        nents = sg_nents_for_len(sgl, nbytes);
 377        if (nents < 0)
 378                return -EINVAL;
 379
 380        sg_miter_start(&miter, sgl, nents, SG_MITER_ATOMIC | SG_MITER_TO_SG);
 381        sg_miter_next(&miter);
 382        buf_len = miter.length;
 383        p2 = miter.addr;
 384
 385        while (nbytes > n) {
 386                i = min_t(unsigned, nbytes - n, buf_len);
 387                memset(p2, 0, i);
 388                p2 += i;
 389                nbytes -= i;
 390
 391                buf_len -= i;
 392                if (!buf_len) {
 393                        sg_miter_next(&miter);
 394                        buf_len = miter.length;
 395                        p2 = miter.addr;
 396                }
 397        }
 398
 399        for (i = a->nlimbs - 1; i >= 0; i--) {
 400#if BYTES_PER_MPI_LIMB == 4
 401                alimb = a->d[i] ? cpu_to_be32(a->d[i]) : 0;
 402#elif BYTES_PER_MPI_LIMB == 8
 403                alimb = a->d[i] ? cpu_to_be64(a->d[i]) : 0;
 404#else
 405#error please implement for this limb size.
 406#endif
 407                p = (u8 *)&alimb;
 408
 409                for (x = 0; x < sizeof(alimb); x++) {
 410                        *p2++ = *p++;
 411                        if (!--buf_len) {
 412                                sg_miter_next(&miter);
 413                                buf_len = miter.length;
 414                                p2 = miter.addr;
 415                        }
 416                }
 417        }
 418
 419        sg_miter_stop(&miter);
 420        return 0;
 421}
 422EXPORT_SYMBOL_GPL(mpi_write_to_sgl);
 423
 424/*
 425 * mpi_read_raw_from_sgl() - Function allocates an MPI and populates it with
 426 *                           data from the sgl
 427 *
 428 * This function works in the same way as the mpi_read_raw_data, but it
 429 * takes an sgl instead of void * buffer. i.e. it allocates
 430 * a new MPI and reads the content of the sgl to the MPI.
 431 *
 432 * @sgl:        scatterlist to read from
 433 * @nbytes:     number of bytes to read
 434 *
 435 * Return:      Pointer to a new MPI or NULL on error
 436 */
 437MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int nbytes)
 438{
 439        struct sg_mapping_iter miter;
 440        unsigned int nbits, nlimbs;
 441        int x, j, z, lzeros, ents;
 442        unsigned int len;
 443        const u8 *buff;
 444        mpi_limb_t a;
 445        MPI val = NULL;
 446
 447        ents = sg_nents_for_len(sgl, nbytes);
 448        if (ents < 0)
 449                return NULL;
 450
 451        sg_miter_start(&miter, sgl, ents, SG_MITER_ATOMIC | SG_MITER_FROM_SG);
 452
 453        lzeros = 0;
 454        len = 0;
 455        while (nbytes > 0) {
 456                while (len && !*buff) {
 457                        lzeros++;
 458                        len--;
 459                        buff++;
 460                }
 461
 462                if (len && *buff)
 463                        break;
 464
 465                sg_miter_next(&miter);
 466                buff = miter.addr;
 467                len = miter.length;
 468
 469                nbytes -= lzeros;
 470                lzeros = 0;
 471        }
 472
 473        miter.consumed = lzeros;
 474
 475        nbytes -= lzeros;
 476        nbits = nbytes * 8;
 477        if (nbits > MAX_EXTERN_MPI_BITS) {
 478                sg_miter_stop(&miter);
 479                pr_info("MPI: mpi too large (%u bits)\n", nbits);
 480                return NULL;
 481        }
 482
 483        if (nbytes > 0)
 484                nbits -= count_leading_zeros(*buff) - (BITS_PER_LONG - 8);
 485
 486        sg_miter_stop(&miter);
 487
 488        nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB);
 489        val = mpi_alloc(nlimbs);
 490        if (!val)
 491                return NULL;
 492
 493        val->nbits = nbits;
 494        val->sign = 0;
 495        val->nlimbs = nlimbs;
 496
 497        if (nbytes == 0)
 498                return val;
 499
 500        j = nlimbs - 1;
 501        a = 0;
 502        z = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
 503        z %= BYTES_PER_MPI_LIMB;
 504
 505        while (sg_miter_next(&miter)) {
 506                buff = miter.addr;
 507                len = miter.length;
 508
 509                for (x = 0; x < len; x++) {
 510                        a <<= 8;
 511                        a |= *buff++;
 512                        if (((z + x + 1) % BYTES_PER_MPI_LIMB) == 0) {
 513                                val->d[j--] = a;
 514                                a = 0;
 515                        }
 516                }
 517                z += x;
 518        }
 519
 520        return val;
 521}
 522EXPORT_SYMBOL_GPL(mpi_read_raw_from_sgl);
 523
 524/* Perform a two's complement operation on buffer P of size N bytes.  */
 525static void twocompl(unsigned char *p, unsigned int n)
 526{
 527        int i;
 528
 529        for (i = n-1; i >= 0 && !p[i]; i--)
 530                ;
 531        if (i >= 0) {
 532                if ((p[i] & 0x01))
 533                        p[i] = (((p[i] ^ 0xfe) | 0x01) & 0xff);
 534                else if ((p[i] & 0x02))
 535                        p[i] = (((p[i] ^ 0xfc) | 0x02) & 0xfe);
 536                else if ((p[i] & 0x04))
 537                        p[i] = (((p[i] ^ 0xf8) | 0x04) & 0xfc);
 538                else if ((p[i] & 0x08))
 539                        p[i] = (((p[i] ^ 0xf0) | 0x08) & 0xf8);
 540                else if ((p[i] & 0x10))
 541                        p[i] = (((p[i] ^ 0xe0) | 0x10) & 0xf0);
 542                else if ((p[i] & 0x20))
 543                        p[i] = (((p[i] ^ 0xc0) | 0x20) & 0xe0);
 544                else if ((p[i] & 0x40))
 545                        p[i] = (((p[i] ^ 0x80) | 0x40) & 0xc0);
 546                else
 547                        p[i] = 0x80;
 548
 549                for (i--; i >= 0; i--)
 550                        p[i] ^= 0xff;
 551        }
 552}
 553
 554int mpi_print(enum gcry_mpi_format format, unsigned char *buffer,
 555                        size_t buflen, size_t *nwritten, MPI a)
 556{
 557        unsigned int nbits = mpi_get_nbits(a);
 558        size_t len;
 559        size_t dummy_nwritten;
 560        int negative;
 561
 562        if (!nwritten)
 563                nwritten = &dummy_nwritten;
 564
 565        /* Libgcrypt does no always care to set clear the sign if the value
 566         * is 0.  For printing this is a bit of a surprise, in particular
 567         * because if some of the formats don't support negative numbers but
 568         * should be able to print a zero.  Thus we need this extra test
 569         * for a negative number.
 570         */
 571        if (a->sign && mpi_cmp_ui(a, 0))
 572                negative = 1;
 573        else
 574                negative = 0;
 575
 576        len = buflen;
 577        *nwritten = 0;
 578        if (format == GCRYMPI_FMT_STD) {
 579                unsigned char *tmp;
 580                int extra = 0;
 581                unsigned int n;
 582
 583                tmp = mpi_get_buffer(a, &n, NULL);
 584                if (!tmp)
 585                        return -EINVAL;
 586
 587                if (negative) {
 588                        twocompl(tmp, n);
 589                        if (!(*tmp & 0x80)) {
 590                                /* Need to extend the sign.  */
 591                                n++;
 592                                extra = 2;
 593                        }
 594                } else if (n && (*tmp & 0x80)) {
 595                        /* Positive but the high bit of the returned buffer is set.
 596                         * Thus we need to print an extra leading 0x00 so that the
 597                         * output is interpreted as a positive number.
 598                         */
 599                        n++;
 600                        extra = 1;
 601                }
 602
 603                if (buffer && n > len) {
 604                        /* The provided buffer is too short. */
 605                        kfree(tmp);
 606                        return -E2BIG;
 607                }
 608                if (buffer) {
 609                        unsigned char *s = buffer;
 610
 611                        if (extra == 1)
 612                                *s++ = 0;
 613                        else if (extra)
 614                                *s++ = 0xff;
 615                        memcpy(s, tmp, n-!!extra);
 616                }
 617                kfree(tmp);
 618                *nwritten = n;
 619                return 0;
 620        } else if (format == GCRYMPI_FMT_USG) {
 621                unsigned int n = (nbits + 7)/8;
 622
 623                /* Note:  We ignore the sign for this format.  */
 624                /* FIXME: for performance reasons we should put this into
 625                 * mpi_aprint because we can then use the buffer directly.
 626                 */
 627
 628                if (buffer && n > len)
 629                        return -E2BIG;
 630                if (buffer) {
 631                        unsigned char *tmp;
 632
 633                        tmp = mpi_get_buffer(a, &n, NULL);
 634                        if (!tmp)
 635                                return -EINVAL;
 636                        memcpy(buffer, tmp, n);
 637                        kfree(tmp);
 638                }
 639                *nwritten = n;
 640                return 0;
 641        } else if (format == GCRYMPI_FMT_PGP) {
 642                unsigned int n = (nbits + 7)/8;
 643
 644                /* The PGP format can only handle unsigned integers.  */
 645                if (negative)
 646                        return -EINVAL;
 647
 648                if (buffer && n+2 > len)
 649                        return -E2BIG;
 650
 651                if (buffer) {
 652                        unsigned char *tmp;
 653                        unsigned char *s = buffer;
 654
 655                        s[0] = nbits >> 8;
 656                        s[1] = nbits;
 657
 658                        tmp = mpi_get_buffer(a, &n, NULL);
 659                        if (!tmp)
 660                                return -EINVAL;
 661                        memcpy(s+2, tmp, n);
 662                        kfree(tmp);
 663                }
 664                *nwritten = n+2;
 665                return 0;
 666        } else if (format == GCRYMPI_FMT_SSH) {
 667                unsigned char *tmp;
 668                int extra = 0;
 669                unsigned int n;
 670
 671                tmp = mpi_get_buffer(a, &n, NULL);
 672                if (!tmp)
 673                        return -EINVAL;
 674
 675                if (negative) {
 676                        twocompl(tmp, n);
 677                        if (!(*tmp & 0x80)) {
 678                                /* Need to extend the sign.  */
 679                                n++;
 680                                extra = 2;
 681                        }
 682                } else if (n && (*tmp & 0x80)) {
 683                        n++;
 684                        extra = 1;
 685                }
 686
 687                if (buffer && n+4 > len) {
 688                        kfree(tmp);
 689                        return -E2BIG;
 690                }
 691
 692                if (buffer) {
 693                        unsigned char *s = buffer;
 694
 695                        *s++ = n >> 24;
 696                        *s++ = n >> 16;
 697                        *s++ = n >> 8;
 698                        *s++ = n;
 699                        if (extra == 1)
 700                                *s++ = 0;
 701                        else if (extra)
 702                                *s++ = 0xff;
 703                        memcpy(s, tmp, n-!!extra);
 704                }
 705                kfree(tmp);
 706                *nwritten = 4+n;
 707                return 0;
 708        } else if (format == GCRYMPI_FMT_HEX) {
 709                unsigned char *tmp;
 710                int i;
 711                int extra = 0;
 712                unsigned int n = 0;
 713
 714                tmp = mpi_get_buffer(a, &n, NULL);
 715                if (!tmp)
 716                        return -EINVAL;
 717                if (!n || (*tmp & 0x80))
 718                        extra = 2;
 719
 720                if (buffer && 2*n + extra + negative + 1 > len) {
 721                        kfree(tmp);
 722                        return -E2BIG;
 723                }
 724                if (buffer) {
 725                        unsigned char *s = buffer;
 726
 727                        if (negative)
 728                                *s++ = '-';
 729                        if (extra) {
 730                                *s++ = '0';
 731                                *s++ = '0';
 732                        }
 733
 734                        for (i = 0; i < n; i++) {
 735                                unsigned int c = tmp[i];
 736
 737                                *s++ = (c >> 4) < 10 ? '0'+(c>>4) : 'A'+(c>>4)-10;
 738                                c &= 15;
 739                                *s++ = c < 10 ? '0'+c : 'A'+c-10;
 740                        }
 741                        *s++ = 0;
 742                        *nwritten = s - buffer;
 743                } else {
 744                        *nwritten = 2*n + extra + negative + 1;
 745                }
 746                kfree(tmp);
 747                return 0;
 748        } else
 749                return -EINVAL;
 750}
 751EXPORT_SYMBOL_GPL(mpi_print);
 752