See ChangeLog: Tue Dec 8 13:15:16 CET 1998 Werner Koch
[gnupg.git] / mpi / mpiutil.c
1 /* mpiutil.ac  -  Utility functions for MPI
2  *      Copyright (C) 1998 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 <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <assert.h>
26
27 #include "mpi.h"
28 #include "mpi-internal.h"
29 #include "memory.h"
30 #include "util.h"
31
32
33 #ifdef M_DEBUG
34   #undef mpi_alloc
35   #undef mpi_alloc_secure
36   #undef mpi_free
37 #endif
38
39 /****************
40  * fixme: It was a bad idea to use the number of limbs to allocate
41  *        because on a alpha the limbs are large but we normally need
42  *        integers of n bits - So we should chnage this to bits (or bytes).
43  *
44  *        But mpi_alloc is used in a lot of places :-)
45  */
46 MPI
47 #ifdef M_DEBUG
48 mpi_debug_alloc( unsigned nlimbs, const char *info )
49 #else
50 mpi_alloc( unsigned nlimbs )
51 #endif
52 {
53     MPI a;
54
55     if( DBG_MEMORY )
56         log_debug("mpi_alloc(%u)\n", nlimbs*BITS_PER_MPI_LIMB );
57   #ifdef M_DEBUG
58     a = m_debug_alloc( sizeof *a, info );
59     a->d = nlimbs? mpi_debug_alloc_limb_space( nlimbs, 0, info ) : NULL;
60   #else
61     a = m_alloc( sizeof *a );
62     a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 0 ) : NULL;
63   #endif
64     a->alloced = nlimbs;
65     a->nlimbs = 0;
66     a->sign = 0;
67     a->flags = 0;
68     a->nbits = 0;
69     return a;
70 }
71
72 void
73 mpi_m_check( MPI a )
74 {
75     m_check(a);
76     m_check(a->d);
77 }
78
79 MPI
80 #ifdef M_DEBUG
81 mpi_debug_alloc_secure( unsigned nlimbs, const char *info )
82 #else
83 mpi_alloc_secure( unsigned nlimbs )
84 #endif
85 {
86     MPI a;
87
88     if( DBG_MEMORY )
89         log_debug("mpi_alloc_secure(%u)\n", nlimbs*BITS_PER_MPI_LIMB );
90   #ifdef M_DEBUG
91     a = m_debug_alloc( sizeof *a, info );
92     a->d = nlimbs? mpi_debug_alloc_limb_space( nlimbs, 1, info ) : NULL;
93   #else
94     a = m_alloc( sizeof *a );
95     a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 1 ) : NULL;
96   #endif
97     a->alloced = nlimbs;
98     a->flags = 1;
99     a->nlimbs = 0;
100     a->sign = 0;
101     a->nbits = 0;
102     return a;
103 }
104
105
106 mpi_ptr_t
107 #ifdef M_DEBUG
108 mpi_debug_alloc_limb_space( unsigned nlimbs, int secure, const char *info )
109 #else
110 mpi_alloc_limb_space( unsigned nlimbs, int secure )
111 #endif
112 {
113     size_t len = nlimbs * sizeof(mpi_limb_t);
114
115     if( DBG_MEMORY )
116         log_debug("mpi_alloc_limb_space(%u)\n", (unsigned)len*8 );
117   #ifdef M_DEBUG
118     return secure? m_debug_alloc_secure(len, info):m_debug_alloc( len, info );
119   #else
120     return secure? m_alloc_secure( len ):m_alloc( len );
121   #endif
122 }
123
124 void
125 #ifdef M_DEBUG
126 mpi_debug_free_limb_space( mpi_ptr_t a, const char *info )
127 #else
128 mpi_free_limb_space( mpi_ptr_t a )
129 #endif
130 {
131     if( !a )
132         return;
133     if( DBG_MEMORY )
134         log_debug("mpi_free_limb_space of size %lu\n", (ulong)m_size(a)*8 );
135     m_free(a);
136 }
137
138
139 void
140 mpi_assign_limb_space( MPI a, mpi_ptr_t ap, unsigned nlimbs )
141 {
142     mpi_free_limb_space(a->d);
143     a->d = ap;
144     a->alloced = nlimbs;
145 }
146
147
148
149 /****************
150  * Resize the array of A to NLIMBS. the additional space is cleared
151  * (set to 0) [done by m_realloc()]
152  */
153 void
154 #ifdef M_DEBUG
155 mpi_debug_resize( MPI a, unsigned nlimbs, const char *info )
156 #else
157 mpi_resize( MPI a, unsigned nlimbs )
158 #endif
159 {
160     if( nlimbs <= a->alloced )
161         return; /* no need to do it */
162     /* FIXME: add realloc_secure based on a->secure */
163   #ifdef M_DEBUG
164     if( a->d )
165         a->d = m_debug_realloc(a->d, nlimbs * sizeof(mpi_limb_t), info );
166     else
167         a->d = m_debug_alloc_clear( nlimbs * sizeof(mpi_limb_t), info );
168   #else
169     if( a->d )
170         a->d = m_realloc(a->d, nlimbs * sizeof(mpi_limb_t) );
171     else
172         a->d = m_alloc_clear( nlimbs * sizeof(mpi_limb_t) );
173   #endif
174     a->alloced = nlimbs;
175 }
176
177 void
178 mpi_clear( MPI a )
179 {
180     a->nlimbs = 0;
181     a->nbits = 0;
182     a->flags = 0;
183 }
184
185
186 void
187 #ifdef M_DEBUG
188 mpi_debug_free( MPI a, const char *info )
189 #else
190 mpi_free( MPI a )
191 #endif
192 {
193     if( !a )
194         return;
195     if( DBG_MEMORY )
196         log_debug("mpi_free\n" );
197     if( a->flags & 4 )
198         m_free( a->d );
199     else {
200       #ifdef M_DEBUG
201         mpi_debug_free_limb_space(a->d, info);
202       #else
203         mpi_free_limb_space(a->d);
204       #endif
205     }
206     if( a->flags & ~7 )
207         log_bug("invalid flag value in mpi\n");
208     m_free(a);
209 }
210
211
212 void
213 mpi_set_secure( MPI a )
214 {
215     mpi_ptr_t ap, bp;
216
217     if( (a->flags & 1) )
218         return;
219     a->flags |= 1;
220     ap = a->d;
221     if( !a->nlimbs ) {
222         assert(!ap);
223         return;
224     }
225   #ifdef M_DEBUG
226     bp = mpi_debug_alloc_limb_space( a->nlimbs, 1, "set_secure" );
227   #else
228     bp = mpi_alloc_limb_space( a->nlimbs, 1 );
229   #endif
230     MPN_COPY( bp, ap, a->nlimbs );
231     a->d = bp;
232   #ifdef M_DEBUG
233     mpi_debug_free_limb_space(ap, "set_secure");
234   #else
235     mpi_free_limb_space(ap);
236   #endif
237 }
238
239
240 MPI
241 mpi_set_opaque( MPI a, void *p, int len )
242 {
243     if( !a ) {
244       #ifdef M_DEBUG
245         a = mpi_debug_alloc(0,"alloc_opaque");
246       #else
247         a = mpi_alloc(0);
248       #endif
249     }
250
251     if( a->flags & 4 )
252         m_free( a->d );
253     else {
254       #ifdef M_DEBUG
255         mpi_debug_free_limb_space(a->d, "alloc_opaque");
256       #else
257         mpi_free_limb_space(a->d);
258       #endif
259     }
260
261     a->d = p;
262     a->alloced = 0;
263     a->nlimbs = 0;
264     a->nbits = len;
265     a->flags = 4;
266     return a;
267 }
268
269
270 void *
271 mpi_get_opaque( MPI a, int *len )
272 {
273     if( !(a->flags & 4) )
274         log_bug("mpi_get_opaque on normal mpi\n");
275     if( len )
276         *len = a->nbits;
277     return a->d;
278 }
279
280
281 /****************
282  * Note: This copy function should not interpret the MPI
283  *       but copy it transparently.
284  */
285 MPI
286 #ifdef M_DEBUG
287 mpi_debug_copy( MPI a, const char *info )
288 #else
289 mpi_copy( MPI a )
290 #endif
291 {
292     int i;
293     MPI b;
294
295     if( a && (a->flags & 4) ) {
296         void *p = m_is_secure(a->d)? m_alloc_secure( a->nbits )
297                                    : m_alloc( a->nbits );
298         memcpy( p, a->d, a->nbits );
299         b = mpi_set_opaque( NULL, p, a->nbits );
300     }
301     else if( a ) {
302       #ifdef M_DEBUG
303         b = mpi_is_secure(a)? mpi_debug_alloc_secure( a->nlimbs, info )
304                             : mpi_debug_alloc( a->nlimbs, info );
305       #else
306         b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs )
307                             : mpi_alloc( a->nlimbs );
308       #endif
309         b->nlimbs = a->nlimbs;
310         b->sign = a->sign;
311         b->flags  = a->flags;
312         b->nbits = a->nbits;
313         for(i=0; i < b->nlimbs; i++ )
314             b->d[i] = a->d[i];
315     }
316     else
317         b = NULL;
318     return b;
319 }
320
321
322 void
323 mpi_set( MPI w, MPI u)
324 {
325     mpi_ptr_t wp, up;
326     mpi_size_t usize = u->nlimbs;
327     int usign = u->sign;
328
329     RESIZE_IF_NEEDED(w, usize);
330     wp = w->d;
331     up = u->d;
332     MPN_COPY( wp, up, usize );
333     w->nlimbs = usize;
334     w->nbits = u->nbits;
335     w->flags = u->flags;
336     w->sign = usign;
337 }
338
339
340 void
341 mpi_set_ui( MPI w, unsigned long u)
342 {
343     RESIZE_IF_NEEDED(w, 1);
344     w->d[0] = u;
345     w->nlimbs = u? 1:0;
346     w->sign = 0;
347     w->nbits = 0;
348     w->flags = 0;
349 }
350
351
352 MPI
353 mpi_alloc_set_ui( unsigned long u)
354 {
355   #ifdef M_DEBUG
356     MPI w = mpi_debug_alloc(1,"alloc_set_ui");
357   #else
358     MPI w = mpi_alloc(1);
359   #endif
360     w->d[0] = u;
361     w->nlimbs = u? 1:0;
362     w->sign = 0;
363     return w;
364 }
365
366
367 void
368 mpi_swap( MPI a, MPI b)
369 {
370     struct gcry_mpi tmp;
371
372     tmp = *a; *a = *b; *b = tmp;
373 }
374