See ChangeLog: Fri Dec 31 12:48:31 CET 1999 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 "memory.h"
39 #include "options.h"
40 #include "i18n.h"
41
42
43 #define MAX_EXTERN_MPI_BITS 16384
44
45
46 #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
47 #warning using trap_unaligned
48 static int
49 setsysinfo(unsigned long op, void *buffer, unsigned long size,
50                      int *start, void *arg, unsigned long flag)
51 {
52     return syscall(__NR_osf_setsysinfo, op, buffer, size, start, arg, flag);
53 }
54
55 void
56 trap_unaligned(void)
57 {
58     unsigned int buf[2];
59
60     buf[0] = SSIN_UACPROC;
61     buf[1] = UAC_SIGBUS | UAC_NOPRINT;
62     setsysinfo(SSI_NVPAIRS, buf, 1, 0, 0, 0);
63 }
64 #else
65 void
66 trap_unaligned(void)
67 {  /* dummy */
68 }
69 #endif
70
71
72 void
73 disable_core_dumps()
74 {
75  #ifndef HAVE_DOSISH_SYSTEM
76   #ifdef HAVE_SETRLIMIT
77     struct rlimit limit;
78
79     limit.rlim_cur = 0;
80     limit.rlim_max = 0;
81     if( !setrlimit( RLIMIT_CORE, &limit ) )
82         return;
83     if( errno != EINVAL )
84         log_fatal(_("can't disable core dumps: %s\n"), strerror(errno) );
85   #endif
86     if( !opt.quiet )
87         log_info(_("WARNING: program may create a core file!\n"));
88  #endif
89 }
90
91
92
93 /****************
94  * write an mpi to out.
95  */
96 int
97 mpi_write( IOBUF out, MPI a )
98 {
99     char buffer[(MAX_EXTERN_MPI_BITS+7)/8];
100     size_t nbytes;
101     int rc;
102
103     nbytes = (MAX_EXTERN_MPI_BITS+7)/8;
104     rc = gcry_mpi_print( GCRYMPI_FMT_PGP, buffer, &nbytes, a );
105     if( !rc )
106         rc = iobuf_write( out, buffer, nbytes );
107
108     return rc;
109 }
110
111 /****************
112  * Writye a MPI to out, but in this case it is an opaque one,
113  * s used vor v3 protected keys.
114  */
115 int
116 mpi_write_opaque( IOBUF out, MPI a )
117 {
118     size_t nbytes, nbits;
119     int rc;
120     char *p;
121
122     assert( gcry_mpi_get_flag( a, GCRYMPI_FLAG_OPAQUE ) );
123     p = gcry_mpi_get_opaque( a, &nbits );
124     nbytes = (nbits+7) / 8;
125     iobuf_put( out, nbits >> 8 );
126     iobuf_put( out, nbits );
127     rc = iobuf_write( out, p, nbytes );
128     return rc;
129 }
130
131
132 /****************
133  * Read an external representation of an mpi and return the MPI
134  * The external format is a 16 bit unsigned value stored in network byte order,
135  * giving the number of bits for the following integer. The integer is stored
136  * with MSB first (left padded with zeroes to align on a byte boundary).
137  */
138 MPI
139 mpi_read(IOBUF inp, unsigned int *ret_nread, int secure)
140 {
141     int c, c1, c2, i;
142     unsigned int nbits, nbytes, nread=0;
143     MPI a = NULL;
144     byte *buf = NULL;
145     byte *p;
146
147     if( (c = c1 = iobuf_get(inp)) == -1 )
148         goto leave;
149     nbits = c << 8;
150     if( (c = c2 = iobuf_get(inp)) == -1 )
151         goto leave;
152     nbits |= c;
153     if( nbits > MAX_EXTERN_MPI_BITS ) {
154         log_error("mpi too large (%u bits)\n", nbits);
155         goto leave;
156     }
157     nread = 2;
158     nbytes = (nbits+7) / 8;
159     buf = secure? m_alloc_secure( nbytes+2 ) : m_alloc( nbytes+2 );
160     p = buf;
161     p[0] = c1;
162     p[1] = c2;
163     for( i=0 ; i < nbytes; i++ ) {
164         p[i+2] = iobuf_get(inp) & 0xff;
165         nread++;
166     }
167     nread += nbytes;
168     if( gcry_mpi_scan( &a, GCRYMPI_FMT_PGP, buf, &nread ) )
169         a = NULL;
170
171   leave:
172     m_free(buf);
173     if( nread > *ret_nread )
174         log_bug("mpi larger than packet");
175     else
176         *ret_nread = nread;
177     return a;
178 }
179
180 /****************
181  * Same as mpi_read but the value is stored as an opaque MPI.
182  * This function is used to read encrpted MPI of v3 packets.
183  */
184 GCRY_MPI
185 mpi_read_opaque(IOBUF inp, unsigned *ret_nread )
186 {
187     int c, c1, c2, i;
188     unsigned nbits, nbytes, nread=0;
189     GCRY_MPI a = NULL;
190     byte *buf = NULL;
191     byte *p;
192
193     if( (c = c1 = iobuf_get(inp)) == -1 )
194         goto leave;
195     nbits = c << 8;
196     if( (c = c2 = iobuf_get(inp)) == -1 )
197         goto leave;
198     nbits |= c;
199     if( nbits > MAX_EXTERN_MPI_BITS ) {
200         log_error("mpi too large (%u bits)\n", nbits);
201         goto leave;
202     }
203     nread = 2;
204     nbytes = (nbits+7) / 8;
205     buf = m_alloc( nbytes );
206     p = buf;
207     for( i=0 ; i < nbytes; i++ ) {
208         p[i] = iobuf_get(inp) & 0xff;
209         nread++;
210     }
211     nread += nbytes;
212     a = gcry_mpi_set_opaque(NULL, buf, nbits );
213     buf = NULL;
214
215   leave:
216     m_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         byte *buffer;
240         size_t nbytes;
241
242         rc = gcry_mpi_print( GCRYMPI_FMT_HEX, NULL, &nbytes, a );
243         assert( !rc );
244         buffer = m_is_secure(a)? m_alloc_secure(nbytes) : m_alloc(nbytes);
245         rc = gcry_mpi_print( GCRYMPI_FMT_HEX, buffer, &nbytes, a );
246         assert( !rc );
247         fputs( buffer, fp );
248         n += strlen(buffer);
249         m_free( buffer );
250     }
251     return n;
252 }
253
254
255 u16
256 checksum_u16( unsigned n )
257 {
258     u16 a;
259
260     a  = (n >> 8) & 0xff;
261     a += n & 0xff;
262     return a;
263 }
264
265 u16
266 checksum( byte *p, unsigned n )
267 {
268     u16 a;
269
270     for(a=0; n; n-- )
271         a += *p++;
272     return a;
273 }
274
275 u16
276 checksum_mpi( MPI a )
277 {
278     int rc;
279     u16 csum;
280     byte *buffer;
281     size_t nbytes;
282
283     rc = gcry_mpi_print( GCRYMPI_FMT_PGP, NULL, &nbytes, a );
284     assert( !rc );
285     /* fixme: for numbers not in the suecre memory we
286      * should use a stack based buffer and only allocate
287      * a larger one when the mpi_print return an error
288      */
289     buffer = m_is_secure(a)? m_alloc_secure(nbytes) : m_alloc(nbytes);
290     rc = gcry_mpi_print( GCRYMPI_FMT_PGP, buffer, &nbytes, a );
291     assert( !rc );
292     csum = checksum( buffer, nbytes );
293     m_free( buffer );
294     return csum;
295 }
296
297
298
299 u32
300 buffer_to_u32( const byte *buffer )
301 {
302     unsigned long a;
303     a =  *buffer << 24;
304     a |= buffer[1] << 16;
305     a |= buffer[2] << 8;
306     a |= buffer[3];
307     return a;
308 }
309
310
311 static void
312 no_exp_algo(void)
313 {
314     static int did_note = 0;
315
316     if( !did_note ) {
317         did_note = 1;
318         log_info(_("Experimental algorithms should not be used!\n"));
319     }
320 }
321
322 void
323 print_pubkey_algo_note( int algo )
324 {
325     if( algo >= 100 && algo <= 110 )
326         no_exp_algo();
327     else if( is_RSA( algo ) ) {
328         static int did_note = 0;
329
330         if( !did_note ) {
331             did_note = 1;
332             log_info(_("RSA keys are deprecated; please consider "
333                        "creating a new key and use this key in the future\n"));
334         }
335     }
336 }
337
338 void
339 print_cipher_algo_note( int algo )
340 {
341     if( algo >= 100 && algo <= 110 )
342         no_exp_algo();
343     else if(    algo == GCRY_CIPHER_3DES
344              || algo == GCRY_CIPHER_CAST5
345              || algo == GCRY_CIPHER_BLOWFISH
346              || algo == GCRY_CIPHER_TWOFISH
347            )
348         ;
349     else {
350         static int did_note = 0;
351
352         if( !did_note ) {
353             did_note = 1;
354             log_info(_("this cipher algorithm is depreciated; "
355                        "please use a more standard one!\n"));
356         }
357     }
358 }
359
360 void
361 print_digest_algo_note( int algo )
362 {
363     if( algo >= 100 && algo <= 110 )
364         no_exp_algo();
365 }
366
367
368 /****************
369  * Wrapper around the libgcrypt function with addional checks on
370  * openPGP contrainst for the algo ID.
371  */
372 int
373 openpgp_cipher_test_algo( int algo )
374 {
375     if( algo < 0 || algo > 110 )
376         return GCRYERR_INV_CIPHER_ALGO;
377     return gcry_cipher_test_algo(algo);
378 }
379
380 int
381 openpgp_pk_test_algo( int algo, unsigned int usage_flags )
382 {
383     size_t n = usage_flags;
384
385     if( algo < 0 || algo > 110 )
386         return GCRYERR_INV_PK_ALGO;
387     return gcry_pk_algo_info( algo, GCRYCTL_TEST_ALGO, NULL, &n );
388 }
389
390
391 int
392 openpgp_md_test_algo( int algo )
393 {
394     if( algo < 0 || algo > 110 )
395         return GCRYERR_INV_MD_ALGO;
396     return gcry_md_test_algo(algo);
397 }
398
399
400 int
401 pubkey_get_npkey( int algo )
402 {
403     int n = gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NPKEY, NULL, 0 );
404     return n > 0? n : 0;
405 }
406
407 int
408 pubkey_get_nskey( int algo )
409 {
410     int n = gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NSKEY, NULL, 0 );
411     return n > 0? n : 0;
412 }
413
414 int
415 pubkey_get_nsig( int algo )
416 {
417     int n = gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NSIGN, NULL, 0 );
418     return n > 0? n : 0;
419 }
420
421 int
422 pubkey_get_nenc( int algo )
423 {
424     int n = gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NENCR, NULL, 0 );
425     return n > 0? n : 0;
426 }
427
428 int
429 pubkey_nbits()
430 {
431 }
432