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