Collected changes - see ChangeLogs
[libgcrypt.git] / mpi / mpiutil.c
1 /* mpiutil.ac  -  Utility functions for MPI
2  * Copyright (C) 1998, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
3  *
4  * This file is part of Libgcrypt.
5  *
6  * Libgcrypt is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as
8  * published by the Free Software Foundation; either version 2.1 of
9  * the License, or (at your option) any later version.
10  *
11  * Libgcrypt 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 Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License 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 gcry_mpi_t
39 _gcry_mpi_alloc( unsigned nlimbs )
40 {
41     gcry_mpi_t a;
42
43     a = gcry_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 _gcry_mpi_m_check( gcry_mpi_t a )
54 {
55     _gcry_check_heap(a);
56     _gcry_check_heap(a->d);
57 }
58
59 gcry_mpi_t
60 _gcry_mpi_alloc_secure( unsigned nlimbs )
61 {
62     gcry_mpi_t a;
63
64     a = gcry_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 _gcry_mpi_alloc_limb_space( unsigned int nlimbs, int secure )
77 {
78     mpi_ptr_t p;
79     size_t len;
80
81     len = (nlimbs ? nlimbs : 1) * sizeof (mpi_limb_t);
82     p = secure ? gcry_xmalloc_secure (len) : gcry_xmalloc (len);
83     if (! nlimbs)
84       *p = 0;
85
86     return p;
87 }
88
89 void
90 _gcry_mpi_free_limb_space( mpi_ptr_t a, unsigned int nlimbs)
91 {
92   if (a)
93     {
94       size_t len = nlimbs * sizeof(mpi_limb_t);
95       
96       /* If we have information on the number of allocated limbs, we
97          better wipe that space out.  This is a failsafe feature if
98          secure memory has been disabled or was not properly
99          implemented in user provided allocation functions. */
100       if (len)
101         wipememory (a, len);
102       gcry_free(a);
103     }
104 }
105
106
107 void
108 _gcry_mpi_assign_limb_space( gcry_mpi_t a, mpi_ptr_t ap, unsigned int nlimbs )
109 {
110   _gcry_mpi_free_limb_space (a->d, a->alloced);
111   a->d = ap;
112   a->alloced = nlimbs;
113 }
114
115
116
117 /****************
118  * Resize the array of A to NLIMBS. the additional space is cleared
119  * (set to 0) [done by gcry_realloc()]
120  */
121 void
122 _gcry_mpi_resize (gcry_mpi_t a, unsigned nlimbs)
123 {
124   if (nlimbs <= a->alloced)
125     return; /* no need to do it */
126
127   if (a->d)
128     a->d = gcry_xrealloc (a->d, nlimbs * sizeof (mpi_limb_t));
129   else
130     {
131       if (a->flags & 1)
132         /* Secure memory is wanted.  */
133         a->d = gcry_xcalloc_secure (nlimbs , sizeof (mpi_limb_t));
134       else
135         /* Standard memory.  */
136         a->d = gcry_xcalloc (nlimbs , sizeof (mpi_limb_t));
137     }
138   a->alloced = nlimbs;
139 }
140
141 void
142 _gcry_mpi_clear( gcry_mpi_t a )
143 {
144     a->nlimbs = 0;
145     a->flags = 0;
146 }
147
148
149 void
150 _gcry_mpi_free( gcry_mpi_t a )
151 {
152   if (!a )
153     return;
154   if ((a->flags & 4))
155     gcry_free( a->d );
156   else
157     {
158       _gcry_mpi_free_limb_space(a->d, a->alloced);
159     }
160   if ((a->flags & ~7))
161     log_bug("invalid flag value in mpi\n");
162   gcry_free(a);
163 }
164
165 static void
166 mpi_set_secure( gcry_mpi_t a )
167 {
168   mpi_ptr_t ap, bp;
169
170   if ( (a->flags & 1) )
171     return;
172   a->flags |= 1;
173   ap = a->d;
174   if (!a->nlimbs)
175     {
176       assert(!ap);
177       return;
178     }
179   bp = mpi_alloc_limb_space (a->nlimbs, 1);
180   MPN_COPY( bp, ap, a->nlimbs );
181   a->d = bp;
182   _gcry_mpi_free_limb_space (ap, a->alloced);
183 }
184
185
186 gcry_mpi_t
187 gcry_mpi_set_opaque( gcry_mpi_t a, void *p, unsigned int nbits )
188 {
189   if (!a) 
190     a = mpi_alloc(0);
191     
192   if( a->flags & 4 )
193     gcry_free( a->d );
194   else 
195     _gcry_mpi_free_limb_space (a->d, a->alloced);
196
197   a->d = p;
198   a->alloced = 0;
199   a->nlimbs = 0;
200   a->sign  = nbits;
201   a->flags = 4;
202   return a;
203 }
204
205
206 void *
207 gcry_mpi_get_opaque( gcry_mpi_t a, unsigned int *nbits )
208 {
209     if( !(a->flags & 4) )
210         log_bug("mpi_get_opaque on normal mpi\n");
211     if( nbits )
212         *nbits = a->sign;
213     return a->d;
214 }
215
216
217 /****************
218  * Note: This copy function should not interpret the MPI
219  *       but copy it transparently.
220  */
221 gcry_mpi_t
222 _gcry_mpi_copy( gcry_mpi_t a )
223 {
224     int i;
225     gcry_mpi_t b;
226
227     if( a && (a->flags & 4) ) {
228         void *p = gcry_is_secure(a->d)? gcry_xmalloc_secure( (a->sign+7)/8 )
229                                      : gcry_xmalloc( (a->sign+7)/8 );
230         memcpy( p, a->d, (a->sign+7)/8 );
231         b = gcry_mpi_set_opaque( NULL, p, a->sign );
232     }
233     else if( a ) {
234         b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs )
235                             : mpi_alloc( a->nlimbs );
236         b->nlimbs = a->nlimbs;
237         b->sign = a->sign;
238         b->flags  = a->flags;
239         for(i=0; i < b->nlimbs; i++ )
240             b->d[i] = a->d[i];
241     }
242     else
243         b = NULL;
244     return b;
245 }
246
247
248 /****************
249  * This function allocates an MPI which is optimized to hold
250  * a value as large as the one given in the argument and allocates it
251  * with the same flags as A.
252  */
253 gcry_mpi_t
254 _gcry_mpi_alloc_like( gcry_mpi_t a )
255 {
256     gcry_mpi_t b;
257
258     if( a && (a->flags & 4) ) {
259         int n = (a->sign+7)/8;
260         void *p = gcry_is_secure(a->d)? gcry_malloc_secure( n )
261                                      : gcry_malloc( n );
262         memcpy( p, a->d, n );
263         b = gcry_mpi_set_opaque( NULL, p, a->sign );
264     }
265     else if( a ) {
266         b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs )
267                             : mpi_alloc( a->nlimbs );
268         b->nlimbs = 0;
269         b->sign = 0;
270         b->flags = a->flags;
271     }
272     else
273         b = NULL;
274     return b;
275 }
276
277
278 void
279 _gcry_mpi_set( gcry_mpi_t w, gcry_mpi_t u)
280 {
281     mpi_ptr_t wp, up;
282     mpi_size_t usize = u->nlimbs;
283     int usign = u->sign;
284
285     RESIZE_IF_NEEDED(w, usize);
286     wp = w->d;
287     up = u->d;
288     MPN_COPY( wp, up, usize );
289     w->nlimbs = usize;
290     w->flags = u->flags;
291     w->sign = usign;
292 }
293
294
295 void
296 _gcry_mpi_set_ui( gcry_mpi_t w, unsigned long u)
297 {
298     RESIZE_IF_NEEDED(w, 1);
299     w->d[0] = u;
300     w->nlimbs = u? 1:0;
301     w->sign = 0;
302     w->flags = 0;
303 }
304
305 gcry_err_code_t
306 _gcry_mpi_get_ui (gcry_mpi_t w, unsigned long *u)
307 {
308   gcry_err_code_t err = GPG_ERR_NO_ERROR;
309   unsigned long x = 0;
310
311   if (w->nlimbs > 1)
312     err = GPG_ERR_TOO_LARGE;
313   else if (w->nlimbs == 1)
314     x = w->d[0];
315   else
316     x = 0;
317
318   if (! err)
319     *u = x;
320   
321   return err;
322 }
323
324 gcry_error_t
325 gcry_mpi_get_ui (gcry_mpi_t w, unsigned long *u)
326 {
327   gcry_err_code_t err = GPG_ERR_NO_ERROR;
328
329   err = _gcry_mpi_get_ui (w, u);
330   
331   return gcry_error (err);
332 }
333
334 gcry_mpi_t
335 _gcry_mpi_alloc_set_ui( unsigned long u)
336 {
337     gcry_mpi_t w = mpi_alloc(1);
338     w->d[0] = u;
339     w->nlimbs = u? 1:0;
340     w->sign = 0;
341     return w;
342 }
343
344
345 void
346 _gcry_mpi_swap( gcry_mpi_t a, gcry_mpi_t b)
347 {
348     struct gcry_mpi tmp;
349
350     tmp = *a; *a = *b; *b = tmp;
351 }
352
353 void
354 gcry_mpi_swap( gcry_mpi_t a, gcry_mpi_t b)
355 {
356   _gcry_mpi_swap (a, b);
357 }
358
359
360 gcry_mpi_t
361 gcry_mpi_new( unsigned int nbits )
362 {
363     return _gcry_mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1) / BITS_PER_MPI_LIMB );
364 }
365
366
367 gcry_mpi_t
368 gcry_mpi_snew( unsigned int nbits )
369 {
370     return _gcry_mpi_alloc_secure( (nbits+BITS_PER_MPI_LIMB-1) / BITS_PER_MPI_LIMB );
371 }
372
373 void
374 gcry_mpi_release( gcry_mpi_t a )
375 {
376     _gcry_mpi_free( a );
377 }
378
379 gcry_mpi_t
380 gcry_mpi_copy( const gcry_mpi_t a )
381 {
382     return _gcry_mpi_copy( (gcry_mpi_t)a );
383 }
384
385 gcry_mpi_t
386 gcry_mpi_set( gcry_mpi_t w, const gcry_mpi_t u )
387 {
388     if( !w )
389         w = _gcry_mpi_alloc( mpi_get_nlimbs(u) );
390     _gcry_mpi_set( w, (gcry_mpi_t)u );
391     return w;
392 }
393
394 gcry_mpi_t
395 gcry_mpi_set_ui( gcry_mpi_t w, unsigned long u )
396 {
397     if( !w )
398         w = _gcry_mpi_alloc(1);
399     _gcry_mpi_set_ui( w, u );
400     return w;
401 }
402
403
404 void
405 gcry_mpi_randomize( gcry_mpi_t w,
406                     unsigned int nbits, enum gcry_random_level level )
407 {
408   unsigned char *p;
409   size_t nbytes = (nbits+7)/8;
410   
411   if (level == GCRY_WEAK_RANDOM)
412     {
413       p = mpi_is_secure(w) ? gcry_xmalloc_secure (nbytes)
414                            : gcry_xmalloc (nbytes);
415       gcry_create_nonce (p, nbytes);
416     }
417   else
418     {
419       p = mpi_is_secure(w) ? gcry_random_bytes_secure (nbytes, level)
420                            : gcry_random_bytes (nbytes, level);
421     }
422   _gcry_mpi_set_buffer( w, p, nbytes, 0 );
423   gcry_free (p);
424 }
425
426
427 void
428 gcry_mpi_set_flag( gcry_mpi_t a, enum gcry_mpi_flag flag )
429 {
430     switch( flag ) {
431       case GCRYMPI_FLAG_SECURE:  mpi_set_secure(a); break;
432       case GCRYMPI_FLAG_OPAQUE:
433       default: log_bug("invalid flag value\n");
434     }
435 }
436
437 void
438 gcry_mpi_clear_flag( gcry_mpi_t a, enum gcry_mpi_flag flag )
439 {
440     switch( flag ) {
441       case GCRYMPI_FLAG_SECURE:
442       case GCRYMPI_FLAG_OPAQUE:
443       default: log_bug("invalid flag value\n");
444     }
445 }
446
447 int
448 gcry_mpi_get_flag( gcry_mpi_t a, enum gcry_mpi_flag flag )
449 {
450     switch( flag ) {
451       case GCRYMPI_FLAG_SECURE: return (a->flags & 1);
452       case GCRYMPI_FLAG_OPAQUE: return (a->flags & 4);
453       default: log_bug("invalid flag value\n");
454     }
455 }
456