See ChangeLog: Mon Jan 24 22:24:38 CET 2000 Werner Koch
[gnupg.git] / g10 / misc.c
1 /* misc.c -  miscellaneous functions
2  *      Copyright (C) 1998, 1999 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 #include <assert.h>
27 #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
28   #include <asm/sysinfo.h>
29   #include <asm/unistd.h>
30 #endif
31 #ifdef HAVE_SETRLIMIT
32   #include <sys/time.h>
33   #include <sys/resource.h>
34 #endif
35 #include <gcrypt.h>
36 #include "util.h"
37 #include "main.h"
38 #include "options.h"
39 #include "i18n.h"
40
41
42 #define MAX_EXTERN_MPI_BITS 16384
43
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 u16
250 checksum_u16( unsigned n )
251 {
252     u16 a;
253
254     a  = (n >> 8) & 0xff;
255     a += n & 0xff;
256     return a;
257 }
258
259 u16
260 checksum( byte *p, unsigned n )
261 {
262     u16 a;
263
264     for(a=0; n; n-- )
265         a += *p++;
266     return a;
267 }
268
269 u16
270 checksum_mpi( MPI a )
271 {
272     int rc;
273     u16 csum;
274     byte *buffer;
275     size_t nbytes;
276
277     rc = gcry_mpi_print( GCRYMPI_FMT_PGP, NULL, &nbytes, a );
278     assert( !rc );
279     /* fixme: for numbers not in the suecre memory we
280      * should use a stack based buffer and only allocate
281      * a larger one when the mpi_print return an error
282      */
283     buffer = gcry_is_secure(a)? gcry_xmalloc_secure(nbytes) : gcry_xmalloc(nbytes);
284     rc = gcry_mpi_print( GCRYMPI_FMT_PGP, buffer, &nbytes, a );
285     assert( !rc );
286     csum = checksum( buffer, nbytes );
287     gcry_free( buffer );
288     return csum;
289 }
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  * Wrapper around the libgcrypt function with addional checks on
364  * openPGP contrainst for the algo ID.
365  */
366 int
367 openpgp_cipher_test_algo( int algo )
368 {
369     if( algo < 0 || algo > 110 )
370         return GCRYERR_INV_CIPHER_ALGO;
371     return gcry_cipher_test_algo(algo);
372 }
373
374 int
375 openpgp_pk_test_algo( int algo, unsigned int usage_flags )
376 {
377     size_t n = usage_flags;
378
379     if( algo < 0 || algo > 110 )
380         return GCRYERR_INV_PK_ALGO;
381     return gcry_pk_algo_info( algo, GCRYCTL_TEST_ALGO, NULL, &n );
382 }
383
384
385 int
386 openpgp_md_test_algo( int algo )
387 {
388     if( algo < 0 || algo > 110 )
389         return GCRYERR_INV_MD_ALGO;
390     return gcry_md_test_algo(algo);
391 }
392
393
394 int
395 pubkey_get_npkey( int algo )
396 {
397     int n = gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NPKEY, NULL, 0 );
398     return n > 0? n : 0;
399 }
400
401 int
402 pubkey_get_nskey( int algo )
403 {
404     int n = gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NSKEY, NULL, 0 );
405     return n > 0? n : 0;
406 }
407
408 int
409 pubkey_get_nsig( int algo )
410 {
411     int n = gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NSIGN, NULL, 0 );
412     return n > 0? n : 0;
413 }
414
415 int
416 pubkey_get_nenc( int algo )
417 {
418     int n = gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NENCR, NULL, 0 );
419     return n > 0? n : 0;
420 }
421
422 unsigned int
423 pubkey_nbits( int algo, MPI *key )
424 {
425     int nbits;
426     GCRY_SEXP sexp;
427
428
429     if( algo == GCRY_PK_DSA ) {
430         sexp = SEXP_CONS( SEXP_NEW( "public-key", 0 ),
431                           gcry_sexp_vlist( SEXP_NEW( "dsa", 3 ),
432                           gcry_sexp_new_name_mpi( "p", key[0] ),
433                           gcry_sexp_new_name_mpi( "q", key[1] ),
434                           gcry_sexp_new_name_mpi( "g", key[2] ),
435                           gcry_sexp_new_name_mpi( "y", key[3] ),
436                           NULL ));
437     }
438     else if( algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E ) {
439         sexp = SEXP_CONS( SEXP_NEW( "public-key", 0 ),
440                           gcry_sexp_vlist( SEXP_NEW( "elg", 3 ),
441                           gcry_sexp_new_name_mpi( "p", key[0] ),
442                           gcry_sexp_new_name_mpi( "g", key[1] ),
443                           gcry_sexp_new_name_mpi( "y", key[2] ),
444                           NULL ));
445     }
446     else if( algo == GCRY_PK_RSA ) {
447         sexp = SEXP_CONS( SEXP_NEW( "public-key", 0 ),
448                           gcry_sexp_vlist( SEXP_NEW( "rsa", 3 ),
449                           gcry_sexp_new_name_mpi( "n", key[0] ),
450                           gcry_sexp_new_name_mpi( "e", key[1] ),
451                           NULL ));
452     }
453     else
454         return 0;
455
456     nbits = gcry_pk_get_nbits( sexp );
457     gcry_sexp_release( sexp );
458     return nbits;
459 }
460