Revert "Merge branch 'upstream' into tizen"
[platform/upstream/nettle.git] / gmp-glue.c
1 /* gmp-glue.c */
2
3 /* nettle, low-level cryptographics library
4  *
5  * Copyright (C) 2013 Niels Möller
6  *  
7  * The nettle library is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU Lesser General Public License as published by
9  * the Free Software Foundation; either version 2.1 of the License, or (at your
10  * option) any later version.
11  * 
12  * The nettle library is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
15  * License for more details.
16  * 
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with the nettle library; see the file COPYING.LIB.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20  * MA 02111-1301, USA.
21  */
22
23 #if HAVE_CONFIG_H
24 # include "config.h"
25 #endif
26
27 #include <assert.h>
28 #include <stdlib.h>
29
30 #include "gmp-glue.h"
31
32 #if !GMP_HAVE_mpz_limbs_read
33
34 /* This implementation tries to make a minimal use of GMP internals.
35    We access and _mp_size and _mp_d, but not _mp_alloc. */
36
37 /* Use macros compatible with gmp-impl.h. */
38 #define ABS(x) ((x) >= 0 ? (x) : -(x))
39 #define PTR(x) ((x)->_mp_d)
40 #define SIZ(x) ((x)->_mp_size)
41 #define ABSIZ(x) ABS (SIZ (x))
42
43 #define MPN_NORMALIZE(xp, xn) do {              \
44     while ( (xn) > 0 && (xp)[xn-1] == 0)        \
45       (xn)--;                                   \
46   }  while (0)
47
48 /* NOTE: Makes an unnecessary realloc if allocation is already large
49    enough, but looking at _mp_alloc may break in future GMP
50    versions. */
51 #define MPZ_REALLOC(x, n) \
52   (ABSIZ(x) >= (n) ? PTR(x) : (_mpz_realloc ((x),(n)), PTR (x)))
53
54 #define MPZ_NEWALLOC MPZ_REALLOC
55
56 /* Read access to mpz numbers. */
57
58 /* Return limb pointer, for read-only operations. Use mpz_size to get
59    the number of limbs. */
60 const mp_limb_t *
61 mpz_limbs_read (mpz_srcptr x)
62 {
63   return PTR (x);
64 }
65
66 /* Write access to mpz numbers. */
67
68 /* Get a limb pointer for writing, previous contents may be
69    destroyed. */
70 mp_limb_t *
71 mpz_limbs_write (mpz_ptr x, mp_size_t n)
72 {
73   assert (n > 0);
74   return MPZ_NEWALLOC (x, n);
75 }
76
77 /* Get a limb pointer for writing, previous contents is intact. */
78 mp_limb_t *
79 mpz_limbs_modify (mpz_ptr x, mp_size_t n)
80 {
81   assert (n > 0);
82   return MPZ_REALLOC (x, n);
83 }
84
85 void
86 mpz_limbs_finish (mpz_ptr x, mp_size_t n)
87 {
88   assert (n >= 0);
89   MPN_NORMALIZE (PTR(x), n);
90
91   SIZ (x) = n;
92 }
93
94 /* Needs some ugly casts. */
95 mpz_srcptr
96 mpz_roinit_n (mpz_ptr x, const mp_limb_t *xp, mp_size_t xs)
97 {
98   mp_size_t xn = ABS (xs);
99   
100   MPN_NORMALIZE (xp, xn);
101
102   x->_mp_size = xs < 0 ? -xn : xn;
103   x->_mp_alloc = 0;
104   x->_mp_d = (mp_limb_t *) xp;
105   return x;
106 }
107 #endif /* !GMP_HAVE_mpz_limbs_read */
108
109 #if !GMP_HAVE_mpn_copyd
110 void
111 mpn_copyd (mp_ptr dst, mp_srcptr src, mp_size_t n)
112 {
113   mp_size_t i;
114   for (i = n - 1; i >= 0; i--)
115     dst[i] = src[i];
116 }
117
118 void
119 mpn_copyi (mp_ptr dst, mp_srcptr src, mp_size_t n)
120 {
121   mp_size_t i;
122   for (i = 0; i < n; i++)
123     dst[i] = src[i];
124 }
125
126 void
127 mpn_zero (mp_ptr ptr, mp_size_t n)
128 {
129   mp_size_t i;
130   for (i = 0; i < n; i++)
131     ptr[i] = 0;
132 }
133 #endif /* !GMP_HAVE_mpn_copyd */
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 mp_limb_t *
221 gmp_alloc_limbs (mp_size_t n)
222 {
223
224   void *(*alloc_func)(size_t);
225
226   assert (n > 0);
227
228   mp_get_memory_functions (&alloc_func, NULL, NULL);
229   return (mp_limb_t *) alloc_func ( (size_t) n * sizeof(mp_limb_t));
230 }
231
232 void
233 gmp_free_limbs (mp_limb_t *p, mp_size_t n)
234 {
235   void (*free_func)(void *, size_t);
236   assert (n > 0);
237   assert (p != 0);
238   mp_get_memory_functions (NULL, NULL, &free_func);
239
240   free_func (p, (size_t) n * sizeof(mp_limb_t));
241 }