1 /* mpicoder.c - Coder for the external representation of MPIs
2 * Copyright (C) 1998, 1999 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
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.
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.
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
21 #include "mpi-internal.h"
23 #define MAX_EXTERN_MPI_BITS 16384
25 MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread)
27 const uint8_t *buffer = xbuffer;
29 unsigned nbits, nbytes, nlimbs, nread = 0;
35 nbits = buffer[0] << 8 | buffer[1];
37 if (nbits > MAX_EXTERN_MPI_BITS) {
38 pr_info("MPI: mpi too large (%u bits)\n", nbits);
44 nbytes = (nbits + 7) / 8;
45 nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB;
46 val = mpi_alloc(nlimbs);
49 i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
50 i %= BYTES_PER_MPI_LIMB;
52 j = val->nlimbs = nlimbs;
56 for (; i < BYTES_PER_MPI_LIMB; i++) {
57 if (++nread > *ret_nread) {
59 ("MPI: mpi larger than buffer nread=%d ret_nread=%d\n",
74 EXPORT_SYMBOL_GPL(mpi_read_from_buffer);
77 * Return an allocated buffer with the MPI (msb first).
78 * NBYTES receives the length of this buffer. Caller must free the
79 * return string (This function does return a 0 byte buffer with NBYTES
80 * set to zero if the value of A is zero. If sign is not NULL, it will
81 * be set to the sign of the A.
83 void *mpi_get_buffer(MPI a, unsigned *nbytes, int *sign)
92 *nbytes = n = a->nlimbs * BYTES_PER_MPI_LIMB;
94 n++; /* avoid zero length allocation */
95 p = buffer = kmalloc(n, GFP_KERNEL);
99 for (i = a->nlimbs - 1; i >= 0; i--) {
101 #if BYTES_PER_MPI_LIMB == 4
106 #elif BYTES_PER_MPI_LIMB == 8
116 #error please implement for this limb size.
120 /* this is sub-optimal but we need to do the shift operation
121 * because the caller has to free the returned buffer */
122 for (p = buffer; !*p && *nbytes; p++, --*nbytes)
125 memmove(buffer, p, *nbytes);
129 EXPORT_SYMBOL_GPL(mpi_get_buffer);
132 * Use BUFFER to update MPI.
134 int mpi_set_buffer(MPI a, const void *xbuffer, unsigned nbytes, int sign)
136 const uint8_t *buffer = xbuffer, *p;
141 nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB;
142 if (RESIZE_IF_NEEDED(a, nlimbs) < 0)
146 for (i = 0, p = buffer + nbytes - 1; p >= buffer + BYTES_PER_MPI_LIMB;) {
147 #if BYTES_PER_MPI_LIMB == 4
148 alimb = (mpi_limb_t) *p--;
149 alimb |= (mpi_limb_t) *p-- << 8;
150 alimb |= (mpi_limb_t) *p-- << 16;
151 alimb |= (mpi_limb_t) *p-- << 24;
152 #elif BYTES_PER_MPI_LIMB == 8
153 alimb = (mpi_limb_t) *p--;
154 alimb |= (mpi_limb_t) *p-- << 8;
155 alimb |= (mpi_limb_t) *p-- << 16;
156 alimb |= (mpi_limb_t) *p-- << 24;
157 alimb |= (mpi_limb_t) *p-- << 32;
158 alimb |= (mpi_limb_t) *p-- << 40;
159 alimb |= (mpi_limb_t) *p-- << 48;
160 alimb |= (mpi_limb_t) *p-- << 56;
162 #error please implement for this limb size.
167 #if BYTES_PER_MPI_LIMB == 4
170 alimb |= (mpi_limb_t) *p-- << 8;
172 alimb |= (mpi_limb_t) *p-- << 16;
174 alimb |= (mpi_limb_t) *p-- << 24;
175 #elif BYTES_PER_MPI_LIMB == 8
176 alimb = (mpi_limb_t) *p--;
178 alimb |= (mpi_limb_t) *p-- << 8;
180 alimb |= (mpi_limb_t) *p-- << 16;
182 alimb |= (mpi_limb_t) *p-- << 24;
184 alimb |= (mpi_limb_t) *p-- << 32;
186 alimb |= (mpi_limb_t) *p-- << 40;
188 alimb |= (mpi_limb_t) *p-- << 48;
190 alimb |= (mpi_limb_t) *p-- << 56;
192 #error please implement for this limb size.
199 pr_emerg("MPI: mpi_set_buffer: Assertion failed (%d != %d)", i,
205 EXPORT_SYMBOL_GPL(mpi_set_buffer);