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