f9a5e358c7de297a5c7a1e49d0c294142e3d1570
[platform/upstream/nettle.git] / gmp-glue.c
1 /* gmp-glue.c
2
3    Copyright (C) 2013 Niels Möller
4    Copyright (C) 2013 Red Hat
5
6    This file is part of GNU Nettle.
7
8    GNU Nettle is free software: you can redistribute it and/or
9    modify it under the terms of either:
10
11      * the GNU Lesser General Public License as published by the Free
12        Software Foundation; either version 3 of the License, or (at your
13        option) any later version.
14
15    or
16
17      * the GNU General Public License as published by the Free
18        Software Foundation; either version 2 of the License, or (at your
19        option) any later version.
20
21    or both in parallel, as here.
22
23    GNU Nettle is distributed in the hope that it will be useful,
24    but WITHOUT ANY WARRANTY; without even the implied warranty of
25    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
26    General Public License for more details.
27
28    You should have received copies of the GNU General Public License and
29    the GNU Lesser General Public License along with this program.  If
30    not, see http://www.gnu.org/licenses/.
31 */
32
33 #if HAVE_CONFIG_H
34 # include "config.h"
35 #endif
36
37 #include <assert.h>
38 #include <stdlib.h>
39
40 #include "gmp-glue.h"
41
42 #if !GMP_HAVE_mpz_limbs_read
43
44 /* This implementation tries to make a minimal use of GMP internals.
45    We access and _mp_size and _mp_d, but not _mp_alloc. */
46
47 /* Use macros compatible with gmp-impl.h. */
48 #define ABS(x) ((x) >= 0 ? (x) : -(x))
49 #define PTR(x) ((x)->_mp_d)
50 #define SIZ(x) ((x)->_mp_size)
51 #define ABSIZ(x) ABS (SIZ (x))
52
53 #define MPN_NORMALIZE(xp, xn) do {              \
54     while ( (xn) > 0 && (xp)[xn-1] == 0)        \
55       (xn)--;                                   \
56   }  while (0)
57
58 /* NOTE: Makes an unnecessary realloc if allocation is already large
59    enough, but looking at _mp_alloc may break in future GMP
60    versions. */
61 #define MPZ_REALLOC(x, n) \
62   (ABSIZ(x) >= (n) ? PTR(x) : (_mpz_realloc ((x),(n)), PTR (x)))
63
64 #define MPZ_NEWALLOC MPZ_REALLOC
65
66 /* Read access to mpz numbers. */
67
68 /* Return limb pointer, for read-only operations. Use mpz_size to get
69    the number of limbs. */
70 const mp_limb_t *
71 mpz_limbs_read (mpz_srcptr x)
72 {
73   return PTR (x);
74 }
75
76 /* Write access to mpz numbers. */
77
78 /* Get a limb pointer for writing, previous contents may be
79    destroyed. */
80 mp_limb_t *
81 mpz_limbs_write (mpz_ptr x, mp_size_t n)
82 {
83   assert (n > 0);
84   return MPZ_NEWALLOC (x, n);
85 }
86
87 /* Get a limb pointer for writing, previous contents is intact. */
88 mp_limb_t *
89 mpz_limbs_modify (mpz_ptr x, mp_size_t n)
90 {
91   assert (n > 0);
92   return MPZ_REALLOC (x, n);
93 }
94
95 void
96 mpz_limbs_finish (mpz_ptr x, mp_size_t n)
97 {
98   assert (n >= 0);
99   MPN_NORMALIZE (PTR(x), n);
100
101   SIZ (x) = n;
102 }
103
104 /* Needs some ugly casts. */
105 mpz_srcptr
106 mpz_roinit_n (mpz_ptr x, const mp_limb_t *xp, mp_size_t xs)
107 {
108   mp_size_t xn = ABS (xs);
109   
110   MPN_NORMALIZE (xp, xn);
111
112   x->_mp_size = xs < 0 ? -xn : xn;
113   x->_mp_alloc = 0;
114   x->_mp_d = (mp_limb_t *) xp;
115   return x;
116 }
117 #endif /* !GMP_HAVE_mpz_limbs_read */
118
119 #if !GMP_HAVE_mpn_copyd
120 void
121 mpn_copyd (mp_ptr dst, mp_srcptr src, mp_size_t n)
122 {
123   mp_size_t i;
124   for (i = n - 1; i >= 0; i--)
125     dst[i] = src[i];
126 }
127
128 void
129 mpn_copyi (mp_ptr dst, mp_srcptr src, mp_size_t n)
130 {
131   mp_size_t i;
132   for (i = 0; i < n; i++)
133     dst[i] = src[i];
134 }
135
136 void
137 mpn_zero (mp_ptr ptr, mp_size_t n)
138 {
139   mp_size_t i;
140   for (i = 0; i < n; i++)
141     ptr[i] = 0;
142 }
143 #endif /* !GMP_HAVE_mpn_copyd */
144
145 void
146 cnd_swap (mp_limb_t cnd, mp_limb_t *ap, mp_limb_t *bp, mp_size_t n)
147 {
148   mp_limb_t mask = - (mp_limb_t) (cnd != 0);
149   mp_size_t i;
150   for (i = 0; i < n; i++)
151     {
152       mp_limb_t a, b, t;
153       a = ap[i];
154       b = bp[i];
155       t = (a ^ b) & mask;
156       ap[i] = a ^ t;
157       bp[i] = b ^ t;
158     }
159 }
160
161 /* Additional convenience functions. */
162
163 int
164 mpz_limbs_cmp (mpz_srcptr a, const mp_limb_t *bp, mp_size_t bn)
165 {
166   mp_size_t an = mpz_size (a);
167   assert (mpz_sgn (a) >= 0);
168   assert (bn >= 0);
169
170   if (an < bn)
171     return -1;
172   if (an > bn)
173     return 1;
174   if (an == 0)
175     return 0;
176
177   return mpn_cmp (mpz_limbs_read(a), bp, an);
178 }
179
180 /* Get a pointer to an n limb area, for read-only operation. n must be
181    greater or equal to the current size, and the mpz is zero-padded if
182    needed. */
183 const mp_limb_t *
184 mpz_limbs_read_n (mpz_ptr x, mp_size_t n)
185 {
186   mp_size_t xn = mpz_size (x);
187   mp_ptr xp;
188   
189   assert (xn <= n);
190
191   xp = mpz_limbs_modify (x, n);
192
193   if (xn < n)
194     mpn_zero (xp + xn, n - xn);
195
196   return xp;
197 }
198
199 void
200 mpz_limbs_copy (mp_limb_t *xp, mpz_srcptr x, mp_size_t n)
201 {
202   mp_size_t xn = mpz_size (x);
203
204   assert (xn <= n);
205   mpn_copyi (xp, mpz_limbs_read (x), xn);
206   if (xn < n)
207     mpn_zero (xp + xn, n - xn);
208 }
209
210 void
211 mpz_set_n (mpz_t r, const mp_limb_t *xp, mp_size_t xn)
212 {
213   mpn_copyi (mpz_limbs_write (r, xn), xp, xn);
214   mpz_limbs_finish (r, xn);
215 }
216
217 void
218 mpn_set_base256 (mp_limb_t *rp, mp_size_t rn,
219                  const uint8_t *xp, size_t xn)
220 {
221   size_t xi;
222   mp_limb_t out;
223   unsigned bits;
224   for (xi = xn, out = bits = 0; xi > 0 && rn > 0; )
225     {
226       mp_limb_t in = xp[--xi];
227       out |= (in << bits) & GMP_NUMB_MASK;
228       bits += 8;
229       if (bits >= GMP_NUMB_BITS)
230         {
231           *rp++ = out;
232           rn--;
233
234           bits -= GMP_NUMB_BITS;
235           out = in >> (8 - bits);
236         }
237     }
238   if (rn > 0)
239     {
240       *rp++ = out;
241       if (--rn > 0)
242         mpn_zero (rp, rn);
243     }
244 }
245
246 void
247 mpn_set_base256_le (mp_limb_t *rp, mp_size_t rn,
248                     const uint8_t *xp, size_t xn)
249 {
250   size_t xi;
251   mp_limb_t out;
252   unsigned bits;
253   for (xi = 0, out = bits = 0; xi < xn && rn > 0; )
254     {
255       mp_limb_t in = xp[xi++];
256       out |= (in << bits) & GMP_NUMB_MASK;
257       bits += 8;
258       if (bits >= GMP_NUMB_BITS)
259         {
260           *rp++ = out;
261           rn--;
262
263           bits -= GMP_NUMB_BITS;
264           out = in >> (8 - bits);
265         }
266     }
267   if (rn > 0)
268     {
269       *rp++ = out;
270       if (--rn > 0)
271         mpn_zero (rp, rn);
272     }
273 }
274
275 void
276 mpn_get_base256_le (uint8_t *rp, size_t rn,
277                     const mp_limb_t *xp, mp_size_t xn)
278 {
279   unsigned bits;
280   mp_limb_t in;
281   for (bits = in = 0; xn > 0 && rn > 0; )
282     {
283       if (bits >= 8)
284         {
285           *rp++ = in;
286           rn--;
287           in >>= 8;
288           bits -= 8;
289         }
290       else
291         {
292           uint8_t old = in;
293           in = *xp++;
294           xn--;
295           *rp++ = old | (in << bits);
296           rn--;
297           in >>= (8 - bits);
298           bits += GMP_NUMB_BITS - 8;
299         }
300     }
301   while (rn > 0)
302     {
303       *rp++ = in;
304       rn--;
305       in >>= 8;
306     }
307 }
308
309 mp_limb_t *
310 gmp_alloc_limbs (mp_size_t n)
311 {
312
313   void *(*alloc_func)(size_t);
314
315   assert (n > 0);
316
317   mp_get_memory_functions (&alloc_func, NULL, NULL);
318   return (mp_limb_t *) alloc_func ( (size_t) n * sizeof(mp_limb_t));
319 }
320
321 void
322 gmp_free_limbs (mp_limb_t *p, mp_size_t n)
323 {
324   void (*free_func)(void *, size_t);
325   assert (n > 0);
326   assert (p != 0);
327   mp_get_memory_functions (NULL, NULL, &free_func);
328
329   free_func (p, (size_t) n * sizeof(mp_limb_t));
330 }
331
332 void *
333 gmp_alloc(size_t n)
334 {
335   void *(*alloc_func)(size_t);
336   assert (n > 0);
337
338   mp_get_memory_functions(&alloc_func, NULL, NULL);
339
340   return alloc_func (n);
341 }
342
343 void
344 gmp_free(void *p, size_t n)
345 {
346   void (*free_func)(void *, size_t);
347   assert (n > 0);
348   assert (p != 0);
349   mp_get_memory_functions (NULL, NULL, &free_func);
350
351   free_func (p, (size_t) n);
352 }