See ChangeLog: Mon May 31 19:41:10 CEST 1999 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  * Note:  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     /* Note: a->secure is not used - instead the realloc functions
163      * take care of it. Maybe we should drop a->secure completely
164      * and rely on a mpi_is_secure function, which would be
165      * a wrapper around m_is_secure
166      */
167   #ifdef M_DEBUG
168     if( a->d )
169         a->d = m_debug_realloc(a->d, nlimbs * sizeof(mpi_limb_t), info );
170     else
171         a->d = m_debug_alloc_clear( nlimbs * sizeof(mpi_limb_t), info );
172   #else
173     if( a->d )
174         a->d = m_realloc(a->d, nlimbs * sizeof(mpi_limb_t) );
175     else
176         a->d = m_alloc_clear( nlimbs * sizeof(mpi_limb_t) );
177   #endif
178     a->alloced = nlimbs;
179 }
180
181 void
182 mpi_clear( MPI a )
183 {
184     a->nlimbs = 0;
185     a->nbits = 0;
186     a->flags = 0;
187 }
188
189
190 void
191 #ifdef M_DEBUG
192 mpi_debug_free( MPI a, const char *info )
193 #else
194 mpi_free( MPI a )
195 #endif
196 {
197     if( !a )
198         return;
199     if( DBG_MEMORY )
200         log_debug("mpi_free\n" );
201     if( a->flags & 4 )
202         m_free( a->d );
203     else {
204       #ifdef M_DEBUG
205         mpi_debug_free_limb_space(a->d, info);
206       #else
207         mpi_free_limb_space(a->d);
208       #endif
209     }
210     if( a->flags & ~7 )
211         log_bug("invalid flag value in mpi\n");
212     m_free(a);
213 }
214
215
216 void
217 mpi_set_secure( MPI a )
218 {
219     mpi_ptr_t ap, bp;
220
221     if( (a->flags & 1) )
222         return;
223     a->flags |= 1;
224     ap = a->d;
225     if( !a->nlimbs ) {
226         assert(!ap);
227         return;
228     }
229   #ifdef M_DEBUG
230     bp = mpi_debug_alloc_limb_space( a->nlimbs, 1, "set_secure" );
231   #else
232     bp = mpi_alloc_limb_space( a->nlimbs, 1 );
233   #endif
234     MPN_COPY( bp, ap, a->nlimbs );
235     a->d = bp;
236   #ifdef M_DEBUG
237     mpi_debug_free_limb_space(ap, "set_secure");
238   #else
239     mpi_free_limb_space(ap);
240   #endif
241 }
242
243
244 MPI
245 mpi_set_opaque( MPI a, void *p, int len )
246 {
247     if( !a ) {
248       #ifdef M_DEBUG
249         a = mpi_debug_alloc(0,"alloc_opaque");
250       #else
251         a = mpi_alloc(0);
252       #endif
253     }
254
255     if( a->flags & 4 )
256         m_free( a->d );
257     else {
258       #ifdef M_DEBUG
259         mpi_debug_free_limb_space(a->d, "alloc_opaque");
260       #else
261         mpi_free_limb_space(a->d);
262       #endif
263     }
264
265     a->d = p;
266     a->alloced = 0;
267     a->nlimbs = 0;
268     a->nbits = len;
269     a->flags = 4;
270     return a;
271 }
272
273
274 void *
275 mpi_get_opaque( MPI a, int *len )
276 {
277     if( !(a->flags & 4) )
278         log_bug("mpi_get_opaque on normal mpi\n");
279     if( len )
280         *len = a->nbits;
281     return a->d;
282 }
283
284
285 /****************
286  * Note: This copy function should not interpret the MPI
287  *       but copy it transparently.
288  */
289 MPI
290 #ifdef M_DEBUG
291 mpi_debug_copy( MPI a, const char *info )
292 #else
293 mpi_copy( MPI a )
294 #endif
295 {
296     int i;
297     MPI b;
298
299     if( a && (a->flags & 4) ) {
300         void *p = m_is_secure(a->d)? m_alloc_secure( a->nbits )
301                                    : m_alloc( a->nbits );
302         memcpy( p, a->d, a->nbits );
303         b = mpi_set_opaque( NULL, p, a->nbits );
304     }
305     else if( a ) {
306       #ifdef M_DEBUG
307         b = mpi_is_secure(a)? mpi_debug_alloc_secure( a->nlimbs, info )
308                             : mpi_debug_alloc( a->nlimbs, info );
309       #else
310         b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs )
311                             : mpi_alloc( a->nlimbs );
312       #endif
313         b->nlimbs = a->nlimbs;
314         b->sign = a->sign;
315         b->flags  = a->flags;
316         b->nbits = a->nbits;
317         for(i=0; i < b->nlimbs; i++ )
318             b->d[i] = a->d[i];
319     }
320     else
321         b = NULL;
322     return b;
323 }
324
325
326 /****************
327  * This function allocates an MPI which is optimized to hold
328  * a value as large as the one given in the arhgument and allocates it
329  * with the same flags as A.
330  */
331 MPI
332 mpi_alloc_like( MPI a )
333 {
334     MPI b;
335
336     if( a && (a->flags & 4) ) {
337         void *p = m_is_secure(a->d)? m_alloc_secure( a->nbits )
338                                    : m_alloc( a->nbits );
339         memcpy( p, a->d, a->nbits );
340         b = mpi_set_opaque( NULL, p, a->nbits );
341     }
342     else if( a ) {
343         b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs )
344                             : mpi_alloc( a->nlimbs );
345         b->nlimbs = 0;
346         b->sign = 0;
347         b->flags = a->flags;
348         b->nbits = 0;
349     }
350     else
351         b = NULL;
352     return b;
353 }
354
355
356 void
357 mpi_set( MPI w, MPI u)
358 {
359     mpi_ptr_t wp, up;
360     mpi_size_t usize = u->nlimbs;
361     int usign = u->sign;
362
363     RESIZE_IF_NEEDED(w, usize);
364     wp = w->d;
365     up = u->d;
366     MPN_COPY( wp, up, usize );
367     w->nlimbs = usize;
368     w->nbits = u->nbits;
369     w->flags = u->flags;
370     w->sign = usign;
371 }
372
373
374 void
375 mpi_set_ui( MPI w, unsigned long u)
376 {
377     RESIZE_IF_NEEDED(w, 1);
378     w->d[0] = u;
379     w->nlimbs = u? 1:0;
380     w->sign = 0;
381     w->nbits = 0;
382     w->flags = 0;
383 }
384
385
386 MPI
387 mpi_alloc_set_ui( unsigned long u)
388 {
389   #ifdef M_DEBUG
390     MPI w = mpi_debug_alloc(1,"alloc_set_ui");
391   #else
392     MPI w = mpi_alloc(1);
393   #endif
394     w->d[0] = u;
395     w->nlimbs = u? 1:0;
396     w->sign = 0;
397     return w;
398 }
399
400
401 void
402 mpi_swap( MPI a, MPI b)
403 {
404     struct gcry_mpi tmp;
405
406     tmp = *a; *a = *b; *b = tmp;
407 }
408