Merged most of David Shaw's changes in 1.3 since 2003-06-03.
[gnupg.git] / g10 / misc.c
1 /* misc.c -  miscellaneous functions
2  * Copyright (C) 1998, 1999, 2000, 2001, 2002,
3  *               2003 Free Software Foundation, Inc.
4  *
5  * This file is part of GnuPG.
6  *
7  * GnuPG is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * GnuPG is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20  */
21
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <errno.h>
28 #include <assert.h>
29 #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
30 #include <asm/sysinfo.h>
31 #include <asm/unistd.h>
32 #endif
33 #ifdef HAVE_SETRLIMIT
34 #include <time.h>
35 #include <sys/time.h>
36 #include <sys/resource.h>
37 #endif
38
39 #include "gpg.h"
40 #include "util.h"
41 #include "main.h"
42 #include "photoid.h"
43 #include "options.h"
44 #include "i18n.h"
45
46 #define MAX_EXTERN_MPI_BITS 16384
47
48
49 #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
50 static int
51 setsysinfo(unsigned long op, void *buffer, unsigned long size,
52                      int *start, void *arg, unsigned long flag)
53 {
54     return syscall(__NR_osf_setsysinfo, op, buffer, size, start, arg, flag);
55 }
56
57 void
58 trap_unaligned(void)
59 {
60     unsigned int buf[2];
61
62     buf[0] = SSIN_UACPROC;
63     buf[1] = UAC_SIGBUS | UAC_NOPRINT;
64     setsysinfo(SSI_NVPAIRS, buf, 1, 0, 0, 0);
65 }
66 #else
67 void
68 trap_unaligned(void)
69 {  /* dummy */
70 }
71 #endif
72
73
74 int
75 disable_core_dumps()
76 {
77 #ifdef HAVE_DOSISH_SYSTEM
78     return 0;
79 #else
80 #ifdef HAVE_SETRLIMIT
81     struct rlimit limit;
82
83     limit.rlim_cur = 0;
84     limit.rlim_max = 0;
85     if( !setrlimit( RLIMIT_CORE, &limit ) )
86         return 0;
87     if( errno != EINVAL && errno != ENOSYS )
88         log_fatal(_("can't disable core dumps: %s\n"), strerror(errno) );
89 #endif
90     return 1;
91 #endif
92 }
93
94
95
96 u16
97 checksum_u16( unsigned n )
98 {
99     u16 a;
100
101     a  = (n >> 8) & 0xff;
102     a += n & 0xff;
103     return a;
104 }
105
106
107 u16
108 checksum( byte *p, unsigned n )
109 {
110     u16 a;
111
112     for(a=0; n; n-- )
113         a += *p++;
114     return a;
115 }
116
117 u16
118 checksum_mpi( gcry_mpi_t a )
119 {
120   int rc;
121   u16 csum;
122   byte *buffer;
123   size_t nbytes;
124
125   rc = gcry_mpi_print( GCRYMPI_FMT_PGP, NULL, 0, &nbytes, a );
126   if (rc)
127     BUG ();
128   /* fixme: for numbers not in secure memory we should use a stack
129    * based buffer and only allocate a larger one if mpi_print return
130    * an error */
131   buffer = gcry_is_secure(a)? gcry_xmalloc_secure(nbytes):gcry_xmalloc(nbytes);
132   rc = gcry_mpi_print (GCRYMPI_FMT_PGP, buffer, nbytes, NULL, a );
133   if (rc)
134     BUG ();
135   csum = checksum (buffer, nbytes );
136   xfree (buffer );
137   return csum;
138 }
139
140 u32
141 buffer_to_u32( const byte *buffer )
142 {
143     unsigned long a;
144     a =  *buffer << 24;
145     a |= buffer[1] << 16;
146     a |= buffer[2] << 8;
147     a |= buffer[3];
148     return a;
149 }
150
151
152 static void
153 no_exp_algo(void)
154 {
155     static int did_note = 0;
156
157     if( !did_note ) {
158         did_note = 1;
159         log_info(_("Experimental algorithms should not be used!\n"));
160     }
161 }
162
163 void
164 print_pubkey_algo_note( int algo )
165 {
166     if( algo >= 100 && algo <= 110 )
167         no_exp_algo();
168 }
169
170 void
171 print_cipher_algo_note( int algo )
172 {
173     if( algo >= 100 && algo <= 110 )
174         no_exp_algo();
175     else if(    algo == CIPHER_ALGO_3DES
176              || algo == CIPHER_ALGO_CAST5
177              || algo == CIPHER_ALGO_BLOWFISH
178              || algo == CIPHER_ALGO_TWOFISH
179              || algo == CIPHER_ALGO_RIJNDAEL
180              || algo == CIPHER_ALGO_RIJNDAEL192
181              || algo == CIPHER_ALGO_RIJNDAEL256
182            )
183         ;
184     else {
185         static int did_note = 0;
186
187         if( !did_note ) {
188             did_note = 1;
189             log_info(_("this cipher algorithm is deprecated; "
190                        "please use a more standard one!\n"));
191         }
192     }
193 }
194
195 void
196 print_digest_algo_note( int algo )
197 {
198     if( algo >= 100 && algo <= 110 )
199         no_exp_algo();
200 }
201
202
203 /* Return a string which is used as a kind of process ID */
204 const byte *
205 get_session_marker( size_t *rlen )
206 {
207     static byte marker[SIZEOF_UNSIGNED_LONG*2];
208     static int initialized;
209
210     if ( !initialized ) {
211         volatile ulong aa, bb; /* we really want the uninitialized value */
212         ulong a, b;
213
214         initialized = 1;
215         /* also this marker is guessable it is not easy to use this 
216          * for a faked control packet because an attacker does not
217          * have enough control about the time the verification does 
218          * take place.  Of course, we can add just more random but 
219          * than we need the random generator even for verification
220          * tasks - which does not make sense. */
221         a = aa ^ (ulong)getpid();
222         b = bb ^ (ulong)time(NULL);
223         memcpy( marker, &a, SIZEOF_UNSIGNED_LONG );
224         memcpy( marker+SIZEOF_UNSIGNED_LONG, &b, SIZEOF_UNSIGNED_LONG );
225     }
226     *rlen = sizeof(marker);
227     return marker;
228 }
229
230 /****************
231  * Wrapper around the libgcrypt function with addional checks on
232  * openPGP contraints for the algo ID.
233  */
234 int
235 openpgp_cipher_test_algo( int algo )
236 {
237     if( algo < 0 || algo > 110 )
238         return GPG_ERR_CIPHER_ALGO;
239     return gcry_cipher_test_algo (algo);
240 }
241
242 int
243 openpgp_pk_test_algo( int algo, unsigned int usage_flags )
244 {
245   size_t value = usage_flags;
246
247   if (algo == GCRY_PK_ELG_E)
248     algo = GCRY_PK_ELG;
249 #warning need to handle the usage here?
250   if (algo < 0 || algo > 110)
251     return GPG_ERR_PUBKEY_ALGO;
252   return gcry_pk_algo_info (algo, GCRYCTL_TEST_ALGO, NULL, &value);
253 }
254
255 int 
256 openpgp_pk_algo_usage ( int algo )
257 {
258     int use = 0; 
259     
260     /* they are hardwired in gpg 1.0 */
261     switch ( algo ) {    
262       case PUBKEY_ALGO_RSA:
263           use = PUBKEY_USAGE_SIG | PUBKEY_USAGE_ENC | PUBKEY_USAGE_AUTH;
264           break;
265       case PUBKEY_ALGO_RSA_E:
266           use = PUBKEY_USAGE_ENC;
267           break;
268       case PUBKEY_ALGO_RSA_S:
269           use = PUBKEY_USAGE_SIG;
270           break;
271       case PUBKEY_ALGO_ELGAMAL_E:
272           use = PUBKEY_USAGE_ENC;
273           break;
274       case PUBKEY_ALGO_DSA:  
275           use = PUBKEY_USAGE_SIG | PUBKEY_USAGE_AUTH;
276           break;
277       case PUBKEY_ALGO_ELGAMAL:
278           use = PUBKEY_USAGE_SIG | PUBKEY_USAGE_ENC | PUBKEY_USAGE_AUTH;
279           break;
280       default:
281           break;
282     }
283     return use;
284 }
285
286 int
287 openpgp_md_test_algo( int algo )
288 {
289     if( algo < 0 || algo > 110 )
290         return GPG_ERR_DIGEST_ALGO;
291     return gcry_md_test_algo (algo);
292 }
293
294 int
295 openpgp_md_map_name (const char *string)
296 {
297   int i = gcry_md_map_name (string);
298
299   if (!i && (string[0]=='H' || string[0]=='h'))
300     { /* Didn't find it, so try the Hx format */
301       long val;
302       char *endptr;
303
304       string++;
305       
306       val=strtol(string,&endptr,10);
307       if (*string!='\0' && *endptr=='\0' && !openpgp_md_test_algo(val))
308         i = val;
309     }
310   return i < 0 || i > 110? 0 : i;
311 }
312
313 int
314 openpgp_cipher_map_name (const char *string)
315 {
316   int i = gcry_cipher_map_name (string);
317
318   if (!i && (string[0]=='S' || string[0]=='s'))
319     { /* Didn't find it, so try the Sx format */
320       long val;
321       char *endptr;
322
323       string++;
324       
325       val=strtol(string,&endptr,10);
326       if (*string!='\0' && *endptr=='\0' && !openpgp_cipher_test_algo(val))
327         i = val;
328     }
329   return i < 0 || i > 110? 0 : i;
330 }
331
332 int
333 openpgp_pk_map_name (const char *string)
334 {
335   int i = gcry_pk_map_name (string);
336   return i < 0 || i > 110? 0 : i;
337 }
338
339 #ifdef USE_IDEA
340 /* Special warning for the IDEA cipher */
341 void
342 idea_cipher_warn(int show)
343 {
344   static int warned=0;
345
346   if(!warned || show)
347     {
348       log_info(_("the IDEA cipher plugin is not present\n"));
349       log_info(_("please see http://www.gnupg.org/why-not-idea.html "
350                  "for more information\n"));
351       warned=1;
352     }
353 }
354 #endif
355
356 /* Expand %-strings.  Returns a string which must be m_freed.  Returns
357    NULL if the string cannot be expanded (too large). */
358 char *
359 pct_expando(const char *string,struct expando_args *args)
360 {
361   const char *ch=string;
362   int idx=0,maxlen=0,done=0;
363   u32 pk_keyid[2]={0,0},sk_keyid[2]={0,0};
364   char *ret=NULL;
365
366   if(args->pk)
367     keyid_from_pk(args->pk,pk_keyid);
368
369   if(args->sk)
370     keyid_from_sk(args->sk,sk_keyid);
371
372   /* This is used so that %k works in photoid command strings in
373      --list-secret-keys (which of course has a sk, but no pk). */
374   if(!args->pk && args->sk)
375     keyid_from_sk(args->sk,pk_keyid);
376
377   while(*ch!='\0')
378     {
379       char *str=NULL;
380
381       if(!done)
382         {
383           /* 8192 is way bigger than we'll need here */
384           if(maxlen>=8192)
385             goto fail;
386
387           maxlen+=1024;
388           ret= xrealloc(ret,maxlen);
389         }
390
391       done=0;
392
393       if(*ch=='%')
394         {
395           switch(*(ch+1))
396             {
397             case 's': /* short key id */
398               if(idx+8<maxlen)
399                 {
400                   sprintf(&ret[idx],"%08lX",(ulong)sk_keyid[1]);
401                   idx+=8;
402                   done=1;
403                 }
404               break;
405
406             case 'S': /* long key id */
407               if(idx+16<maxlen)
408                 {
409                   sprintf(&ret[idx],"%08lX%08lX",
410                           (ulong)sk_keyid[0],(ulong)sk_keyid[1]);
411                   idx+=16;
412                   done=1;
413                 }
414               break;
415
416             case 'k': /* short key id */
417               if(idx+8<maxlen)
418                 {
419                   sprintf(&ret[idx],"%08lX",(ulong)pk_keyid[1]);
420                   idx+=8;
421                   done=1;
422                 }
423               break;
424
425             case 'K': /* long key id */
426               if(idx+16<maxlen)
427                 {
428                   sprintf(&ret[idx],"%08lX%08lX",
429                           (ulong)pk_keyid[0],(ulong)pk_keyid[1]);
430                   idx+=16;
431                   done=1;
432                 }
433               break;
434
435             case 'p': /* primary pk fingerprint of a sk */
436             case 'f': /* pk fingerprint */
437             case 'g': /* sk fingerprint */
438               {
439                 byte array[MAX_FINGERPRINT_LEN];
440                 size_t len;
441                 int i;
442
443                 if( ch[1]=='p' && args->sk)
444                   {
445                     if(args->sk->is_primary)
446                       fingerprint_from_sk(args->sk,array,&len);
447                     else if(args->sk->main_keyid[0] || args->sk->main_keyid[1])
448                       {
449                         PKT_public_key *pk= xcalloc(1, sizeof(PKT_public_key));
450
451                         if(get_pubkey_fast(pk,args->sk->main_keyid)==0)
452                           fingerprint_from_pk(pk,array,&len);
453                         else
454                           memset(array,0,(len=MAX_FINGERPRINT_LEN));
455                         free_public_key(pk);
456                       }
457                     else
458                       memset(array,0,(len=MAX_FINGERPRINT_LEN));
459                   }
460                 else if( ch[1]=='f' && args->pk)
461                   fingerprint_from_pk(args->pk,array,&len);
462                 else if( ch[1]=='g' && args->sk)
463                   fingerprint_from_sk(args->sk,array,&len);
464                 else
465                   memset(array, 0, (len=MAX_FINGERPRINT_LEN));
466
467                 if(idx+(len*2)<maxlen)
468                   {
469                     for(i=0;i<len;i++)
470                       {
471                         sprintf(&ret[idx],"%02X",array[i]);
472                         idx+=2;
473                       }
474                     done=1;
475                   }
476               }
477               break;
478
479             case 't': /* e.g. "jpg" */
480               str=image_type_to_string(args->imagetype,0);
481               /* fall through */
482
483             case 'T': /* e.g. "image/jpeg" */
484               if(str==NULL)
485                 str=image_type_to_string(args->imagetype,2);
486
487               if(idx+strlen(str)<maxlen)
488                 {
489                   strcpy(&ret[idx],str);
490                   idx+=strlen(str);
491                   done=1;
492                 }
493               break;
494
495             case '%':
496               if(idx+1<maxlen)
497                 {
498                   ret[idx++]='%';
499                   ret[idx]='\0';
500                   done=1;
501                 }
502               break;
503
504               /* Any unknown %-keys (like %i, %o, %I, and %O) are
505                  passed through for later expansion.  Note this also
506                  handles the case where the last character in the
507                  string is a '%' - the terminating \0 will end up here
508                  and properly terminate the string. */
509             default:
510               if(idx+2<maxlen)
511                 {
512                   ret[idx++]='%';
513                   ret[idx++]=*(ch+1);
514                   ret[idx]='\0';
515                   done=1;
516                 }
517               break;
518               }
519
520           if(done)
521             ch++;
522         }
523       else
524         {
525           if(idx+1<maxlen)
526             {
527               ret[idx++]=*ch;
528               ret[idx]='\0';
529               done=1;
530             }
531         }
532
533       if(done)
534         ch++;
535     }
536
537   return ret;
538
539  fail:
540   xfree (ret);
541   return NULL;
542 }
543
544 int
545 hextobyte( const char *s )
546 {
547     int c;
548
549     if( *s >= '0' && *s <= '9' )
550         c = 16 * (*s - '0');
551     else if( *s >= 'A' && *s <= 'F' )
552         c = 16 * (10 + *s - 'A');
553     else if( *s >= 'a' && *s <= 'f' )
554         c = 16 * (10 + *s - 'a');
555     else
556         return -1;
557     s++;
558     if( *s >= '0' && *s <= '9' )
559         c += *s - '0';
560     else if( *s >= 'A' && *s <= 'F' )
561         c += 10 + *s - 'A';
562     else if( *s >= 'a' && *s <= 'f' )
563         c += 10 + *s - 'a';
564     else
565         return -1;
566     return c;
567 }
568
569 void
570 deprecated_warning(const char *configname,unsigned int configlineno,
571                    const char *option,const char *repl1,const char *repl2)
572 {
573   if(configname)
574     {
575       if(strncmp("--",option,2)==0)
576         option+=2;
577
578       if(strncmp("--",repl1,2)==0)
579         repl1+=2;
580
581       log_info(_("%s:%d: deprecated option \"%s\"\n"),
582                configname,configlineno,option);
583     }
584   else
585     log_info(_("WARNING: \"%s\" is a deprecated option\n"),option);
586
587   log_info(_("please use \"%s%s\" instead\n"),repl1,repl2);
588 }
589
590 const char *
591 compress_algo_to_string(int algo)
592 {
593   const char *s="?";
594
595   switch(algo)
596     {
597     case 0:
598       s="Uncompressed";
599       break;
600
601     case 1:
602       s="ZIP";
603       break;
604
605     case 2:
606       s="ZLIB";
607       break;
608     }
609
610   return s;
611 }
612
613 int
614 string_to_compress_algo(const char *string)
615 {
616   if(ascii_strcasecmp(string,"uncompressed")==0)
617     return 0;
618   else if(ascii_strcasecmp(string,"zip")==0)
619     return 1;
620   else if(ascii_strcasecmp(string,"zlib")==0)
621     return 2;
622   else if(ascii_strcasecmp(string,"z0")==0)
623     return 0;
624   else if(ascii_strcasecmp(string,"z1")==0)
625     return 1;
626   else if(ascii_strcasecmp(string,"z2")==0)
627     return 2;
628   else
629     return -1;
630 }
631
632 int
633 check_compress_algo(int algo)
634 {
635   if(algo>=0 && algo<=2)
636     return 0;
637
638   return GPG_ERR_COMPR_ALGO;
639 }
640
641 int
642 default_cipher_algo(void)
643 {
644   if(opt.def_cipher_algo)
645     return opt.def_cipher_algo;
646   else if(opt.personal_cipher_prefs)
647     return opt.personal_cipher_prefs[0].value;
648   else
649     return opt.s2k_cipher_algo;
650 }
651
652 /* There is no default_digest_algo function, but see
653    sign.c:hash_for */
654
655 int
656 default_compress_algo(void)
657 {
658   if(opt.def_compress_algo!=-1)
659     return opt.def_compress_algo;
660   else if(opt.personal_compress_prefs)
661     return opt.personal_compress_prefs[0].value;
662   else
663     return DEFAULT_COMPRESS_ALGO;
664 }
665
666 const char *
667 compliance_option_string(void)
668 {
669   switch(opt.compliance)
670     {
671     case CO_RFC2440:
672       return "--openpgp";
673     case CO_PGP2:
674       return "--pgp2";
675     case CO_PGP6:
676       return "--pgp6";
677     case CO_PGP7:
678       return "--pgp7";
679     case CO_PGP8:
680       return "--pgp8";
681     default:
682       return "???";
683     }
684 }
685
686 static const char *
687 compliance_string(void)
688 {
689   switch(opt.compliance)
690     {
691     case CO_RFC2440:
692       return "OpenPGP";
693     case CO_PGP2:
694       return "PGP 2.x";
695     case CO_PGP6:
696       return "PGP 6.x";
697     case CO_PGP7:
698       return "PGP 7.x";
699     case CO_PGP8:
700       return "PGP 8.x";
701     default:
702       return "???";
703     }
704 }
705
706 void
707 compliance_failure(void)
708 {
709   log_info(_("this message may not be usable by %s\n"),compliance_string());
710   opt.compliance=CO_GNUPG;
711 }
712
713 int
714 parse_options(char *str,unsigned int *options,struct parse_options *opts)
715 {
716   char *tok;
717
718   while((tok=strsep(&str," ,")))
719     {
720       int i,rev=0;
721
722       if(tok[0]=='\0')
723         continue;
724
725       if(ascii_strncasecmp("no-",tok,3)==0)
726         {
727           rev=1;
728           tok+=3;
729         }
730
731       for(i=0;opts[i].name;i++)
732         {
733           if(ascii_strcasecmp(opts[i].name,tok)==0)
734             {
735               if(rev)
736                 *options&=~opts[i].bit;
737               else
738                 *options|=opts[i].bit;
739               break;
740             }
741         }
742
743       if(!opts[i].name)
744         return 0;
745     }
746
747   return 1;
748 }
749
750
751
752 /* Temporary helper. */
753 int
754 pubkey_get_npkey( int algo )
755 {
756   size_t n;
757
758   if (algo == GCRY_PK_ELG_E)
759     algo = GCRY_PK_ELG;
760   if (gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NPKEY, NULL, &n))
761     n = 0;
762   return n;
763 }
764
765 /* Temporary helper. */
766 int
767 pubkey_get_nskey( int algo )
768 {
769   size_t n;
770
771   if (algo == GCRY_PK_ELG_E)
772     algo = GCRY_PK_ELG;
773   if (gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NSKEY, NULL, &n ))
774     n = 0;
775   return n;
776 }
777
778 /* Temporary helper. */
779 int
780 pubkey_get_nsig( int algo )
781 {
782   size_t n;
783
784   if (algo == GCRY_PK_ELG_E)
785     algo = GCRY_PK_ELG;
786   if (gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NSIGN, NULL, &n))
787     n = 0;
788   return n;
789 }
790
791 /* Temporary helper. */
792 int
793 pubkey_get_nenc( int algo )
794 {
795   size_t n;
796   
797   if (algo == GCRY_PK_ELG_E)
798     algo = GCRY_PK_ELG;
799   if (gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NENCR, NULL, &n ))
800     n = 0;
801   return n;
802 }
803
804
805 /* Temporary helper. */
806 unsigned int
807 pubkey_nbits( int algo, gcry_mpi_t *key )
808 {
809     int rc, nbits;
810     gcry_sexp_t sexp;
811
812     if( algo == GCRY_PK_DSA ) {
813         rc = gcry_sexp_build ( &sexp, NULL,
814                               "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))",
815                                   key[0], key[1], key[2], key[3] );
816     }
817     else if( algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E ) {
818         rc = gcry_sexp_build ( &sexp, NULL,
819                               "(public-key(elg(p%m)(g%m)(y%m)))",
820                                   key[0], key[1], key[2] );
821     }
822     else if( algo == GCRY_PK_RSA ) {
823         rc = gcry_sexp_build ( &sexp, NULL,
824                               "(public-key(rsa(n%m)(e%m)))",
825                                   key[0], key[1] );
826     }
827     else
828         return 0;
829
830     if ( rc )
831         BUG ();
832
833     nbits = gcry_pk_get_nbits( sexp );
834     gcry_sexp_release( sexp );
835     return nbits;
836 }
837
838 \f
839 /* MPI helper functions. */
840
841
842 /****************
843  * write an mpi to out.
844  */
845 int
846 mpi_write( iobuf_t out, gcry_mpi_t a )
847 {
848     char buffer[(MAX_EXTERN_MPI_BITS+7)/8];
849     size_t nbytes;
850     int rc;
851
852     nbytes = (MAX_EXTERN_MPI_BITS+7)/8;
853     rc = gcry_mpi_print (GCRYMPI_FMT_PGP, buffer, nbytes, &nbytes, a );
854     if( !rc )
855         rc = iobuf_write( out, buffer, nbytes );
856
857     return rc;
858 }
859
860 /****************
861  * Writyeg a MPI to out, but in this case it is an opaque one,
862  * s used vor v3 protected keys.
863  */
864 int
865 mpi_write_opaque( iobuf_t out, gcry_mpi_t a )
866 {
867     size_t nbytes, nbits;
868     int rc;
869     char *p;
870
871     assert( gcry_mpi_get_flag( a, GCRYMPI_FLAG_OPAQUE ) );
872     p = gcry_mpi_get_opaque( a, &nbits );
873     nbytes = (nbits+7) / 8;
874     iobuf_put( out, nbits >> 8 );
875     iobuf_put( out, nbits );
876     rc = iobuf_write( out, p, nbytes );
877     return rc;
878 }
879
880
881 /****************
882  * Read an external representation of an mpi and return the MPI
883  * The external format is a 16 bit unsigned value stored in network byte order,
884  * giving the number of bits for the following integer. The integer is stored
885  * with MSB first (left padded with zeroes to align on a byte boundary).
886  */
887 gcry_mpi_t
888 mpi_read(iobuf_t inp, unsigned int *ret_nread, int secure)
889 {
890     int c, c1, c2, i;
891     unsigned int nbits, nbytes, nread=0;
892     gcry_mpi_t a = NULL;
893     byte *buf = NULL;
894     byte *p;
895
896     if( (c = c1 = iobuf_get(inp)) == -1 )
897         goto leave;
898     nbits = c << 8;
899     if( (c = c2 = iobuf_get(inp)) == -1 )
900         goto leave;
901     nbits |= c;
902     if( nbits > MAX_EXTERN_MPI_BITS ) {
903         log_error("mpi too large (%u bits)\n", nbits);
904         goto leave;
905     }
906     nread = 2;
907     nbytes = (nbits+7) / 8;
908     buf = secure? gcry_xmalloc_secure( nbytes+2 ) : gcry_xmalloc( nbytes+2 );
909     p = buf;
910     p[0] = c1;
911     p[1] = c2;
912     for( i=0 ; i < nbytes; i++ ) {
913         p[i+2] = iobuf_get(inp) & 0xff;
914         nread++;
915     }
916     nread += nbytes;
917     if( gcry_mpi_scan( &a, GCRYMPI_FMT_PGP, buf, nread, &nread ) )
918         a = NULL;
919
920   leave:
921     gcry_free(buf);
922     if( nread > *ret_nread )
923         log_bug("mpi larger than packet");
924     else
925         *ret_nread = nread;
926     return a;
927 }
928
929 /****************
930  * Same as mpi_read but the value is stored as an opaque MPI.
931  * This function is used to read encrypted MPI of v3 packets.
932  */
933 gcry_mpi_t
934 mpi_read_opaque(iobuf_t inp, unsigned *ret_nread )
935 {
936     int c, c1, c2, i;
937     unsigned nbits, nbytes, nread=0;
938     gcry_mpi_t a = NULL;
939     byte *buf = NULL;
940     byte *p;
941
942     if( (c = c1 = iobuf_get(inp)) == -1 )
943         goto leave;
944     nbits = c << 8;
945     if( (c = c2 = iobuf_get(inp)) == -1 )
946         goto leave;
947     nbits |= c;
948     if( nbits > MAX_EXTERN_MPI_BITS ) {
949         log_error("mpi too large (%u bits)\n", nbits);
950         goto leave;
951     }
952     nread = 2;
953     nbytes = (nbits+7) / 8;
954     buf = gcry_xmalloc( nbytes );
955     p = buf;
956     for( i=0 ; i < nbytes; i++ ) {
957         p[i] = iobuf_get(inp) & 0xff;
958     }
959     nread += nbytes;
960     a = gcry_mpi_set_opaque(NULL, buf, nbits );
961     buf = NULL;
962
963   leave:
964     gcry_free(buf);
965     if( nread > *ret_nread )
966         log_bug("mpi larger than packet");
967     else
968         *ret_nread = nread;
969     return a;
970 }
971
972
973 int
974 mpi_print( FILE *fp, gcry_mpi_t a, int mode )
975 {
976     int n=0;
977
978     if( !a )
979         return fprintf(fp, "[MPI_NULL]");
980     if( !mode ) {
981         unsigned int n1;
982         n1 = gcry_mpi_get_nbits(a);
983         n += fprintf(fp, "[%u bits]", n1);
984     }
985     else {
986         int rc;
987         unsigned char *buffer;
988
989         rc = gcry_mpi_aprint( GCRYMPI_FMT_HEX, &buffer, NULL, a );
990         assert( !rc );
991         fputs( buffer, fp );
992         n += strlen(buffer);
993         gcry_free( buffer );
994     }
995     return n;
996 }
997
998