See ChangeLog: Wed Dec 8 21:58:32 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 #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 <gcrypt.h>
35 #include "util.h"
36 #include "main.h"
37 #include "memory.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
120     assert( gcry_mpi_get_flag( a, GCRYMPI_FLAG_OPAQUE ) );
121     p = gcry_mpi_get_opaque( a, &nbits );
122     nbytes = (nbits+7) / 8;
123     iobuf_put( out, nbits >> 8 );
124     iobuf_put( out, nbits )
125     rc = iobuf_write( out, p, nbytes );
126     return rc;
127 }
128
129
130 /****************
131  * Read an external representation of an mpi and return the MPI
132  * The external format is a 16 bit unsigned value stored in network byte order,
133  * giving the number of bits for the following integer. The integer is stored
134  * with MSB first (left padded with zeroes to align on a byte boundary).
135  */
136 MPI
137 mpi_read(IOBUF inp, unsigned *ret_nread, int secure)
138 {
139     int c, c1, c2, i;
140     unsigned nbits, nbytes, nread=0;
141     MPI a = NULL;
142     byte *buf = NULL;
143     byte *p;
144
145     if( (c = c1 = iobuf_get(inp)) == -1 )
146         goto leave;
147     nbits = c << 8;
148     if( (c = c2 = iobuf_get(inp)) == -1 )
149         goto leave;
150     nbits |= c;
151     if( nbits > MAX_EXTERN_MPI_BITS ) {
152         log_error("mpi too large (%u bits)\n", nbits);
153         goto leave;
154     }
155     nread = 2;
156     nbytes = (nbits+7) / 8;
157     buf = secure? m_alloc_secure( nbytes+2 ) : m_alloc( nbytes+2 );
158     p = buf;
159     p[0] = c1;
160     p[1] = c2;
161     for( i=0 ; i < nbytes; i++ ) {
162         p[i+2] = iobuf_get(inp) & 0xff;
163         nread++;
164     }
165     nread += nbytes;
166     /* FIXME: replace with the gcry_scan function */
167     a = mpi_read_from_buffer( buf, &nread, secure );
168
169   leave:
170     m_free(buf);
171     if( nread > *ret_nread )
172         log_bug("mpi larger than packet");
173     else
174         *ret_nread = nread;
175     return a;
176 }
177
178 /****************
179  * Same as mpi_read but the value is stored as an opaque MPI.
180  * This function is used to read encrpted MPI of v3 packets.
181  */
182 GCRY_MPI
183 mpi_read_opaque(IOBUF inp, unsigned *ret_nread )
184 {
185     int c, c1, c2, i;
186     unsigned nbits, nbytes, nread=0;
187     GCRY_MPI a = NULL;
188     byte *buf = NULL;
189     byte *p;
190
191     if( (c = c1 = iobuf_get(inp)) == -1 )
192         goto leave;
193     nbits = c << 8;
194     if( (c = c2 = iobuf_get(inp)) == -1 )
195         goto leave;
196     nbits |= c;
197     if( nbits > MAX_EXTERN_MPI_BITS ) {
198         log_error("mpi too large (%u bits)\n", nbits);
199         goto leave;
200     }
201     nread = 2;
202     nbytes = (nbits+7) / 8;
203     buf = m_alloc( nbytes );
204     p = buf;
205     for( i=0 ; i < nbytes; i++ ) {
206         p[i] = iobuf_get(inp) & 0xff;
207         nread++;
208     }
209     nread += nbytes;
210     a = gcry_mpi_set_opaque(NULL, buf, nbits );
211     buf = NULL;
212
213   leave:
214     m_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
224 u16
225 checksum_u16( unsigned n )
226 {
227     u16 a;
228
229     a  = (n >> 8) & 0xff;
230     a += n & 0xff;
231     return a;
232 }
233
234 u16
235 checksum( byte *p, unsigned n )
236 {
237     u16 a;
238
239     for(a=0; n; n-- )
240         a += *p++;
241     return a;
242 }
243
244 u16
245 checksum_mpi( MPI a )
246 {
247     u16 csum;
248     byte *buffer;
249     unsigned nbytes;
250     unsigned nbits;
251
252     buffer = mpi_get_buffer( a, &nbytes, NULL );
253     nbits = mpi_get_nbits(a);
254     csum = checksum_u16( nbits );
255     csum += checksum( buffer, nbytes );
256     m_free( buffer );
257     return csum;
258 }
259
260
261
262 u32
263 buffer_to_u32( const byte *buffer )
264 {
265     unsigned long a;
266     a =  *buffer << 24;
267     a |= buffer[1] << 16;
268     a |= buffer[2] << 8;
269     a |= buffer[3];
270     return a;
271 }
272
273
274 static void
275 no_exp_algo(void)
276 {
277     static int did_note = 0;
278
279     if( !did_note ) {
280         did_note = 1;
281         log_info(_("Experimental algorithms should not be used!\n"));
282     }
283 }
284
285 void
286 print_pubkey_algo_note( int algo )
287 {
288     if( algo >= 100 && algo <= 110 )
289         no_exp_algo();
290     else if( is_RSA( algo ) ) {
291         static int did_note = 0;
292
293         if( !did_note ) {
294             did_note = 1;
295             log_info(_("RSA keys are deprecated; please consider "
296                        "creating a new key and use this key in the future\n"));
297         }
298     }
299 }
300
301 void
302 print_cipher_algo_note( int algo )
303 {
304     if( algo >= 100 && algo <= 110 )
305         no_exp_algo();
306     else if(    algo == GCRY_CIPHER_3DES
307              || algo == GCRY_CIPHER_CAST5
308              || algo == GCRY_CIPHER_BLOWFISH
309              || algo == GCRY_CIPHER_TWOFISH
310            )
311         ;
312     else {
313         static int did_note = 0;
314
315         if( !did_note ) {
316             did_note = 1;
317             log_info(_("this cipher algorithm is depreciated; "
318                        "please use a more standard one!\n"));
319         }
320     }
321 }
322
323 void
324 print_digest_algo_note( int algo )
325 {
326     if( algo >= 100 && algo <= 110 )
327         no_exp_algo();
328 }
329
330
331 /****************
332  * Wrapper around the libgcrypt function with addional checks on
333  * openPGP contrainst for the algo ID.
334  */
335 int
336 openpgp_cipher_test_algo( int algo )
337 {
338     if( algo < 0 || algo > 110 )
339         return GCRYERR_INV_CIPHER_ALGO;
340     return gcry_cipher_test_algo(algo);
341 }
342
343 int
344 openpgp_pk_test_algo( int algo, unsigned int usage_flags )
345 {
346     size_t n = usage_flags;
347
348     if( algo < 0 || algo > 110 )
349         return GCRYERR_INV_PK_ALGO;
350     return gcry_pk_algo_info( algo, GCRYCTL_TEST_ALGO, NULL, &n );
351 }
352
353
354 int
355 openpgp_md_test_algo( int algo )
356 {
357     if( algo < 0 || algo > 110 )
358         return GCRYERR_INV_MD_ALGO;
359     return gcry_md_test_algo(algo);
360 }
361
362
363 int
364 pubkey_get_npkey( int algo )
365 {
366     int n = gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NPKEY, NULL, 0 );
367     return n > 0? n : 0;
368 }
369
370 int
371 pubkey_get_nskey( int algo )
372 {
373     int n = gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NSKEY, NULL, 0 );
374     return n > 0? n : 0;
375 }
376
377 int
378 pubkey_get_nsig( int algo )
379 {
380     int n = gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NSIGN, NULL, 0 );
381     return n > 0? n : 0;
382 }
383
384 int
385 pubkey_get_nenc( int algo )
386 {
387     int n = gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NENCR, NULL, 0 );
388     return n > 0? n : 0;
389 }
390