New configure option --disable-endian-check.
[libgcrypt.git] / mpi / mpicoder.c
1 /* mpicoder.c  -  Coder for the external representation of MPIs
2  * Copyright (C) 1998, 1999, 2000, 2001, 2002,
3  *               2003 Free Software Foundation, Inc.
4  *
5  * This file is part of Libgcrypt.
6  *
7  * Libgcrypt is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU Lesser General Public License as
9  * published by the Free Software Foundation; either version 2.1 of
10  * the License, or (at your option) any later version.
11  *
12  * Libgcrypt is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA   
20  */
21
22 #include <config.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <assert.h>
27
28 #include "mpi-internal.h"
29 #include "g10lib.h"
30
31 #define MAX_EXTERN_MPI_BITS 16384
32
33
34 static gcry_mpi_t
35 mpi_read_from_buffer (const unsigned char *buffer, unsigned *ret_nread,
36                       int secure)
37 {
38   int i, j;
39   unsigned int nbits, nbytes, nlimbs, nread=0;
40   mpi_limb_t a;
41   gcry_mpi_t val = MPI_NULL;
42   
43   if ( *ret_nread < 2 )
44     goto leave;
45   nbits = buffer[0] << 8 | buffer[1];
46   if ( nbits > MAX_EXTERN_MPI_BITS )
47     {
48       log_error ("mpi too large (%u bits)\n", nbits);
49       goto leave;
50     }
51   else if( !nbits ) 
52     {
53       log_error ("an mpi of size 0 is not allowed\n");
54       goto leave;
55     }
56   buffer += 2;
57   nread = 2;
58
59   nbytes = (nbits+7) / 8;
60   nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB;
61   val = secure? mpi_alloc_secure (nlimbs) : mpi_alloc( nlimbs );
62   i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
63   i %= BYTES_PER_MPI_LIMB;
64   j= val->nlimbs = nlimbs;
65   val->sign = 0;
66   for ( ; j > 0; j-- )
67     {
68       a = 0;
69       for (; i < BYTES_PER_MPI_LIMB; i++ ) 
70         {
71           if ( ++nread > *ret_nread )
72             log_bug ("mpi larger than buffer");
73           a <<= 8;
74           a |= *buffer++;
75         }
76       i = 0;
77       val->d[j-1] = a;
78     }
79   
80  leave:
81   *ret_nread = nread;
82   return val;
83 }
84
85
86 /****************
87  * Make an mpi from a hex character string.
88  */
89 static int
90 mpi_fromstr(gcry_mpi_t val, const char *str)
91 {
92     int sign=0, prepend_zero=0, i, j, c, c1, c2;
93     unsigned nbits, nbytes, nlimbs;
94     mpi_limb_t a;
95
96     if( *str == '-' ) {
97         sign = 1;
98         str++;
99     }
100
101     /* skip optional hex prefix */
102     if ( *str == '0' && str[1] == 'x' ) {
103         str += 2;
104     }
105
106     nbits = strlen(str)*4;
107     if( nbits % 8 )
108         prepend_zero = 1;
109     nbytes = (nbits+7) / 8;
110     nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB;
111     if( val->alloced < nlimbs )
112         mpi_resize(val, nlimbs );
113     i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
114     i %= BYTES_PER_MPI_LIMB;
115     j= val->nlimbs = nlimbs;
116     val->sign = sign;
117     for( ; j > 0; j-- ) {
118         a = 0;
119         for(; i < BYTES_PER_MPI_LIMB; i++ ) {
120             if( prepend_zero ) {
121                 c1 = '0';
122                 prepend_zero = 0;
123             }
124             else
125                 c1 = *str++;
126             assert(c1);
127             c2 = *str++;
128             assert(c2);
129             if( c1 >= '0' && c1 <= '9' )
130                 c = c1 - '0';
131             else if( c1 >= 'a' && c1 <= 'f' )
132                 c = c1 - 'a' + 10;
133             else if( c1 >= 'A' && c1 <= 'F' )
134                 c = c1 - 'A' + 10;
135             else {
136                 mpi_clear(val);
137                 return 1;
138             }
139             c <<= 4;
140             if( c2 >= '0' && c2 <= '9' )
141                 c |= c2 - '0';
142             else if( c2 >= 'a' && c2 <= 'f' )
143                 c |= c2 - 'a' + 10;
144             else if( c2 >= 'A' && c2 <= 'F' )
145                 c |= c2 - 'A' + 10;
146             else {
147                 mpi_clear(val);
148                 return 1;
149             }
150             a <<= 8;
151             a |= c;
152         }
153         i = 0;
154         val->d[j-1] = a;
155     }
156
157     return 0;
158 }
159
160
161 /* Dump the value of A in a format suitable for debugging to
162    Libgcrypt's logging stream.  Note that one leading space but no
163    trailing space or linefeed will be printed.  It is okay to pass
164    NULL for A. */
165 void 
166 gcry_mpi_dump (const gcry_mpi_t a)
167 {
168   int i;
169
170   log_printf (" ");
171   if (!a)
172     log_printf ("[MPI_NULL]");
173   else 
174     {
175       if (a->sign)
176         log_printf ( "-");
177 #if BYTES_PER_MPI_LIMB == 2
178 # define X "4"
179 #elif BYTES_PER_MPI_LIMB == 4
180 # define X "8"
181 #elif BYTES_PER_MPI_LIMB == 8
182 # define X "16"
183 #elif BYTES_PER_MPI_LIMB == 16
184 # define X "32"
185 #else
186 # error please define the format here
187 #endif
188       for (i=a->nlimbs; i > 0 ; i-- )
189         {
190           log_printf (i != a->nlimbs? "%0" X "lX":"%lX", (ulong)a->d[i-1]);
191         }
192 #undef X
193       if (!a->nlimbs)
194         log_printf ("0");
195     }
196 }
197
198 /* Convience function used internally. */
199 void
200 _gcry_log_mpidump (const char *text, gcry_mpi_t a)
201 {
202   log_printf ("%s:", text);
203   gcry_mpi_dump (a);
204   log_printf ("\n");
205 }
206
207
208 /****************
209  * Return an m_alloced buffer with the MPI (msb first).
210  * NBYTES receives the length of this buffer. Caller must free the
211  * return string (This function does return a 0 byte buffer with NBYTES
212  * set to zero if the value of A is zero. If sign is not NULL, it will
213  * be set to the sign of the A.
214  */
215 static byte *
216 do_get_buffer( gcry_mpi_t a, unsigned *nbytes, int *sign, int force_secure )
217 {
218     byte *p, *buffer;
219     mpi_limb_t alimb;
220     int i;
221     size_t n;
222
223     if( sign )
224         *sign = a->sign;
225     *nbytes = a->nlimbs * BYTES_PER_MPI_LIMB;
226     n = *nbytes? *nbytes:1; /* allocate at least one byte */
227     p = buffer = force_secure || mpi_is_secure(a) ? gcry_xmalloc_secure(n)
228                                                   : gcry_xmalloc(n);
229
230     for(i=a->nlimbs-1; i >= 0; i-- ) {
231         alimb = a->d[i];
232 #if BYTES_PER_MPI_LIMB == 4
233         *p++ = alimb >> 24;
234         *p++ = alimb >> 16;
235         *p++ = alimb >>  8;
236         *p++ = alimb      ;
237 #elif BYTES_PER_MPI_LIMB == 8
238         *p++ = alimb >> 56;
239         *p++ = alimb >> 48;
240         *p++ = alimb >> 40;
241         *p++ = alimb >> 32;
242         *p++ = alimb >> 24;
243         *p++ = alimb >> 16;
244         *p++ = alimb >>  8;
245         *p++ = alimb      ;
246 #else
247         #error please implement for this limb size.
248 #endif
249     }
250
251     /* this is sub-optimal but we need to do the shift oepration because
252      * the caller has to free the returned buffer */
253     for(p=buffer; !*p && *nbytes; p++, --*nbytes )
254         ;
255     if( p != buffer )
256         memmove(buffer,p, *nbytes);
257     return buffer;
258 }
259
260
261 byte *
262 _gcry_mpi_get_buffer( gcry_mpi_t a, unsigned *nbytes, int *sign )
263 {
264     return do_get_buffer( a, nbytes, sign, 0 );
265 }
266
267 byte *
268 _gcry_mpi_get_secure_buffer( gcry_mpi_t a, unsigned *nbytes, int *sign )
269 {
270     return do_get_buffer( a, nbytes, sign, 1 );
271 }
272
273 /****************
274  * Use BUFFER to update MPI.
275  */
276 void
277 _gcry_mpi_set_buffer( gcry_mpi_t a, const byte *buffer, unsigned nbytes, int sign )
278 {
279     const byte *p;
280     mpi_limb_t alimb;
281     int nlimbs;
282     int i;
283
284     nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB;
285     RESIZE_IF_NEEDED(a, nlimbs);
286     a->sign = sign;
287
288     for(i=0, p = buffer+nbytes-1; p >= buffer+BYTES_PER_MPI_LIMB; ) {
289 #if BYTES_PER_MPI_LIMB == 4
290         alimb  = *p--       ;
291         alimb |= *p-- <<  8 ;
292         alimb |= *p-- << 16 ;
293         alimb |= *p-- << 24 ;
294 #elif BYTES_PER_MPI_LIMB == 8
295         alimb  = (mpi_limb_t)*p--       ;
296         alimb |= (mpi_limb_t)*p-- <<  8 ;
297         alimb |= (mpi_limb_t)*p-- << 16 ;
298         alimb |= (mpi_limb_t)*p-- << 24 ;
299         alimb |= (mpi_limb_t)*p-- << 32 ;
300         alimb |= (mpi_limb_t)*p-- << 40 ;
301         alimb |= (mpi_limb_t)*p-- << 48 ;
302         alimb |= (mpi_limb_t)*p-- << 56 ;
303 #else
304         #error please implement for this limb size.
305 #endif
306         a->d[i++] = alimb;
307     }
308     if( p >= buffer ) {
309 #if BYTES_PER_MPI_LIMB == 4
310         alimb  = *p--       ;
311         if( p >= buffer ) alimb |= *p-- <<  8 ;
312         if( p >= buffer ) alimb |= *p-- << 16 ;
313         if( p >= buffer ) alimb |= *p-- << 24 ;
314 #elif BYTES_PER_MPI_LIMB == 8
315         alimb  = (mpi_limb_t)*p-- ;
316         if( p >= buffer ) alimb |= (mpi_limb_t)*p-- <<  8 ;
317         if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 16 ;
318         if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 24 ;
319         if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 32 ;
320         if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 40 ;
321         if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 48 ;
322         if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 56 ;
323 #else
324         #error please implement for this limb size.
325 #endif
326         a->d[i++] = alimb;
327     }
328     a->nlimbs = i;
329     assert( i == nlimbs );
330 }
331
332
333
334 /* Convert the external representation of an integer stored in BUFFER
335    with a length of BUFLEN into a newly create MPI returned in
336    RET_MPI.  If NBYTES is not NULL, it will receive the number of
337    bytes actually scanned after a successful operation. */
338 gcry_error_t
339 gcry_mpi_scan( struct gcry_mpi **ret_mpi, enum gcry_mpi_format format,
340                const void *buffer_arg, size_t buflen, size_t *nscanned )
341 {
342     const unsigned char *buffer = (const unsigned char*)buffer_arg;
343     struct gcry_mpi *a = NULL;
344     unsigned int len;
345     int secure = (buffer && gcry_is_secure (buffer));
346
347     if (format == GCRYMPI_FMT_SSH)
348       len = 0;
349     else
350       len = buflen;
351
352     if( format == GCRYMPI_FMT_STD ) {
353         const byte *s = buffer;
354
355         a = secure? mpi_alloc_secure ((len+BYTES_PER_MPI_LIMB-1)
356                                       /BYTES_PER_MPI_LIMB)
357                   : mpi_alloc ((len+BYTES_PER_MPI_LIMB-1)/BYTES_PER_MPI_LIMB);
358         if( len ) { /* not zero */
359             a->sign = *s & 0x80;
360             if( a->sign ) {
361                 /* FIXME: we have to convert from 2compl to magnitude format */
362                 mpi_free(a);
363                 return gcry_error (GPG_ERR_INTERNAL);
364             }
365             else
366                 _gcry_mpi_set_buffer( a, s, len, 0 );
367         }
368         if( ret_mpi ) {
369             mpi_normalize ( a );
370             *ret_mpi = a;
371         }
372         else
373             mpi_free(a);
374         return gcry_error (GPG_ERR_NO_ERROR);
375     }
376     else if( format == GCRYMPI_FMT_USG ) {
377         a = secure? mpi_alloc_secure ((len+BYTES_PER_MPI_LIMB-1)
378                                       /BYTES_PER_MPI_LIMB)
379                   : mpi_alloc ((len+BYTES_PER_MPI_LIMB-1)/BYTES_PER_MPI_LIMB);
380
381         if( len )  /* not zero */
382             _gcry_mpi_set_buffer( a, buffer, len, 0 );
383         if( ret_mpi ) {
384             mpi_normalize ( a );
385             *ret_mpi = a;
386         }
387         else
388             mpi_free(a);
389         return gcry_error (GPG_ERR_NO_ERROR);
390     }
391     else if( format == GCRYMPI_FMT_PGP ) {
392         a = mpi_read_from_buffer (buffer, &len, secure);
393         if( nscanned )
394             *nscanned = len;
395         if( ret_mpi && a ) {
396             mpi_normalize ( a );
397             *ret_mpi = a;
398         }
399         else
400             mpi_free(a);
401         return gcry_error (a ? GPG_ERR_NO_ERROR : GPG_ERR_INV_OBJ);
402     }
403     else if( format == GCRYMPI_FMT_SSH ) {
404         const unsigned char *s = buffer;
405         size_t n;
406
407         if( len && len < 4 )
408             return gcry_error (GPG_ERR_TOO_SHORT);
409         n = s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3];
410         s += 4; 
411         if (len)
412           len -= 4;
413         if( len && n > len )
414             return gcry_error (GPG_ERR_TOO_LARGE); /* or should it be
415                                                       too_short */
416
417         a = secure? mpi_alloc_secure ((n+BYTES_PER_MPI_LIMB-1)
418                                       /BYTES_PER_MPI_LIMB)
419                   : mpi_alloc ((n+BYTES_PER_MPI_LIMB-1)/BYTES_PER_MPI_LIMB);
420         if( n ) { /* not zero */
421             a->sign = *s & 0x80;
422             if( a->sign ) {
423                 /* FIXME: we have to convert from 2compl to magnitude format */
424                 mpi_free(a);
425                 return gcry_error (GPG_ERR_INTERNAL);
426             }
427             else
428                 _gcry_mpi_set_buffer( a, s, n, 0 );
429         }
430         if( nscanned )
431             *nscanned = n+4;
432         if( ret_mpi ) {
433             mpi_normalize ( a );
434             *ret_mpi = a;
435         }
436         else
437             mpi_free(a);
438         return gcry_error (GPG_ERR_NO_ERROR);
439     }
440     else if( format == GCRYMPI_FMT_HEX ) {
441         if( buflen )
442             return gcry_error (GPG_ERR_INV_ARG); /* can only handle C
443                                                     strings for now */
444         a = secure? mpi_alloc_secure (0) : mpi_alloc(0);
445         if( mpi_fromstr ( a, (const char *)buffer ) )
446             return gcry_error (GPG_ERR_INV_OBJ);
447         if( ret_mpi ) {
448             mpi_normalize ( a );
449             *ret_mpi = a;
450         }
451         else
452             mpi_free(a);
453         return gcry_error (GPG_ERR_NO_ERROR);
454     }
455     else
456         return gcry_error (GPG_ERR_INV_ARG);
457 }
458
459 /* Convert the big integer A into the external representation
460    described by FORMAT and store it in the provided BUFFER which has
461    been allocated by the user with a size of BUFLEN bytes.  NWRITTEN
462    receives the actual length of the external representation unless it
463    has been passed as NULL.  BUFFER may be NULL to query the required
464    length.*/
465 gcry_error_t
466 gcry_mpi_print( enum gcry_mpi_format format,
467                 unsigned char *buffer, size_t buflen,
468                 size_t *nwritten, struct gcry_mpi *a)
469 {
470     unsigned int nbits = mpi_get_nbits(a);
471     size_t len;
472     size_t dummy_nwritten;
473
474     if (!nwritten)
475       nwritten = &dummy_nwritten;
476
477     len = buflen;
478     *nwritten = 0;
479     if( format == GCRYMPI_FMT_STD ) {
480         unsigned char *tmp;
481         int extra = 0;
482         unsigned int n;
483
484         if( a->sign )
485             return gcry_error (GPG_ERR_INTERNAL); /* can't handle it yet */
486
487         tmp = _gcry_mpi_get_buffer( a, &n, NULL );
488         if( n && (*tmp & 0x80) ) {
489             n++;
490             extra=1;
491         }
492
493         if (buffer && n > len) {
494             /* The provided buffer is too short. */
495             gcry_free (tmp);
496             return gcry_error (GPG_ERR_TOO_SHORT);  
497         }
498         if( buffer ) {
499             unsigned char *s = buffer;
500             if( extra )
501                 *s++ = 0;
502
503             memcpy( s, tmp, n-extra );
504         }
505         gcry_free(tmp);
506         *nwritten = n;
507         return gcry_error (GPG_ERR_NO_ERROR);
508     }
509     else if( format == GCRYMPI_FMT_USG ) {
510         unsigned int n = (nbits + 7)/8;
511
512         /* we ignore the sign for this format */
513         /* FIXME: for performance reasons we should put this into
514          * mpi_aprint becuase we can then use the buffer directly */
515         if (buffer && n > len)
516             return gcry_error (GPG_ERR_TOO_SHORT);  /* the provided buffer is too short */
517         if( buffer ) {
518             unsigned char *tmp;
519             tmp = _gcry_mpi_get_buffer( a, &n, NULL );
520             memcpy( buffer, tmp, n );
521             gcry_free(tmp);
522         }
523         *nwritten = n;
524         return gcry_error (GPG_ERR_NO_ERROR);
525     }
526     else if( format == GCRYMPI_FMT_PGP ) {
527         unsigned int n = (nbits + 7)/8;
528
529         if( a->sign )
530             return gcry_error (GPG_ERR_INV_ARG); /* pgp format can only handle unsigned */
531
532         if (buffer && n+2 > len)
533             return gcry_error (GPG_ERR_TOO_SHORT);  /* the provided buffer is too short */
534         if( buffer ) {
535             unsigned char *tmp;
536             unsigned char *s = buffer;
537             s[0] = nbits >> 8;
538             s[1] = nbits;
539
540             tmp = _gcry_mpi_get_buffer( a, &n, NULL );
541             memcpy( s+2, tmp, n );
542             gcry_free(tmp);
543         }
544         *nwritten = n+2;
545         return gcry_error (GPG_ERR_NO_ERROR);
546     }
547     else if( format == GCRYMPI_FMT_SSH ) {
548         unsigned char *tmp;
549         int extra = 0;
550         unsigned int n;
551
552         if( a->sign )
553             return gcry_error (GPG_ERR_INTERNAL); /* can't handle it yet */
554
555         tmp = _gcry_mpi_get_buffer( a, &n, NULL );
556         if( n && (*tmp & 0x80) ) {
557             n++;
558             extra=1;
559         }
560
561         if (buffer && n+4 > len) {
562             gcry_free(tmp);
563             return gcry_error (GPG_ERR_TOO_SHORT);  /* the provided buffer is too short */
564         }
565         if( buffer ) {
566             byte *s = buffer;
567             *s++ = n >> 24;
568             *s++ = n >> 16;
569             *s++ = n >> 8;
570             *s++ = n;
571             if( extra )
572                 *s++ = 0;
573
574             memcpy( s, tmp, n-extra );
575         }
576         gcry_free(tmp);
577         *nwritten = 4+n;
578         return gcry_error (GPG_ERR_NO_ERROR);
579     }
580     else if( format == GCRYMPI_FMT_HEX ) {
581         byte *tmp;
582         int i;
583         int extra = 0;
584         unsigned int n=0;
585
586         tmp = _gcry_mpi_get_buffer( a, &n, NULL );
587         if( !n || (*tmp & 0x80) )
588             extra=2;
589
590         if(buffer && 2*n + extra + !!a->sign + 1 > len) {
591             gcry_free(tmp);
592             return gcry_error (GPG_ERR_TOO_SHORT);  /* the provided buffer is too short */
593         }
594         if( buffer ) {
595             byte *s = buffer;
596             if( a->sign )
597                 *s++ = '-';
598             if( extra ) {
599                 *s++ = '0';
600                 *s++ = '0';
601             }
602
603             for(i=0; i < n; i++ ) {
604                 unsigned int c = tmp[i];
605                 *s++ = (c >> 4) < 10? '0'+(c>>4) : 'A'+(c>>4)-10 ;
606                 c &= 15;
607                 *s++ = c < 10? '0'+c : 'A'+c-10 ;
608             }
609             *s++ = 0;
610             *nwritten = s - buffer;
611         }
612         else {
613             *nwritten = 2*n + extra + !!a->sign + 1;
614         }
615         gcry_free(tmp);
616         return gcry_error (GPG_ERR_NO_ERROR);
617     }
618     else
619         return gcry_error (GPG_ERR_INV_ARG);
620 }
621
622 /****************
623  * Like gcry_mpi_print but this function allocates the buffer itself.
624  * The caller has to supply the address of a pointer. NWRITTEN may be
625  * NULL.
626  */
627 gcry_error_t
628 gcry_mpi_aprint( enum gcry_mpi_format format,
629                  unsigned char **buffer, size_t *nwritten,
630                  struct gcry_mpi *a )
631 {
632     size_t n;
633     gcry_error_t rc;
634
635     *buffer = NULL;
636     rc = gcry_mpi_print( format, NULL, 0, &n, a );
637     if( rc )
638         return rc;
639     *buffer = mpi_is_secure(a) ? gcry_xmalloc_secure( n ) : gcry_xmalloc( n );
640     rc = gcry_mpi_print( format, *buffer, n, &n, a );
641     if( rc ) {
642         gcry_free(*buffer);
643         *buffer = NULL;
644     }
645     else if( nwritten )
646         *nwritten = n;
647     return rc;
648 }
649