cfb8: Fix decrypt path
[gd/nettle] / 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 void
120 cnd_swap (mp_limb_t cnd, mp_limb_t *ap, mp_limb_t *bp, mp_size_t n)
121 {
122   mp_limb_t mask = - (mp_limb_t) (cnd != 0);
123   mp_size_t i;
124   for (i = 0; i < n; i++)
125     {
126       mp_limb_t a, b, t;
127       a = ap[i];
128       b = bp[i];
129       t = (a ^ b) & mask;
130       ap[i] = a ^ t;
131       bp[i] = b ^ t;
132     }
133 }
134
135 /* Additional convenience functions. */
136
137 int
138 mpz_limbs_cmp (mpz_srcptr a, const mp_limb_t *bp, mp_size_t bn)
139 {
140   mp_size_t an = mpz_size (a);
141   assert (mpz_sgn (a) >= 0);
142   assert (bn >= 0);
143
144   if (an < bn)
145     return -1;
146   if (an > bn)
147     return 1;
148   if (an == 0)
149     return 0;
150
151   return mpn_cmp (mpz_limbs_read(a), bp, an);
152 }
153
154 /* Get a pointer to an n limb area, for read-only operation. n must be
155    greater or equal to the current size, and the mpz is zero-padded if
156    needed. */
157 const mp_limb_t *
158 mpz_limbs_read_n (mpz_ptr x, mp_size_t n)
159 {
160   mp_size_t xn = mpz_size (x);
161   mp_ptr xp;
162   
163   assert (xn <= n);
164
165   xp = mpz_limbs_modify (x, n);
166
167   if (xn < n)
168     mpn_zero (xp + xn, n - xn);
169
170   return xp;
171 }
172
173 void
174 mpz_limbs_copy (mp_limb_t *xp, mpz_srcptr x, mp_size_t n)
175 {
176   mp_size_t xn = mpz_size (x);
177
178   assert (xn <= n);
179   mpn_copyi (xp, mpz_limbs_read (x), xn);
180   if (xn < n)
181     mpn_zero (xp + xn, n - xn);
182 }
183
184 void
185 mpz_set_n (mpz_t r, const mp_limb_t *xp, mp_size_t xn)
186 {
187   mpn_copyi (mpz_limbs_write (r, xn), xp, xn);
188   mpz_limbs_finish (r, xn);
189 }
190
191 void
192 mpn_set_base256 (mp_limb_t *rp, mp_size_t rn,
193                  const uint8_t *xp, size_t xn)
194 {
195   size_t xi;
196   mp_limb_t out;
197   unsigned bits;
198   for (xi = xn, out = bits = 0; xi > 0 && rn > 0; )
199     {
200       mp_limb_t in = xp[--xi];
201       out |= (in << bits) & GMP_NUMB_MASK;
202       bits += 8;
203       if (bits >= GMP_NUMB_BITS)
204         {
205           *rp++ = out;
206           rn--;
207
208           bits -= GMP_NUMB_BITS;
209           out = in >> (8 - bits);
210         }
211     }
212   if (rn > 0)
213     {
214       *rp++ = out;
215       if (--rn > 0)
216         mpn_zero (rp, rn);
217     }
218 }
219
220 void
221 mpn_set_base256_le (mp_limb_t *rp, mp_size_t rn,
222                     const uint8_t *xp, size_t xn)
223 {
224   size_t xi;
225   mp_limb_t out;
226   unsigned bits;
227   for (xi = 0, out = bits = 0; xi < xn && rn > 0; )
228     {
229       mp_limb_t in = xp[xi++];
230       out |= (in << bits) & GMP_NUMB_MASK;
231       bits += 8;
232       if (bits >= GMP_NUMB_BITS)
233         {
234           *rp++ = out;
235           rn--;
236
237           bits -= GMP_NUMB_BITS;
238           out = in >> (8 - bits);
239         }
240     }
241   if (rn > 0)
242     {
243       *rp++ = out;
244       if (--rn > 0)
245         mpn_zero (rp, rn);
246     }
247 }
248
249 void
250 mpn_get_base256 (uint8_t *rp, size_t rn,
251                  const mp_limb_t *xp, mp_size_t xn)
252 {
253   unsigned bits;
254   mp_limb_t in;
255   for (bits = in = 0; xn > 0 && rn > 0; )
256     {
257       if (bits >= 8)
258         {
259           rp[--rn] = in;
260           in >>= 8;
261           bits -= 8;
262         }
263       else
264         {
265           uint8_t old = in;
266           in = *xp++;
267           xn--;
268           rp[--rn] = old | (in << bits);
269           in >>= (8 - bits);
270           bits += GMP_NUMB_BITS - 8;
271         }
272     }
273   while (rn > 0)
274     {
275       rp[--rn] = in;
276       in >>= 8;
277     }
278 }
279
280 void
281 mpn_get_base256_le (uint8_t *rp, size_t rn,
282                     const mp_limb_t *xp, mp_size_t xn)
283 {
284   unsigned bits;
285   mp_limb_t in;
286   for (bits = in = 0; xn > 0 && rn > 0; )
287     {
288       if (bits >= 8)
289         {
290           *rp++ = in;
291           rn--;
292           in >>= 8;
293           bits -= 8;
294         }
295       else
296         {
297           uint8_t old = in;
298           in = *xp++;
299           xn--;
300           *rp++ = old | (in << bits);
301           rn--;
302           in >>= (8 - bits);
303           bits += GMP_NUMB_BITS - 8;
304         }
305     }
306   while (rn > 0)
307     {
308       *rp++ = in;
309       rn--;
310       in >>= 8;
311     }
312 }
313
314 mp_limb_t *
315 gmp_alloc_limbs (mp_size_t n)
316 {
317
318   void *(*alloc_func)(size_t);
319
320   assert (n > 0);
321
322   mp_get_memory_functions (&alloc_func, NULL, NULL);
323   return (mp_limb_t *) alloc_func ( (size_t) n * sizeof(mp_limb_t));
324 }
325
326 void
327 gmp_free_limbs (mp_limb_t *p, mp_size_t n)
328 {
329   void (*free_func)(void *, size_t);
330   assert (n > 0);
331   assert (p != 0);
332   mp_get_memory_functions (NULL, NULL, &free_func);
333
334   free_func (p, (size_t) n * sizeof(mp_limb_t));
335 }
336
337 void *
338 gmp_alloc(size_t n)
339 {
340   void *(*alloc_func)(size_t);
341   assert (n > 0);
342
343   mp_get_memory_functions(&alloc_func, NULL, NULL);
344
345   return alloc_func (n);
346 }
347
348 void
349 gmp_free(void *p, size_t n)
350 {
351   void (*free_func)(void *, size_t);
352   assert (n > 0);
353   assert (p != 0);
354   mp_get_memory_functions (NULL, NULL, &free_func);
355
356   free_func (p, (size_t) n);
357 }