initially checkin
[gnupg.git] / mpi / mpicoder.c
1 /* mpicoder.c  -  Coder for the external representation of MPIs
2  *      Copyright (c) 1997 by Werner Koch (dd9jn)
3  *
4  * This file is part of G10.
5  *
6  * G10 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  * G10 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 <stdlib.h>
24 #include <assert.h>
25
26 #include "mpi.h"
27 #include "iobuf.h"
28 #include "memory.h"
29 #include "util.h"
30
31 #ifdef M_DEBUG
32   #undef mpi_decode
33   #undef mpi_decode_buffer
34 #endif
35
36 #define MAX_EXTERN_MPI_BITS 16384
37
38 /****************
39  * write an mpi to out.
40  */
41 int
42 mpi_encode( IOBUF out, MPI a )
43 {
44     u16 dummy;
45     return mpi_encode_csum( out, a, &dummy );
46 }
47
48 int
49 mpi_encode_csum( IOBUF out, MPI a, u16 *csum )
50 {
51     int i;
52     byte c;
53     unsigned nbits = a->nlimbs * BITS_PER_MPI_LIMB;
54     mpi_limb_t limb;
55
56 #if BYTES_PER_MPI_LIMB != 4
57   #error Make this function work with other LIMB sizes
58 #endif
59     if( nbits > MAX_EXTERN_MPI_BITS )
60         log_bug("mpi_encode: mpi too large (%u bits)\n", nbits);
61     iobuf_put(out, (c=nbits >>8) ); *csum += c;
62     iobuf_put(out, (c=nbits) );     *csum += c;
63     for(i=a->nlimbs-1; i >= 0; i-- ) {
64         limb = a->d[i];
65         iobuf_put(out, (c=limb >> 24) ); *csum += c;
66         iobuf_put(out, (c=limb >> 16) ); *csum += c;
67         iobuf_put(out, (c=limb >>  8) ); *csum += c;
68         iobuf_put(out, (c=limb      ) ); *csum += c;
69     }
70     return 0;
71 }
72
73 /****************
74  * encode the MPI into a newly allocated buffer, the buffer is
75  * so constructed, that it can be used for mpi_write. The caller
76  * must free the returned buffer. The buffer is allocated in the same
77  * type of memory space as A is.
78  */
79 byte *
80 mpi_encode_buffer( MPI a )
81 {
82     abort();
83     return NULL;
84 }
85
86 /****************
87  * write an mpi to out. This is a special function to handle
88  * encrypted values. It simply writes the buffer a to OUT.
89  * A is a special buffer, starting with 2 bytes giving it's length
90  * (in big endian order) and 2 bytes giving it's length in bits (also
91  * big endian)
92  */
93 int
94 mpi_write( IOBUF out, byte *a)
95 {
96     u16 dummy;
97     return mpi_write_csum( out, a, &dummy );
98 }
99
100 int
101 mpi_write_csum( IOBUF out, byte *a, u16 *csum)
102 {
103     int rc;
104     unsigned n;
105
106     n = *a++ << 8;
107     n |= *a++;
108     rc = iobuf_write(out, a, n );
109     for( ; n; n--, a++ )
110         *csum += *a;
111     return rc;
112 }
113
114 /****************
115  * Decode an external representation and return an MPI
116  * The external format is a 16 bit unsigned value stored in network byte order,
117  * giving the number of bits for the following integer. The integer is stored
118  * with MSB first (left padded with zeroes to align on a byte boundary).
119  */
120 MPI
121 #ifdef M_DEBUG
122 mpi_debug_decode(IOBUF inp, unsigned *ret_nread, const char *info)
123 #else
124 mpi_decode(IOBUF inp, unsigned *ret_nread)
125 #endif
126 {
127     int c, i, j;
128     unsigned nbits, nbytes, nlimbs, nread=0;
129     mpi_limb_t a;
130     MPI val = MPI_NULL;
131
132     if( (c = iobuf_get(inp)) == -1 )
133         goto leave;
134     nbits = c << 8;
135     if( (c = iobuf_get(inp)) == -1 )
136         goto leave;
137     nbits |= c;
138     if( nbits > MAX_EXTERN_MPI_BITS ) {
139         log_error("mpi too large (%u bits)\n", nbits);
140         goto leave;
141     }
142     nread = 2;
143
144     nbytes = (nbits+7) / 8;
145     nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB;
146   #ifdef M_DEBUG
147     val = mpi_debug_alloc( nlimbs, info );
148   #else
149     val = mpi_alloc( nlimbs );
150   #endif
151     i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
152     i %= BYTES_PER_MPI_LIMB;
153     j= val->nlimbs = nlimbs;
154     val->sign = 0;
155     for( ; j > 0; j-- ) {
156         a = 0;
157         for(; i < BYTES_PER_MPI_LIMB; i++ ) {
158             a <<= 8;
159             a |= iobuf_get(inp) & 0xff; nread++;
160         }
161         i = 0;
162         val->d[j-1] = a;
163     }
164
165   leave:
166     if( nread > *ret_nread )
167         log_error("Ooops: mpi crosses packet border");
168     else
169         *ret_nread = nread;
170     return val;
171 }
172
173
174 /****************
175  * Decode an MPI from the buffer, the buffer starts with two bytes giving
176  * the length of the data to follow, the original data follows.
177  * The MPI is alloced from secure MPI space
178  */
179 MPI
180 #ifdef M_DEBUG
181 mpi_debug_decode_buffer(byte *buffer, const char *info )
182 #else
183 mpi_decode_buffer(byte *buffer )
184 #endif
185 {
186     int i, j;
187     u16 buflen;
188     unsigned nbits, nbytes, nlimbs;
189     mpi_limb_t a;
190     byte *p = buffer;
191     MPI val;
192
193     if( !buffer )
194         log_bug("mpi_decode_buffer: no buffer\n");
195     buflen = *p++ << 8;
196     buflen |= *p++;
197     nbits = *p++ << 8;
198     nbits |= *p++;
199     nbytes = (nbits+7) / 8;
200     if( nbytes+2 != buflen )
201         log_bug("mpi_decode_buffer: length conflict\n");
202     nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB;
203   #ifdef M_DEBUG
204     val = mpi_debug_alloc_secure( nlimbs, info );
205   #else
206     val = mpi_alloc_secure( nlimbs );
207   #endif
208     i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
209     i %= BYTES_PER_MPI_LIMB;
210     j= val->nlimbs = nlimbs;
211     val->sign = 0;
212     for( ; j > 0; j-- ) {
213         a = 0;
214         for(; i < BYTES_PER_MPI_LIMB; i++ ) {
215             a <<= 8;
216             a |= *p++;
217         }
218         i = 0;
219         val->d[j-1] = a;
220     }
221     return val;
222 }
223
224
225 /****************
226  * Read a MPI from the external medium and return it in a newly allocated
227  * buffer (This buffer is allocated in the secure memory space, because
228  * we properly need this to decipher this string).
229  * Return: the allocated string and in RET_NREAD the number of bytes
230  *         read (including the 2 length bytes), the returned buffer will
231  *         be prefixed with two bytes describing the length of the following
232  *         data.
233  */
234 byte *
235 mpi_read(IOBUF inp, unsigned *ret_nread)
236 {
237     int c;
238     u16 buflen;
239     unsigned nbits, nbytes, nread;
240     byte *p, *buf;
241
242     if( (c = iobuf_get(inp)) == -1 )
243         return NULL;
244     nbits = c << 8;
245     if( (c = iobuf_get(inp)) == -1 )
246         return NULL;
247     nbits |= c;
248     if( nbits > MAX_EXTERN_MPI_BITS ) {
249         log_error("mpi too large (%u bits)\n", nbits);
250         return NULL;
251     }
252     nread = 2;
253
254     nbytes = (nbits+7) / 8;
255     buflen = nbytes + 2;
256     p = buf = m_alloc_secure( buflen+2 );
257     *p++ = buflen >> 8;
258     *p++ = buflen & 0xff;
259     *p++ = nbits >> 8;
260     *p++ = nbits & 0xff;
261     for( ; nbytes ; nbytes--, nread++ )
262         *p++ = iobuf_get(inp) & 0xff;
263
264     if( nread > *ret_nread )
265         log_error("Ooops: mpi crosses packet border");
266     else
267         *ret_nread = nread;
268     return buf;
269 }
270
271
272 /****************
273  * Make a mpi from a character string.
274  */
275 int
276 mpi_fromstr(MPI val, const char *str)
277 {
278     int hexmode=0, sign=0, prepend_zero=0, i, j, c, c1, c2;
279     unsigned nbits, nbytes, nlimbs;
280     mpi_limb_t a;
281
282     if( *str == '-' ) {
283         sign = 1;
284         str++;
285     }
286     if( *str == '0' && str[1] == 'x' )
287         hexmode = 1;
288     else
289         return 1; /* other bases are not yet supported */
290     str += 2;
291
292     nbits = strlen(str)*4;
293     if( nbits % 8 )
294         prepend_zero = 1;
295     nbytes = (nbits+7) / 8;
296     nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB;
297     if( val->alloced < nlimbs )
298         mpi_resize(val, nlimbs );
299     i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
300     i %= BYTES_PER_MPI_LIMB;
301     j= val->nlimbs = nlimbs;
302     val->sign = sign;
303     for( ; j > 0; j-- ) {
304         a = 0;
305         for(; i < BYTES_PER_MPI_LIMB; i++ ) {
306             if( prepend_zero ) {
307                 c1 = '0';
308                 prepend_zero = 0;
309             }
310             else
311                 c1 = *str++;
312             assert(c1);
313             c2 = *str++;
314             assert(c2);
315             if( c1 >= '0' && c1 <= '9' )
316                 c = c1 - '0';
317             else if( c1 >= 'a' && c1 <= 'f' )
318                 c = c1 - 'a' + 10;
319             else if( c1 >= 'A' && c1 <= 'F' )
320                 c = c1 - 'A' + 10;
321             else {
322                 mpi_clear(val);
323                 return 1;
324             }
325             c <<= 4;
326             if( c2 >= '0' && c2 <= '9' )
327                 c |= c2 - '0';
328             else if( c2 >= 'a' && c2 <= 'f' )
329                 c |= c2 - 'a' + 10;
330             else if( c2 >= 'A' && c2 <= 'F' )
331                 c |= c2 - 'A' + 10;
332             else {
333                 mpi_clear(val);
334                 return 1;
335             }
336             a <<= 8;
337             a |= c;
338         }
339         i = 0;
340         val->d[j-1] = a;
341     }
342
343     return 0;
344 }
345
346
347 /****************
348  * print an MPI to the give stream and return the number of characters
349  * printed.
350  */
351 int
352 mpi_print( FILE *fp, MPI a, int mode )
353 {
354     int i, n=0;
355
356     if( a == MPI_NULL )
357         return fprintf(fp, "[MPI_NULL]");
358     if( !mode )
359         n += fprintf(fp, "[%d bits]", a->nlimbs * BITS_PER_MPI_LIMB );
360     else {
361         if( a->sign )
362             putc('-', fp);
363         for(i=a->nlimbs; i > 0 ; i-- ) {
364             n += fprintf(fp, i!=a->nlimbs? "%0" STR2(BYTES_PER_MPI_LIMB2)
365                                 "lX":"%lX", (unsigned long)a->d[i-1] );
366         }
367         if( !a->nlimbs )
368             putc('0', fp );
369     }
370     return n;
371 }
372
373
374 /****************
375  * Special function to get the low 8 bytes from a mpi,
376  * this can be used as a keyid, KEYID is an 2 element array.
377  * Does return the low 4 bytes.
378  */
379 u32
380 mpi_get_keyid( MPI a, u32 *keyid )
381 {
382 #if BYTES_PER_MPI_LIMB != 4
383   #error Make this function work with other LIMB sizes
384 #endif
385     if( keyid ) {
386         keyid[0] = a->nlimbs >= 2? a->d[1] : 0;
387         keyid[1] = a->nlimbs >= 1? a->d[0] : 0;
388     }
389     return a->nlimbs >= 1? a->d[0] : 0;
390 }
391
392