20e1ff02aa5f97a51fa8b77c91804749f4ccba9e
[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).
120  */
121 void
122 _gcry_mpi_resize (gcry_mpi_t a, unsigned nlimbs)
123 {
124   size_t i;
125
126   if (nlimbs <= a->alloced)
127     {
128       /* We only need to clear the new space (this is a nop if the
129          limb space is already of the correct size. */
130       for (i=a->nlimbs; i < a->alloced; i++)
131         a->d[i] = 0;
132       return; 
133     }
134
135   /* Actually resize the limb space.  */
136   if (a->d)
137     {
138       a->d = gcry_xrealloc (a->d, nlimbs * sizeof (mpi_limb_t));
139       for (i=a->alloced; i < nlimbs; i++)
140         a->d[i] = 0;
141     }
142   else
143     {
144       if (a->flags & 1)
145         /* Secure memory is wanted.  */
146         a->d = gcry_xcalloc_secure (nlimbs , sizeof (mpi_limb_t));
147       else
148         /* Standard memory.  */
149         a->d = gcry_xcalloc (nlimbs , sizeof (mpi_limb_t));
150     }
151   a->alloced = nlimbs;
152 }
153
154 void
155 _gcry_mpi_clear( gcry_mpi_t a )
156 {
157     a->nlimbs = 0;
158     a->flags = 0;
159 }
160
161
162 void
163 _gcry_mpi_free( gcry_mpi_t a )
164 {
165   if (!a )
166     return;
167   if ((a->flags & 4))
168     gcry_free( a->d );
169   else
170     {
171       _gcry_mpi_free_limb_space(a->d, a->alloced);
172     }
173   if ((a->flags & ~7))
174     log_bug("invalid flag value in mpi\n");
175   gcry_free(a);
176 }
177
178 static void
179 mpi_set_secure( gcry_mpi_t a )
180 {
181   mpi_ptr_t ap, bp;
182
183   if ( (a->flags & 1) )
184     return;
185   a->flags |= 1;
186   ap = a->d;
187   if (!a->nlimbs)
188     {
189       assert(!ap);
190       return;
191     }
192   bp = mpi_alloc_limb_space (a->nlimbs, 1);
193   MPN_COPY( bp, ap, a->nlimbs );
194   a->d = bp;
195   _gcry_mpi_free_limb_space (ap, a->alloced);
196 }
197
198
199 gcry_mpi_t
200 gcry_mpi_set_opaque( gcry_mpi_t a, void *p, unsigned int nbits )
201 {
202   if (!a) 
203     a = mpi_alloc(0);
204     
205   if( a->flags & 4 )
206     gcry_free( a->d );
207   else 
208     _gcry_mpi_free_limb_space (a->d, a->alloced);
209
210   a->d = p;
211   a->alloced = 0;
212   a->nlimbs = 0;
213   a->sign  = nbits;
214   a->flags = 4;
215   return a;
216 }
217
218
219 void *
220 gcry_mpi_get_opaque( gcry_mpi_t a, unsigned int *nbits )
221 {
222     if( !(a->flags & 4) )
223         log_bug("mpi_get_opaque on normal mpi\n");
224     if( nbits )
225         *nbits = a->sign;
226     return a->d;
227 }
228
229
230 /****************
231  * Note: This copy function should not interpret the MPI
232  *       but copy it transparently.
233  */
234 gcry_mpi_t
235 _gcry_mpi_copy( gcry_mpi_t a )
236 {
237     int i;
238     gcry_mpi_t b;
239
240     if( a && (a->flags & 4) ) {
241         void *p = gcry_is_secure(a->d)? gcry_xmalloc_secure( (a->sign+7)/8 )
242                                      : gcry_xmalloc( (a->sign+7)/8 );
243         memcpy( p, a->d, (a->sign+7)/8 );
244         b = gcry_mpi_set_opaque( NULL, p, a->sign );
245     }
246     else if( a ) {
247         b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs )
248                             : mpi_alloc( a->nlimbs );
249         b->nlimbs = a->nlimbs;
250         b->sign = a->sign;
251         b->flags  = a->flags;
252         for(i=0; i < b->nlimbs; i++ )
253             b->d[i] = a->d[i];
254     }
255     else
256         b = NULL;
257     return b;
258 }
259
260
261 /****************
262  * This function allocates an MPI which is optimized to hold
263  * a value as large as the one given in the argument and allocates it
264  * with the same flags as A.
265  */
266 gcry_mpi_t
267 _gcry_mpi_alloc_like( gcry_mpi_t a )
268 {
269     gcry_mpi_t b;
270
271     if( a && (a->flags & 4) ) {
272         int n = (a->sign+7)/8;
273         void *p = gcry_is_secure(a->d)? gcry_malloc_secure( n )
274                                      : gcry_malloc( n );
275         memcpy( p, a->d, n );
276         b = gcry_mpi_set_opaque( NULL, p, a->sign );
277     }
278     else if( a ) {
279         b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs )
280                             : mpi_alloc( a->nlimbs );
281         b->nlimbs = 0;
282         b->sign = 0;
283         b->flags = a->flags;
284     }
285     else
286         b = NULL;
287     return b;
288 }
289
290
291 void
292 _gcry_mpi_set( gcry_mpi_t w, gcry_mpi_t u)
293 {
294     mpi_ptr_t wp, up;
295     mpi_size_t usize = u->nlimbs;
296     int usign = u->sign;
297
298     RESIZE_IF_NEEDED(w, usize);
299     wp = w->d;
300     up = u->d;
301     MPN_COPY( wp, up, usize );
302     w->nlimbs = usize;
303     w->flags = u->flags;
304     w->sign = usign;
305 }
306
307
308 void
309 _gcry_mpi_set_ui( gcry_mpi_t w, unsigned long u)
310 {
311     RESIZE_IF_NEEDED(w, 1);
312     w->d[0] = u;
313     w->nlimbs = u? 1:0;
314     w->sign = 0;
315     w->flags = 0;
316 }
317
318 gcry_err_code_t
319 _gcry_mpi_get_ui (gcry_mpi_t w, unsigned long *u)
320 {
321   gcry_err_code_t err = GPG_ERR_NO_ERROR;
322   unsigned long x = 0;
323
324   if (w->nlimbs > 1)
325     err = GPG_ERR_TOO_LARGE;
326   else if (w->nlimbs == 1)
327     x = w->d[0];
328   else
329     x = 0;
330
331   if (! err)
332     *u = x;
333   
334   return err;
335 }
336
337 gcry_error_t
338 gcry_mpi_get_ui (gcry_mpi_t w, unsigned long *u)
339 {
340   gcry_err_code_t err = GPG_ERR_NO_ERROR;
341
342   err = _gcry_mpi_get_ui (w, u);
343   
344   return gcry_error (err);
345 }
346
347 gcry_mpi_t
348 _gcry_mpi_alloc_set_ui( unsigned long u)
349 {
350     gcry_mpi_t w = mpi_alloc(1);
351     w->d[0] = u;
352     w->nlimbs = u? 1:0;
353     w->sign = 0;
354     return w;
355 }
356
357
358 void
359 _gcry_mpi_swap( gcry_mpi_t a, gcry_mpi_t b)
360 {
361     struct gcry_mpi tmp;
362
363     tmp = *a; *a = *b; *b = tmp;
364 }
365
366 void
367 gcry_mpi_swap( gcry_mpi_t a, gcry_mpi_t b)
368 {
369   _gcry_mpi_swap (a, b);
370 }
371
372
373 gcry_mpi_t
374 gcry_mpi_new( unsigned int nbits )
375 {
376     return _gcry_mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1) / BITS_PER_MPI_LIMB );
377 }
378
379
380 gcry_mpi_t
381 gcry_mpi_snew( unsigned int nbits )
382 {
383     return _gcry_mpi_alloc_secure( (nbits+BITS_PER_MPI_LIMB-1) / BITS_PER_MPI_LIMB );
384 }
385
386 void
387 gcry_mpi_release( gcry_mpi_t a )
388 {
389     _gcry_mpi_free( a );
390 }
391
392 gcry_mpi_t
393 gcry_mpi_copy( const gcry_mpi_t a )
394 {
395     return _gcry_mpi_copy( (gcry_mpi_t)a );
396 }
397
398 gcry_mpi_t
399 gcry_mpi_set( gcry_mpi_t w, const gcry_mpi_t u )
400 {
401     if( !w )
402         w = _gcry_mpi_alloc( mpi_get_nlimbs(u) );
403     _gcry_mpi_set( w, (gcry_mpi_t)u );
404     return w;
405 }
406
407 gcry_mpi_t
408 gcry_mpi_set_ui( gcry_mpi_t w, unsigned long u )
409 {
410     if( !w )
411         w = _gcry_mpi_alloc(1);
412     _gcry_mpi_set_ui( w, u );
413     return w;
414 }
415
416
417 void
418 gcry_mpi_randomize( gcry_mpi_t w,
419                     unsigned int nbits, enum gcry_random_level level )
420 {
421   unsigned char *p;
422   size_t nbytes = (nbits+7)/8;
423   
424   if (level == GCRY_WEAK_RANDOM)
425     {
426       p = mpi_is_secure(w) ? gcry_xmalloc_secure (nbytes)
427                            : gcry_xmalloc (nbytes);
428       gcry_create_nonce (p, nbytes);
429     }
430   else
431     {
432       p = mpi_is_secure(w) ? gcry_random_bytes_secure (nbytes, level)
433                            : gcry_random_bytes (nbytes, level);
434     }
435   _gcry_mpi_set_buffer( w, p, nbytes, 0 );
436   gcry_free (p);
437 }
438
439
440 void
441 gcry_mpi_set_flag( gcry_mpi_t a, enum gcry_mpi_flag flag )
442 {
443     switch( flag ) {
444       case GCRYMPI_FLAG_SECURE:  mpi_set_secure(a); break;
445       case GCRYMPI_FLAG_OPAQUE:
446       default: log_bug("invalid flag value\n");
447     }
448 }
449
450 void
451 gcry_mpi_clear_flag( gcry_mpi_t a, enum gcry_mpi_flag flag )
452 {
453   (void)a; /* Not yet used. */
454
455   switch (flag)
456     {
457     case GCRYMPI_FLAG_SECURE:
458     case GCRYMPI_FLAG_OPAQUE:
459     default: log_bug("invalid flag value\n");
460     }
461 }
462
463 int
464 gcry_mpi_get_flag( gcry_mpi_t a, enum gcry_mpi_flag flag )
465 {
466   switch (flag)
467     {
468     case GCRYMPI_FLAG_SECURE: return (a->flags & 1);
469     case GCRYMPI_FLAG_OPAQUE: return (a->flags & 4);
470     default: log_bug("invalid flag value\n");
471     }
472   /*NOTREACHED*/
473   return 0;
474 }
475