See ChangeLog: Tue Oct 26 14:10:21 CEST 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 "options.h"
38 #include "i18n.h"
39
40
41 const char *g10m_revision_string(int);
42 const char *g10c_revision_string(int);
43 const char *g10u_revision_string(int);
44
45 #ifdef __GNUC__
46 volatile
47 #endif
48          void
49 pull_in_libs(void)
50 {
51     g10m_revision_string(0);
52     g10c_revision_string(0);
53     g10u_revision_string(0);
54 }
55
56
57 #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
58 #warning using trap_unaligned
59 static int
60 setsysinfo(unsigned long op, void *buffer, unsigned long size,
61                      int *start, void *arg, unsigned long flag)
62 {
63     return syscall(__NR_osf_setsysinfo, op, buffer, size, start, arg, flag);
64 }
65
66 void
67 trap_unaligned(void)
68 {
69     unsigned int buf[2];
70
71     buf[0] = SSIN_UACPROC;
72     buf[1] = UAC_SIGBUS | UAC_NOPRINT;
73     setsysinfo(SSI_NVPAIRS, buf, 1, 0, 0, 0);
74 }
75 #else
76 void
77 trap_unaligned(void)
78 {  /* dummy */
79 }
80 #endif
81
82
83 void
84 disable_core_dumps()
85 {
86  #ifndef HAVE_DOSISH_SYSTEM
87   #ifdef HAVE_SETRLIMIT
88     struct rlimit limit;
89
90     limit.rlim_cur = 0;
91     limit.rlim_max = 0;
92     if( !setrlimit( RLIMIT_CORE, &limit ) )
93         return;
94     if( errno != EINVAL )
95         log_fatal(_("can't disable core dumps: %s\n"), strerror(errno) );
96   #endif
97     if( !opt.quiet )
98         log_info(_("WARNING: program may create a core file!\n"));
99  #endif
100 }
101
102
103
104 u16
105 checksum_u16( unsigned n )
106 {
107     u16 a;
108
109     a  = (n >> 8) & 0xff;
110     if( opt.emulate_bugs & EMUBUG_GPGCHKSUM ) {
111        a |= n & 0xff;
112        log_debug("csum_u16 emulated for n=%u\n", n);
113     }
114     else
115        a += n & 0xff;
116     return a;
117 }
118
119 static u16
120 checksum_u16_nobug( unsigned n )
121 {
122     u16 a;
123
124     a  = (n >> 8) & 0xff;
125     a += n & 0xff;
126     return a;
127 }
128
129 u16
130 checksum( byte *p, unsigned n )
131 {
132     u16 a;
133
134     for(a=0; n; n-- )
135         a += *p++;
136     return a;
137 }
138
139 u16
140 checksum_mpi( MPI a )
141 {
142     u16 csum;
143     byte *buffer;
144     unsigned nbytes;
145     unsigned nbits;
146
147     buffer = mpi_get_buffer( a, &nbytes, NULL );
148     /* some versions of gpg encode wrong values for the length of an mpi
149      * so that mpi_get_nbits() which counts the mpi yields another (shorter)
150      * value than the one store with the mpi.  mpi_get_nbit_info() returns
151      * this stored value if it is still available.
152      */
153
154     if( opt.emulate_bugs & EMUBUG_GPGCHKSUM )
155         nbits = 0;
156     else
157         nbits = mpi_get_nbit_info(a);
158     if( !nbits )
159        nbits = mpi_get_nbits(a);
160     csum = checksum_u16( nbits );
161     csum += checksum( buffer, nbytes );
162     m_free( buffer );
163     return csum;
164 }
165
166 /****************
167  * This is the correct function
168  */
169 u16
170 checksum_mpi_counted_nbits( MPI a )
171 {
172     u16 csum;
173     byte *buffer;
174     unsigned nbytes;
175     unsigned nbits;
176
177     buffer = mpi_get_buffer( a, &nbytes, NULL );
178     nbits = mpi_get_nbits(a);
179     mpi_set_nbit_info(a,nbits);
180     csum = checksum_u16_nobug( nbits );
181     csum += checksum( buffer, nbytes );
182     m_free( buffer );
183     return csum;
184 }
185
186
187 u32
188 buffer_to_u32( const byte *buffer )
189 {
190     unsigned long a;
191     a =  *buffer << 24;
192     a |= buffer[1] << 16;
193     a |= buffer[2] << 8;
194     a |= buffer[3];
195     return a;
196 }
197
198
199 static void
200 no_exp_algo(void)
201 {
202     static int did_note = 0;
203
204     if( !did_note ) {
205         did_note = 1;
206         log_info(_("Experimental algorithms should not be used!\n"));
207     }
208 }
209
210 void
211 print_pubkey_algo_note( int algo )
212 {
213     if( algo >= 100 && algo <= 110 )
214         no_exp_algo();
215     else if( is_RSA( algo ) ) {
216         static int did_note = 0;
217
218         if( !did_note ) {
219             did_note = 1;
220             log_info(_("RSA keys are deprecated; please consider "
221                        "creating a new key and use this key in the future\n"));
222         }
223     }
224 }
225
226 void
227 print_cipher_algo_note( int algo )
228 {
229     if( algo >= 100 && algo <= 110 )
230         no_exp_algo();
231     else if(    algo == CIPHER_ALGO_3DES
232              || algo == CIPHER_ALGO_CAST5
233              || algo == CIPHER_ALGO_BLOWFISH
234              || algo == CIPHER_ALGO_TWOFISH
235            )
236         ;
237     else {
238         static int did_note = 0;
239
240         if( !did_note ) {
241             did_note = 1;
242             log_info(_("this cipher algorithm is depreciated; "
243                        "please use a more standard one!\n"));
244         }
245     }
246 }
247
248 void
249 print_digest_algo_note( int algo )
250 {
251     if( algo >= 100 && algo <= 110 )
252         no_exp_algo();
253 }
254
255
256
257 /****************
258  * Map errors retuned by libgcrypt to those used by GnuPG.
259  */
260 int
261 map_gcry_rc( int rc )
262 {
263     switch( rc )  {
264       case 0: return 0;
265       default: return G10ERR_GENERAL;
266     }
267 }
268
269
270 /****************
271  * Wrapper around the libgcrypt function with addional checks on
272  * openPGP contrainst for the algo ID.
273  */
274 int
275 openpgp_cipher_test_algo( int algo )
276 {
277     if( algo < 0 || algo > 110 )
278         return GCRYERR_INV_ALGO;
279     return gcry_cipher_test_algo(algo);
280 }
281
282 int
283 openpgp_pk_test_algo( int algo )
284 {
285     if( algo < 0 || algo > 110 )
286         return GCRYERR_INV_ALGO;
287     return gcry_pk_test_algo(algo);
288 }
289
290 int
291 openpgp_md_test_algo( int algo )
292 {
293     if( algo < 0 || algo > 110 )
294         return GCRYERR_INV_ALGO;
295     return gcry_md_test_algo(algo);
296 }
297