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