Some configuration changes
[gnupg.git] / mpi / mpiutil.c
1 /* mpiutil.ac  -  Utility functions for MPI
2  *      Copyright (C) 1998, 2000 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 "g10lib.h"
28 #include "mpi-internal.h"
29 #include "memory.h"
30
31 /****************
32  * Note:  It was a bad idea to use the number of limbs to allocate
33  *        because on a alpha the limbs are large but we normally need
34  *        integers of n bits - So we should chnage this to bits (or bytes).
35  *
36  *        But mpi_alloc is used in a lot of places :-)
37  */
38 MPI
39 mpi_alloc( unsigned nlimbs )
40 {
41     MPI a;
42
43     a = g10_xmalloc( sizeof *a );
44     a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 0 ) : NULL;
45     a->alloced = nlimbs;
46     a->nlimbs = 0;
47     a->sign = 0;
48     a->flags = 0;
49     return a;
50 }
51
52 void
53 mpi_m_check( MPI a )
54 {
55     g10_check_heap(a);
56     g10_check_heap(a->d);
57 }
58
59 MPI
60 mpi_alloc_secure( unsigned nlimbs )
61 {
62     MPI a;
63
64     a = g10_xmalloc( sizeof *a );
65     a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 1 ) : NULL;
66     a->alloced = nlimbs;
67     a->flags = 1;
68     a->nlimbs = 0;
69     a->sign = 0;
70     return a;
71 }
72
73
74
75 mpi_ptr_t
76 mpi_alloc_limb_space( unsigned nlimbs, int secure )
77 {
78     size_t len = nlimbs * sizeof(mpi_limb_t);
79     mpi_ptr_t p;
80
81     p = secure? g10_xmalloc_secure( len ) : g10_xmalloc( len );
82
83     return p;
84 }
85
86 void
87 mpi_free_limb_space( mpi_ptr_t a )
88 {
89     if( !a )
90         return;
91     g10_free(a);
92 }
93
94
95 void
96 mpi_assign_limb_space( MPI a, mpi_ptr_t ap, unsigned nlimbs )
97 {
98     mpi_free_limb_space(a->d);
99     a->d = ap;
100     a->alloced = nlimbs;
101 }
102
103
104
105 /****************
106  * Resize the array of A to NLIMBS. the additional space is cleared
107  * (set to 0) [done by g10_realloc()]
108  */
109 void
110 mpi_resize( MPI a, unsigned nlimbs )
111 {
112     if( nlimbs <= a->alloced )
113         return; /* no need to do it */
114     /* Note: a->secure is not used - instead the realloc functions
115      * take care of it. Maybe we should drop a->secure completely
116      * and rely on a mpi_is_secure function, which would be
117      * a wrapper around g10_is_secure
118      */
119     if( a->d )
120         a->d = g10_xrealloc(a->d, nlimbs * sizeof(mpi_limb_t) );
121     else  /* FIXME: It may not be allocted in secure memory */
122         a->d = g10_xcalloc( nlimbs , sizeof(mpi_limb_t) );
123     a->alloced = nlimbs;
124 }
125
126 void
127 mpi_clear( MPI a )
128 {
129     a->nlimbs = 0;
130     a->flags = 0;
131 }
132
133
134 void
135 mpi_free( MPI a )
136 {
137     if( !a )
138         return;
139     if( a->flags & 4 )
140         g10_free( a->d );
141     else {
142         mpi_free_limb_space(a->d);
143     }
144     if( a->flags & ~7 )
145         log_bug("invalid flag value in mpi\n");
146     g10_free(a);
147 }
148
149 static void
150 mpi_set_secure( MPI a )
151 {
152     mpi_ptr_t ap, bp;
153
154     if( (a->flags & 1) )
155         return;
156     a->flags |= 1;
157     ap = a->d;
158     if( !a->nlimbs ) {
159         assert(!ap);
160         return;
161     }
162     bp = mpi_alloc_limb_space( a->nlimbs, 1 );
163     MPN_COPY( bp, ap, a->nlimbs );
164     a->d = bp;
165     mpi_free_limb_space(ap);
166 }
167
168
169 MPI
170 gcry_mpi_set_opaque( MPI a, void *p, unsigned int nbits )
171 {
172     if( !a ) {
173         a = mpi_alloc(0);
174     }
175
176     if( a->flags & 4 )
177         g10_free( a->d );
178     else {
179         mpi_free_limb_space(a->d);
180     }
181
182     a->d = p;
183     a->alloced = 0;
184     a->nlimbs = 0;
185     a->sign  = nbits;
186     a->flags = 4;
187     return a;
188 }
189
190
191 void *
192 gcry_mpi_get_opaque( MPI a, unsigned int *nbits )
193 {
194     if( !(a->flags & 4) )
195         log_bug("mpi_get_opaque on normal mpi\n");
196     if( nbits )
197         *nbits = a->sign;
198     return a->d;
199 }
200
201
202 /****************
203  * Note: This copy function should not interpret the MPI
204  *       but copy it transparently.
205  */
206 MPI
207 mpi_copy( MPI a )
208 {
209     int i;
210     MPI b;
211
212     if( a && (a->flags & 4) ) {
213         void *p = g10_is_secure(a->d)? g10_xmalloc_secure( (a->sign+7)/8 )
214                                      : g10_xmalloc( (a->sign+7)/8 );
215         memcpy( p, a->d, (a->sign+7)/8 );
216         b = gcry_mpi_set_opaque( NULL, p, a->sign );
217     }
218     else if( a ) {
219         b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs )
220                             : mpi_alloc( a->nlimbs );
221         b->nlimbs = a->nlimbs;
222         b->sign = a->sign;
223         b->flags  = a->flags;
224         for(i=0; i < b->nlimbs; i++ )
225             b->d[i] = a->d[i];
226     }
227     else
228         b = NULL;
229     return b;
230 }
231
232
233 /****************
234  * This function allocates an MPI which is optimized to hold
235  * a value as large as the one given in the arhgument and allocates it
236  * with the same flags as A.
237  */
238 MPI
239 mpi_alloc_like( MPI a )
240 {
241     MPI b;
242
243     if( a && (a->flags & 4) ) {
244         int n = (a->sign+7)/8;
245         void *p = g10_is_secure(a->d)? g10_malloc_secure( n )
246                                      : g10_malloc( n );
247         memcpy( p, a->d, n );
248         b = gcry_mpi_set_opaque( NULL, p, a->sign );
249     }
250     else if( a ) {
251         b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs )
252                             : mpi_alloc( a->nlimbs );
253         b->nlimbs = 0;
254         b->sign = 0;
255         b->flags = a->flags;
256     }
257     else
258         b = NULL;
259     return b;
260 }
261
262
263 void
264 mpi_set( MPI w, MPI u)
265 {
266     mpi_ptr_t wp, up;
267     mpi_size_t usize = u->nlimbs;
268     int usign = u->sign;
269
270     RESIZE_IF_NEEDED(w, usize);
271     wp = w->d;
272     up = u->d;
273     MPN_COPY( wp, up, usize );
274     w->nlimbs = usize;
275     w->flags = u->flags;
276     w->sign = usign;
277 }
278
279
280 void
281 mpi_set_ui( MPI w, unsigned long u)
282 {
283     RESIZE_IF_NEEDED(w, 1);
284     w->d[0] = u;
285     w->nlimbs = u? 1:0;
286     w->sign = 0;
287     w->flags = 0;
288 }
289
290
291 MPI
292 mpi_alloc_set_ui( unsigned long u)
293 {
294     MPI w = mpi_alloc(1);
295     w->d[0] = u;
296     w->nlimbs = u? 1:0;
297     w->sign = 0;
298     return w;
299 }
300
301
302 void
303 mpi_swap( MPI a, MPI b)
304 {
305     struct gcry_mpi tmp;
306
307     tmp = *a; *a = *b; *b = tmp;
308 }
309
310
311 GCRY_MPI
312 gcry_mpi_new( unsigned int nbits )
313 {
314     return mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1) / BITS_PER_MPI_LIMB );
315 }
316
317
318 GCRY_MPI
319 gcry_mpi_snew( unsigned int nbits )
320 {
321     return mpi_alloc_secure( (nbits+BITS_PER_MPI_LIMB-1) / BITS_PER_MPI_LIMB );
322 }
323
324 void
325 gcry_mpi_release( GCRY_MPI a )
326 {
327     mpi_free( a );
328 }
329
330 GCRY_MPI
331 gcry_mpi_copy( const GCRY_MPI a )
332 {
333     return mpi_copy( (GCRY_MPI)a );
334 }
335
336 GCRY_MPI
337 gcry_mpi_set( GCRY_MPI w, const GCRY_MPI u )
338 {
339     if( !w )
340         w = mpi_alloc( mpi_get_nlimbs(u) );
341     mpi_set( w, (GCRY_MPI)u );
342     return w;
343 }
344
345 GCRY_MPI
346 gcry_mpi_set_ui( GCRY_MPI w, unsigned long u )
347 {
348     if( !w )
349         w = mpi_alloc(1);
350     mpi_set_ui( w, u );
351     return w;
352 }
353
354
355 int
356 gcry_mpi_cmp( const GCRY_MPI u, const GCRY_MPI v )
357 {
358     return mpi_cmp( (GCRY_MPI)u, (GCRY_MPI)v );
359 }
360
361 int
362 gcry_mpi_cmp_ui( const GCRY_MPI u, unsigned long v )
363 {
364     return mpi_cmp_ui( (GCRY_MPI)u, v );
365 }
366
367
368 void
369 gcry_mpi_randomize( GCRY_MPI w,
370                     unsigned int nbits, enum gcry_random_level level )
371 {
372     char *p = mpi_is_secure(w) ? gcry_random_bytes( (nbits+7)/8, level )
373                                : gcry_random_bytes_secure( (nbits+7)/8, level );
374     mpi_set_buffer( w, p, (nbits+7)/8, 0 );
375     g10_free(p);
376 }
377
378
379 void
380 gcry_mpi_set_flag( GCRY_MPI a, enum gcry_mpi_flag flag )
381 {
382     switch( flag ) {
383       case GCRYMPI_FLAG_SECURE:  mpi_set_secure(a); break;
384       case GCRYMPI_FLAG_OPAQUE:
385       default: log_bug("invalid flag value\n");
386     }
387 }
388
389 void
390 gcry_mpi_clear_flag( GCRY_MPI a, enum gcry_mpi_flag flag )
391 {
392     switch( flag ) {
393       case GCRYMPI_FLAG_SECURE:
394       case GCRYMPI_FLAG_OPAQUE:
395       default: log_bug("invalid flag value\n");
396     }
397 }
398
399 int
400 gcry_mpi_get_flag( GCRY_MPI a, enum gcry_mpi_flag flag )
401 {
402     switch( flag ) {
403       case GCRYMPI_FLAG_SECURE: return (a->flags & 1);
404       case GCRYMPI_FLAG_OPAQUE: return (a->flags & 4);
405       default: log_bug("invalid flag value\n");
406     }
407 }
408
409