* packet.h, build-packet.c (build_sig_subpkt), export.c
[gnupg.git] / g10 / misc.c
1 /* misc.c -  miscellaneous functions
2  * Copyright (C) 1998, 1999, 2000, 2001, 2002 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 <unistd.h>
26 #include <errno.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 <time.h>
33   #include <sys/time.h>
34   #include <sys/resource.h>
35 #endif
36 #include "util.h"
37 #include "main.h"
38 #include "photoid.h"
39 #include "options.h"
40 #include "i18n.h"
41
42
43 const char *g10m_revision_string(int);
44 const char *g10c_revision_string(int);
45 const char *g10u_revision_string(int);
46
47 #ifdef __GNUC__
48 volatile
49 #endif
50          void
51 pull_in_libs(void)
52 {
53     g10m_revision_string(0);
54     g10c_revision_string(0);
55     g10u_revision_string(0);
56 }
57
58
59 #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
60 static int
61 setsysinfo(unsigned long op, void *buffer, unsigned long size,
62                      int *start, void *arg, unsigned long flag)
63 {
64     return syscall(__NR_osf_setsysinfo, op, buffer, size, start, arg, flag);
65 }
66
67 void
68 trap_unaligned(void)
69 {
70     unsigned int buf[2];
71
72     buf[0] = SSIN_UACPROC;
73     buf[1] = UAC_SIGBUS | UAC_NOPRINT;
74     setsysinfo(SSI_NVPAIRS, buf, 1, 0, 0, 0);
75 }
76 #else
77 void
78 trap_unaligned(void)
79 {  /* dummy */
80 }
81 #endif
82
83
84 int
85 disable_core_dumps()
86 {
87  #ifdef HAVE_DOSISH_SYSTEM
88     return 0;
89  #else
90   #ifdef HAVE_SETRLIMIT
91     struct rlimit limit;
92
93     limit.rlim_cur = 0;
94     limit.rlim_max = 0;
95     if( !setrlimit( RLIMIT_CORE, &limit ) )
96         return 0;
97     if( errno != EINVAL && errno != ENOSYS )
98         log_fatal(_("can't disable core dumps: %s\n"), strerror(errno) );
99   #endif
100     return 1;
101  #endif
102 }
103
104
105
106 u16
107 checksum_u16( unsigned n )
108 {
109     u16 a;
110
111     a  = (n >> 8) & 0xff;
112     a += n & 0xff;
113     return a;
114 }
115
116
117 u16
118 checksum( byte *p, unsigned n )
119 {
120     u16 a;
121
122     for(a=0; n; n-- )
123         a += *p++;
124     return a;
125 }
126
127 u16
128 checksum_mpi( MPI a )
129 {
130     u16 csum;
131     byte *buffer;
132     unsigned nbytes;
133     unsigned nbits;
134
135     buffer = mpi_get_buffer( a, &nbytes, NULL );
136     nbits = mpi_get_nbits(a);
137     csum = checksum_u16( nbits );
138     csum += checksum( buffer, nbytes );
139     m_free( buffer );
140     return csum;
141 }
142
143 u32
144 buffer_to_u32( const byte *buffer )
145 {
146     unsigned long a;
147     a =  *buffer << 24;
148     a |= buffer[1] << 16;
149     a |= buffer[2] << 8;
150     a |= buffer[3];
151     return a;
152 }
153
154
155 static void
156 no_exp_algo(void)
157 {
158     static int did_note = 0;
159
160     if( !did_note ) {
161         did_note = 1;
162         log_info(_("Experimental algorithms should not be used!\n"));
163     }
164 }
165
166 void
167 print_pubkey_algo_note( int algo )
168 {
169     if( algo >= 100 && algo <= 110 )
170         no_exp_algo();
171 }
172
173 void
174 print_cipher_algo_note( int algo )
175 {
176     if( algo >= 100 && algo <= 110 )
177         no_exp_algo();
178     else if(    algo == CIPHER_ALGO_3DES
179              || algo == CIPHER_ALGO_CAST5
180              || algo == CIPHER_ALGO_BLOWFISH
181              || algo == CIPHER_ALGO_TWOFISH
182              || algo == CIPHER_ALGO_RIJNDAEL
183              || algo == CIPHER_ALGO_RIJNDAEL192
184              || algo == CIPHER_ALGO_RIJNDAEL256
185            )
186         ;
187     else {
188         static int did_note = 0;
189
190         if( !did_note ) {
191             did_note = 1;
192             log_info(_("this cipher algorithm is deprecated; "
193                        "please use a more standard one!\n"));
194         }
195     }
196 }
197
198 void
199 print_digest_algo_note( int algo )
200 {
201     if( algo >= 100 && algo <= 110 )
202         no_exp_algo();
203 }
204
205
206 /* Return a string which is used as a kind of process ID */
207 const byte *
208 get_session_marker( size_t *rlen )
209 {
210     static byte marker[SIZEOF_UNSIGNED_LONG*2];
211     static int initialized;
212
213     if ( !initialized ) {
214         volatile ulong aa, bb; /* we really want the uninitialized value */
215         ulong a, b;
216
217         initialized = 1;
218         /* also this marker is guessable it is not easy to use this 
219          * for a faked control packet because an attacker does not
220          * have enough control about the time the verification does 
221          * take place.  Of course, we can add just more random but 
222          * than we need the random generator even for verification
223          * tasks - which does not make sense. */
224         a = aa ^ (ulong)getpid();
225         b = bb ^ (ulong)time(NULL);
226         memcpy( marker, &a, SIZEOF_UNSIGNED_LONG );
227         memcpy( marker+SIZEOF_UNSIGNED_LONG, &b, SIZEOF_UNSIGNED_LONG );
228     }
229     *rlen = sizeof(marker);
230     return marker;
231 }
232
233 /****************
234  * Wrapper around the libgcrypt function with addional checks on
235  * openPGP contraints for the algo ID.
236  */
237 int
238 openpgp_cipher_test_algo( int algo )
239 {
240     if( algo < 0 || algo > 110 )
241         return G10ERR_CIPHER_ALGO;
242     return check_cipher_algo(algo);
243 }
244
245 int
246 openpgp_pk_test_algo( int algo, unsigned int usage_flags )
247 {
248     if( algo < 0 || algo > 110 )
249         return G10ERR_PUBKEY_ALGO;
250     return check_pubkey_algo2( algo, usage_flags );
251 }
252
253 int 
254 openpgp_pk_algo_usage ( int algo )
255 {
256     int use = 0; 
257     
258     /* they are hardwired in gpg 1.0 */
259     switch ( algo ) {    
260       case PUBKEY_ALGO_RSA:
261           use = PUBKEY_USAGE_SIG | PUBKEY_USAGE_ENC;
262           break;
263       case PUBKEY_ALGO_RSA_E:
264           use = PUBKEY_USAGE_ENC;
265           break;
266       case PUBKEY_ALGO_RSA_S:
267           use = PUBKEY_USAGE_SIG;
268           break;
269       case PUBKEY_ALGO_ELGAMAL_E:
270           use = PUBKEY_USAGE_ENC;
271           break;
272       case PUBKEY_ALGO_DSA:  
273           use = PUBKEY_USAGE_SIG;
274           break;
275       case PUBKEY_ALGO_ELGAMAL:
276           use = PUBKEY_USAGE_SIG | PUBKEY_USAGE_ENC;
277           break;
278       default:
279           break;
280     }
281     return use;
282 }
283
284 int
285 openpgp_md_test_algo( int algo )
286 {
287     if( algo < 0 || algo > 110 )
288         return G10ERR_DIGEST_ALGO;
289     return check_digest_algo(algo);
290 }
291
292 #ifdef USE_IDEA
293 /* Special warning for the IDEA cipher */
294 void
295 idea_cipher_warn(int show)
296 {
297   static int warned=0;
298
299   if(!warned || show)
300     {
301       log_info(_("the IDEA cipher plugin is not present\n"));
302       log_info(_("please see http://www.gnupg.org/why-not-idea.html "
303                  "for more information\n"));
304       warned=1;
305     }
306 }
307 #endif
308
309 /* Expand %-strings.  Returns a string which must be m_freed.  Returns
310    NULL if the string cannot be expanded (too large). */
311 char *
312 pct_expando(const char *string,struct expando_args *args)
313 {
314   const char *ch=string;
315   int idx=0,maxlen=0,done=0;
316   u32 pk_keyid[2]={0,0},sk_keyid[2]={0,0};
317   char *ret=NULL;
318
319   if(args->pk)
320     keyid_from_pk(args->pk,pk_keyid);
321
322   if(args->sk)
323     keyid_from_sk(args->sk,sk_keyid);
324
325   if(!args->pk && args->sk)
326     keyid_from_sk(args->sk,pk_keyid);
327
328   while(*ch!='\0')
329     {
330       char *str=NULL;
331
332       if(!done)
333         {
334           /* 8192 is way bigger than we'll need here */
335           if(maxlen>=8192)
336             goto fail;
337
338           maxlen+=1024;
339           ret=m_realloc(ret,maxlen);
340         }
341
342       done=0;
343
344       if(*ch=='%')
345         {
346           switch(*(ch+1))
347             {
348             case 's': /* short key id */
349               if(idx+8<maxlen)
350                 {
351                   sprintf(&ret[idx],"%08lX",(ulong)sk_keyid[1]);
352                   idx+=8;
353                   done=1;
354                 }
355               break;
356
357             case 'S': /* long key id */
358               if(idx+16<maxlen)
359                 {
360                   sprintf(&ret[idx],"%08lX%08lX",
361                           (ulong)sk_keyid[0],(ulong)sk_keyid[1]);
362                   idx+=16;
363                   done=1;
364                 }
365               break;
366
367             case 'k': /* short key id */
368               if(idx+8<maxlen)
369                 {
370                   sprintf(&ret[idx],"%08lX",(ulong)pk_keyid[1]);
371                   idx+=8;
372                   done=1;
373                 }
374               break;
375
376             case 'K': /* long key id */
377               if(idx+16<maxlen)
378                 {
379                   sprintf(&ret[idx],"%08lX%08lX",
380                           (ulong)pk_keyid[0],(ulong)pk_keyid[1]);
381                   idx+=16;
382                   done=1;
383                 }
384               break;
385
386             case 'f': /* fingerprint */
387               {
388                 byte array[MAX_FINGERPRINT_LEN];
389                 size_t len;
390                 int i;
391
392                 if(args->pk)
393                   fingerprint_from_pk(args->pk,array,&len);
394                 else
395                   memset(array,0, (len=MAX_FINGERPRINT_LEN));
396
397                 if(idx+(len*2)<maxlen)
398                   {
399                     for(i=0;i<len;i++)
400                       {
401                         sprintf(&ret[idx],"%02X",array[i]);
402                         idx+=2;
403                       }
404                     done=1;
405                   }
406               }
407               break;
408
409             case 't': /* e.g. "jpg" */
410               str=image_type_to_string(args->imagetype,0);
411               /* fall through */
412
413             case 'T': /* e.g. "image/jpeg" */
414               if(str==NULL)
415                 str=image_type_to_string(args->imagetype,2);
416
417               if(idx+strlen(str)<maxlen)
418                 {
419                   strcpy(&ret[idx],str);
420                   idx+=strlen(str);
421                   done=1;
422                 }
423               break;
424
425             case '%':
426               if(idx+1<maxlen)
427                 {
428                   ret[idx++]='%';
429                   ret[idx]='\0';
430                   done=1;
431                 }
432               break;
433
434               /* Any unknown %-keys (like %i, %o, %I, and %O) are
435                  passed through for later expansion.  Note this also
436                  handles the case where the last character in the
437                  string is a '%' - the terminating \0 will end up here
438                  and properly terminate the string. */
439             default:
440               if(idx+2<maxlen)
441                 {
442                   ret[idx++]='%';
443                   ret[idx++]=*(ch+1);
444                   ret[idx]='\0';
445                   done=1;
446                 }
447               break;
448               }
449
450           if(done)
451             ch++;
452         }
453       else
454         {
455           if(idx+1<maxlen)
456             {
457               ret[idx++]=*ch;
458               ret[idx]='\0';
459               done=1;
460             }
461         }
462
463       if(done)
464         ch++;
465     }
466
467   return ret;
468
469  fail:
470   m_free(ret);
471   return NULL;
472 }
473
474 int
475 hextobyte( const char *s )
476 {
477     int c;
478
479     if( *s >= '0' && *s <= '9' )
480         c = 16 * (*s - '0');
481     else if( *s >= 'A' && *s <= 'F' )
482         c = 16 * (10 + *s - 'A');
483     else if( *s >= 'a' && *s <= 'f' )
484         c = 16 * (10 + *s - 'a');
485     else
486         return -1;
487     s++;
488     if( *s >= '0' && *s <= '9' )
489         c += *s - '0';
490     else if( *s >= 'A' && *s <= 'F' )
491         c += 10 + *s - 'A';
492     else if( *s >= 'a' && *s <= 'f' )
493         c += 10 + *s - 'a';
494     else
495         return -1;
496     return c;
497 }
498
499 void
500 deprecated_warning(const char *configname,unsigned int configlineno,
501                    const char *option,const char *repl1,const char *repl2)
502 {
503   if(configname)
504     {
505       if(strncmp("--",option,2)==0)
506         option+=2;
507
508       if(strncmp("--",repl1,2)==0)
509         repl1+=2;
510
511       log_info(_("%s:%d: deprecated option \"%s\"\n"),
512                configname,configlineno,option);
513     }
514   else
515     log_info(_("WARNING: \"%s\" is a deprecated option\n"),option);
516
517   log_info(_("please use \"%s%s\" instead\n"),repl1,repl2);
518 }
519
520 const char *
521 compress_algo_to_string(int algo)
522 {
523   const char *s="?";
524
525   switch(algo)
526     {
527     case 0:
528       s="Uncompressed";
529       break;
530
531     case 1:
532       s="ZIP";
533       break;
534
535     case 2:
536       s="ZLIB";
537       break;
538     }
539
540   return s;
541 }
542
543 int
544 string_to_compress_algo(const char *string)
545 {
546   if(ascii_strcasecmp(string,"uncompressed")==0)
547     return 0;
548   else if(ascii_strcasecmp(string,"zip")==0)
549     return 1;
550   else if(ascii_strcasecmp(string,"zlib")==0)
551     return 2;
552   else if(ascii_strcasecmp(string,"z0")==0)
553     return 0;
554   else if(ascii_strcasecmp(string,"z1")==0)
555     return 1;
556   else if(ascii_strcasecmp(string,"z2")==0)
557     return 2;
558   else
559     return -1;
560 }
561
562 int
563 check_compress_algo(int algo)
564 {
565   if(algo>=0 && algo<=2)
566     return 0;
567
568   return G10ERR_COMPR_ALGO;
569 }
570
571 int
572 default_cipher_algo(void)
573 {
574   if(opt.def_cipher_algo)
575     return opt.def_cipher_algo;
576   else if(opt.personal_cipher_prefs)
577     return opt.personal_cipher_prefs[0].value;
578   else
579     return opt.s2k_cipher_algo;
580 }
581
582 /* There is no default_digest_algo function, but see
583    sign.c:hash_for */
584
585 int
586 default_compress_algo(void)
587 {
588   if(opt.def_compress_algo!=-1)
589     return opt.def_compress_algo;
590   else if(opt.personal_compress_prefs)
591     return opt.personal_compress_prefs[0].value;
592   else
593     return DEFAULT_COMPRESS_ALGO;
594 }
595
596 const char *
597 compliance_option_string(void)
598 {
599   switch(opt.compliance)
600     {
601     case CO_RFC2440:
602       return "--openpgp";
603     case CO_PGP2:
604       return "--pgp2";
605     case CO_PGP6:
606       return "--pgp6";
607     case CO_PGP7:
608       return "--pgp7";
609     case CO_PGP8:
610       return "--pgp8";
611     default:
612       return "???";
613     }
614 }
615
616 static const char *
617 compliance_string(void)
618 {
619   switch(opt.compliance)
620     {
621     case CO_RFC2440:
622       return "OpenPGP";
623     case CO_PGP2:
624       return "PGP 2.x";
625     case CO_PGP6:
626       return "PGP 6.x";
627     case CO_PGP7:
628       return "PGP 7.x";
629     case CO_PGP8:
630       return "PGP 8.x";
631     default:
632       return "???";
633     }
634 }
635
636 void
637 compliance_failure(void)
638 {
639   log_info(_("this message may not be usable by %s\n"),compliance_string());
640   opt.compliance=CO_GNUPG;
641 }