See ChangeLog: Wed Oct 4 13:16:18 CEST 2000 Werner Koch
[gnupg.git] / g10 / misc.c
1 /* misc.c -  miscellaneous functions
2  *      Copyright (C) 1998, 1999, 2000 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 <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
27   #include <asm/sysinfo.h>
28   #include <asm/unistd.h>
29 #endif
30 #ifdef HAVE_SETRLIMIT
31   #include <sys/time.h>
32   #include <sys/resource.h>
33 #endif
34 #include <assert.h>
35
36 #include <gcrypt.h>
37 #include "util.h"
38 #include "main.h"
39 #include "options.h"
40 #include "i18n.h"
41
42
43 #define MAX_EXTERN_MPI_BITS 16384
44
45 #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
46 #warning using trap_unaligned
47 static int
48 setsysinfo(unsigned long op, void *buffer, unsigned long size,
49                      int *start, void *arg, unsigned long flag)
50 {
51     return syscall(__NR_osf_setsysinfo, op, buffer, size, start, arg, flag);
52 }
53
54 void
55 trap_unaligned(void)
56 {
57     unsigned int buf[2];
58
59     buf[0] = SSIN_UACPROC;
60     buf[1] = UAC_SIGBUS | UAC_NOPRINT;
61     setsysinfo(SSI_NVPAIRS, buf, 1, 0, 0, 0);
62 }
63 #else
64 void
65 trap_unaligned(void)
66 {  /* dummy */
67 }
68 #endif
69
70
71
72 int
73 disable_core_dumps()
74 {
75  #ifdef HAVE_DOSISH_SYSTEM
76     return 0;
77  #else
78   #ifdef HAVE_SETRLIMIT
79     struct rlimit limit;
80
81     limit.rlim_cur = 0;
82     limit.rlim_max = 0;
83     if( !setrlimit( RLIMIT_CORE, &limit ) )
84         return 0;
85     if( errno != EINVAL && errno != ENOSYS )
86         log_fatal(_("can't disable core dumps: %s\n"), strerror(errno) );
87   #endif
88     return 1;
89  #endif
90 }
91
92
93
94 /****************
95  * write an mpi to out.
96  */
97 int
98 mpi_write( IOBUF out, MPI a )
99 {
100     char buffer[(MAX_EXTERN_MPI_BITS+7)/8];
101     size_t nbytes;
102     int rc;
103
104     nbytes = (MAX_EXTERN_MPI_BITS+7)/8;
105     rc = gcry_mpi_print( GCRYMPI_FMT_PGP, buffer, &nbytes, a );
106     if( !rc )
107         rc = iobuf_write( out, buffer, nbytes );
108
109     return rc;
110 }
111
112 /****************
113  * Writye a MPI to out, but in this case it is an opaque one,
114  * s used vor v3 protected keys.
115  */
116 int
117 mpi_write_opaque( IOBUF out, MPI a )
118 {
119     size_t nbytes, nbits;
120     int rc;
121     char *p;
122
123     assert( gcry_mpi_get_flag( a, GCRYMPI_FLAG_OPAQUE ) );
124     p = gcry_mpi_get_opaque( a, &nbits );
125     nbytes = (nbits+7) / 8;
126     iobuf_put( out, nbits >> 8 );
127     iobuf_put( out, nbits );
128     rc = iobuf_write( out, p, nbytes );
129     return rc;
130 }
131
132
133 /****************
134  * Read an external representation of an mpi and return the MPI
135  * The external format is a 16 bit unsigned value stored in network byte order,
136  * giving the number of bits for the following integer. The integer is stored
137  * with MSB first (left padded with zeroes to align on a byte boundary).
138  */
139 MPI
140 mpi_read(IOBUF inp, unsigned int *ret_nread, int secure)
141 {
142     int c, c1, c2, i;
143     unsigned int nbits, nbytes, nread=0;
144     MPI a = NULL;
145     byte *buf = NULL;
146     byte *p;
147
148     if( (c = c1 = iobuf_get(inp)) == -1 )
149         goto leave;
150     nbits = c << 8;
151     if( (c = c2 = iobuf_get(inp)) == -1 )
152         goto leave;
153     nbits |= c;
154     if( nbits > MAX_EXTERN_MPI_BITS ) {
155         log_error("mpi too large (%u bits)\n", nbits);
156         goto leave;
157     }
158     nread = 2;
159     nbytes = (nbits+7) / 8;
160     buf = secure? gcry_xmalloc_secure( nbytes+2 ) : gcry_xmalloc( nbytes+2 );
161     p = buf;
162     p[0] = c1;
163     p[1] = c2;
164     for( i=0 ; i < nbytes; i++ ) {
165         p[i+2] = iobuf_get(inp) & 0xff;
166         nread++;
167     }
168     nread += nbytes;
169     if( gcry_mpi_scan( &a, GCRYMPI_FMT_PGP, buf, &nread ) )
170         a = NULL;
171
172   leave:
173     gcry_free(buf);
174     if( nread > *ret_nread )
175         log_bug("mpi larger than packet");
176     else
177         *ret_nread = nread;
178     return a;
179 }
180
181 /****************
182  * Same as mpi_read but the value is stored as an opaque MPI.
183  * This function is used to read encrypted MPI of v3 packets.
184  */
185 GCRY_MPI
186 mpi_read_opaque(IOBUF inp, unsigned *ret_nread )
187 {
188     int c, c1, c2, i;
189     unsigned nbits, nbytes, nread=0;
190     GCRY_MPI a = NULL;
191     byte *buf = NULL;
192     byte *p;
193
194     if( (c = c1 = iobuf_get(inp)) == -1 )
195         goto leave;
196     nbits = c << 8;
197     if( (c = c2 = iobuf_get(inp)) == -1 )
198         goto leave;
199     nbits |= c;
200     if( nbits > MAX_EXTERN_MPI_BITS ) {
201         log_error("mpi too large (%u bits)\n", nbits);
202         goto leave;
203     }
204     nread = 2;
205     nbytes = (nbits+7) / 8;
206     buf = gcry_xmalloc( nbytes );
207     p = buf;
208     for( i=0 ; i < nbytes; i++ ) {
209         p[i] = iobuf_get(inp) & 0xff;
210     }
211     nread += nbytes;
212     a = gcry_mpi_set_opaque(NULL, buf, nbits );
213     buf = NULL;
214
215   leave:
216     gcry_free(buf);
217     if( nread > *ret_nread )
218         log_bug("mpi larger than packet");
219     else
220         *ret_nread = nread;
221     return a;
222 }
223
224
225 int
226 mpi_print( FILE *fp, MPI a, int mode )
227 {
228     int n=0;
229
230     if( !a )
231         return fprintf(fp, "[MPI_NULL]");
232     if( !mode ) {
233         unsigned int n1;
234         n1 = gcry_mpi_get_nbits(a);
235         n += fprintf(fp, "[%u bits]", n1);
236     }
237     else {
238         int rc;
239         char *buffer;
240
241         rc = gcry_mpi_aprint( GCRYMPI_FMT_HEX, (void **)&buffer, NULL, a );
242         assert( !rc );
243         fputs( buffer, fp );
244         n += strlen(buffer);
245         gcry_free( buffer );
246     }
247     return n;
248 }
249
250
251
252 u16
253 checksum_u16( unsigned n )
254 {
255     u16 a;
256
257     a  = (n >> 8) & 0xff;
258     a += n & 0xff;
259     return a;
260 }
261
262 u16
263 checksum( byte *p, unsigned n )
264 {
265     u16 a;
266
267     for(a=0; n; n-- )
268         a += *p++;
269     return a;
270 }
271
272 u16
273 checksum_mpi( MPI a )
274 {
275     int rc;
276     u16 csum;
277     byte *buffer;
278     size_t nbytes;
279
280     rc = gcry_mpi_print( GCRYMPI_FMT_PGP, NULL, &nbytes, a );
281     assert( !rc );
282     /* fixme: for numbers not in the suecre memory we
283      * should use a stack based buffer and only allocate
284      * a larger one when the mpi_print return an error
285      */
286     buffer = gcry_is_secure(a)? gcry_xmalloc_secure(nbytes) : gcry_xmalloc(nbytes);
287     rc = gcry_mpi_print( GCRYMPI_FMT_PGP, buffer, &nbytes, a );
288     assert( !rc );
289     csum = checksum( buffer, nbytes );
290     gcry_free( buffer );
291     return csum;
292 }
293
294
295 u32
296 buffer_to_u32( const byte *buffer )
297 {
298     unsigned long a;
299     a =  *buffer << 24;
300     a |= buffer[1] << 16;
301     a |= buffer[2] << 8;
302     a |= buffer[3];
303     return a;
304 }
305
306
307 static void
308 no_exp_algo(void)
309 {
310     static int did_note = 0;
311
312     if( !did_note ) {
313         did_note = 1;
314         log_info(_("Experimental algorithms should not be used!\n"));
315     }
316 }
317
318 void
319 print_pubkey_algo_note( int algo )
320 {
321     if( algo >= 100 && algo <= 110 )
322         no_exp_algo();
323 }
324
325 void
326 print_cipher_algo_note( int algo )
327 {
328     if( algo >= 100 && algo <= 110 )
329         no_exp_algo();
330     else if(    algo == GCRY_CIPHER_3DES
331              || algo == GCRY_CIPHER_CAST5
332              || algo == GCRY_CIPHER_BLOWFISH
333              || algo == GCRY_CIPHER_RIJNDAEL
334              || algo == GCRY_CIPHER_TWOFISH
335            )
336         ;
337     else {
338         static int did_note = 0;
339
340         if( !did_note ) {
341             did_note = 1;
342             log_info(_("this cipher algorithm is depreciated; "
343                        "please use a more standard one!\n"));
344         }
345     }
346 }
347
348 void
349 print_digest_algo_note( int algo )
350 {
351     if( algo >= 100 && algo <= 110 )
352         no_exp_algo();
353 }
354
355
356
357 /****************
358  * Wrapper around the libgcrypt function with addional checks on
359  * openPGP contraints for the algo ID.
360  */
361 int
362 openpgp_cipher_test_algo( int algo )
363 {
364     if( algo < 0 || algo > 110 )
365         return GCRYERR_INV_CIPHER_ALGO;
366     return gcry_cipher_test_algo(algo);
367 }
368
369 int
370 openpgp_pk_test_algo( int algo, unsigned int usage_flags )
371 {
372     size_t n = usage_flags;
373
374     if( algo < 0 || algo > 110 )
375         return GCRYERR_INV_PK_ALGO;
376     return gcry_pk_algo_info( algo, GCRYCTL_TEST_ALGO, NULL, &n );
377 }
378
379 int 
380 openpgp_pk_algo_usage ( int algo )
381 {
382     int usage = 0; 
383     
384     /* some are hardwired */
385     switch ( algo ) {    
386       case GCRY_PK_RSA:
387           usage = GCRY_PK_USAGE_SIGN | GCRY_PK_USAGE_ENCR;
388           break;
389       case GCRY_PK_RSA_E:
390           usage = GCRY_PK_USAGE_ENCR;
391           break;
392       case GCRY_PK_RSA_S:
393           usage = GCRY_PK_USAGE_SIGN;
394           break;
395       case GCRY_PK_ELG_E:
396           usage = GCRY_PK_USAGE_ENCR;
397           break;
398       case GCRY_PK_DSA:  
399           usage = GCRY_PK_USAGE_SIGN;
400           break;
401       case GCRY_PK_ELG:
402           usage = GCRY_PK_USAGE_SIGN | GCRY_PK_USAGE_ENCR;
403           break;
404       default:
405           usage = gcry_pk_algo_info ( algo, GCRYCTL_GET_ALGO_USAGE,
406                                       NULL, NULL);
407     }
408     return usage;
409
410 }
411
412
413
414 int
415 openpgp_md_test_algo( int algo )
416 {
417     if( algo < 0 || algo > 110 )
418         return GCRYERR_INV_MD_ALGO;
419     return gcry_md_test_algo(algo);
420 }
421
422
423 int
424 pubkey_get_npkey( int algo )
425 {
426     int n = gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NPKEY, NULL, 0 );
427     return n > 0? n : 0;
428 }
429
430 int
431 pubkey_get_nskey( int algo )
432 {
433     int n = gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NSKEY, NULL, 0 );
434     return n > 0? n : 0;
435 }
436
437 int
438 pubkey_get_nsig( int algo )
439 {
440     int n = gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NSIGN, NULL, 0 );
441     return n > 0? n : 0;
442 }
443
444 int
445 pubkey_get_nenc( int algo )
446 {
447     int n = gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NENCR, NULL, 0 );
448     return n > 0? n : 0;
449 }
450
451
452 unsigned int
453 pubkey_nbits( int algo, MPI *key )
454 {
455     int rc, nbits;
456     GCRY_SEXP sexp;
457
458     if( algo == GCRY_PK_DSA ) {
459         rc = gcry_sexp_build ( &sexp, NULL,
460                               "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))",
461                                   key[0], key[1], key[2], key[3] );
462     }
463     else if( algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E ) {
464         rc = gcry_sexp_build ( &sexp, NULL,
465                               "(public-key(elg(p%m)(g%m)(y%m)))",
466                                   key[0], key[1], key[2] );
467     }
468     else if( algo == GCRY_PK_RSA ) {
469         rc = gcry_sexp_build ( &sexp, NULL,
470                               "(public-key(rsa(n%m)(e%m)))",
471                                   key[0], key[1] );
472     }
473     else
474         return 0;
475
476     if ( rc )
477         BUG ();
478
479     nbits = gcry_pk_get_nbits( sexp );
480     gcry_sexp_release( sexp );
481     return nbits;
482 }
483