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