Integrating http://code.google.com/p/gnupg-ecc/source/detail?r=15 .
[gnupg.git] / g10 / misc.c
1 /* misc.c - miscellaneous functions
2  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
3  *               2008, 2009 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 3 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, see <http://www.gnu.org/licenses/>.
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 #ifdef ENABLE_SELINUX_HACKS
37 #include <sys/stat.h>
38 #endif
39
40 #ifdef HAVE_W32_SYSTEM
41 #include <time.h>
42 #include <process.h>
43 #include <windows.h> 
44 #include <shlobj.h>
45 #ifndef CSIDL_APPDATA
46 #define CSIDL_APPDATA 0x001a
47 #endif
48 #ifndef CSIDL_LOCAL_APPDATA
49 #define CSIDL_LOCAL_APPDATA 0x001c
50 #endif
51 #ifndef CSIDL_FLAG_CREATE
52 #define CSIDL_FLAG_CREATE 0x8000
53 #endif
54 #endif /*HAVE_W32_SYSTEM*/
55
56 #include "gpg.h"
57 #ifdef HAVE_W32_SYSTEM
58 # include "status.h"
59 #endif /*HAVE_W32_SYSTEM*/
60 #include "util.h"
61 #include "main.h"
62 #include "photoid.h"
63 #include "options.h"
64 #include "call-agent.h"
65 #include "i18n.h"
66
67 #include <assert.h>
68
69 static int
70 string_count_chr (const char *string, int c)
71 {
72   int count;
73
74   for (count=0; *string; string++ )
75     if ( *string == c )
76       count++;
77   return count;
78 }
79
80
81
82 #ifdef ENABLE_SELINUX_HACKS
83 /* A object and a global variable to keep track of files marked as
84    secured. */
85 struct secured_file_item 
86 {
87   struct secured_file_item *next;
88   ino_t ino;
89   dev_t dev;
90 };
91 static struct secured_file_item *secured_files;
92 #endif /*ENABLE_SELINUX_HACKS*/
93
94
95
96
97 /* For the sake of SELinux we want to restrict access through gpg to
98    certain files we keep under our own control.  This function
99    registers such a file and is_secured_file may then be used to
100    check whether a file has ben registered as secured. */
101 void
102 register_secured_file (const char *fname)
103 {
104 #ifdef ENABLE_SELINUX_HACKS
105   struct stat buf;
106   struct secured_file_item *sf;
107
108   /* Note that we stop immediatley if something goes wrong here. */
109   if (stat (fname, &buf))
110     log_fatal (_("fstat of `%s' failed in %s: %s\n"), fname, 
111                "register_secured_file", strerror (errno));
112 /*   log_debug ("registering `%s' i=%lu.%lu\n", fname, */
113 /*              (unsigned long)buf.st_dev, (unsigned long)buf.st_ino); */
114   for (sf=secured_files; sf; sf = sf->next)
115     {
116       if (sf->ino == buf.st_ino && sf->dev == buf.st_dev)
117         return; /* Already registered.  */
118     }
119
120   sf = xmalloc (sizeof *sf);
121   sf->ino = buf.st_ino;
122   sf->dev = buf.st_dev;
123   sf->next = secured_files;
124   secured_files = sf;
125 #else /*!ENABLE_SELINUX_HACKS*/
126   (void)fname;
127 #endif /*!ENABLE_SELINUX_HACKS*/
128 }
129
130 /* Remove a file registered as secure. */
131 void
132 unregister_secured_file (const char *fname)
133 {
134 #ifdef ENABLE_SELINUX_HACKS
135   struct stat buf;
136   struct secured_file_item *sf, *sfprev;
137
138   if (stat (fname, &buf))
139     {
140       log_error (_("fstat of `%s' failed in %s: %s\n"), fname,
141                  "unregister_secured_file", strerror (errno));
142       return;
143     }
144 /*   log_debug ("unregistering `%s' i=%lu.%lu\n", fname,  */
145 /*              (unsigned long)buf.st_dev, (unsigned long)buf.st_ino); */
146   for (sfprev=NULL,sf=secured_files; sf; sfprev=sf, sf = sf->next)
147     {
148       if (sf->ino == buf.st_ino && sf->dev == buf.st_dev)
149         {
150           if (sfprev)
151             sfprev->next = sf->next;
152           else
153             secured_files = sf->next;
154           xfree (sf);
155           return;
156         }
157     }
158 #else /*!ENABLE_SELINUX_HACKS*/
159   (void)fname;
160 #endif /*!ENABLE_SELINUX_HACKS*/
161 }
162
163 /* Return true if FD is corresponds to a secured file.  Using -1 for
164    FS is allowed and will return false. */ 
165 int 
166 is_secured_file (int fd)
167 {
168 #ifdef ENABLE_SELINUX_HACKS
169   struct stat buf;
170   struct secured_file_item *sf;
171
172   if (fd == -1)
173     return 0; /* No file descriptor so it can't be secured either.  */
174
175   /* Note that we print out a error here and claim that a file is
176      secure if something went wrong. */
177   if (fstat (fd, &buf))
178     {
179       log_error (_("fstat(%d) failed in %s: %s\n"), fd, 
180                  "is_secured_file", strerror (errno));
181       return 1;
182     }
183 /*   log_debug ("is_secured_file (%d) i=%lu.%lu\n", fd, */
184 /*              (unsigned long)buf.st_dev, (unsigned long)buf.st_ino); */
185   for (sf=secured_files; sf; sf = sf->next)
186     {
187       if (sf->ino == buf.st_ino && sf->dev == buf.st_dev)
188         return 1; /* Yes.  */
189     }
190 #else /*!ENABLE_SELINUX_HACKS*/
191   (void)fd;
192 #endif /*!ENABLE_SELINUX_HACKS*/
193   return 0; /* No. */
194 }
195
196 /* Return true if FNAME is corresponds to a secured file.  Using NULL,
197    "" or "-" for FS is allowed and will return false. This function is
198    used before creating a file, thus it won't fail if the file does
199    not exist. */ 
200 int 
201 is_secured_filename (const char *fname)
202 {
203 #ifdef ENABLE_SELINUX_HACKS
204   struct stat buf;
205   struct secured_file_item *sf;
206
207   if (iobuf_is_pipe_filename (fname) || !*fname)
208     return 0; 
209
210   /* Note that we print out a error here and claim that a file is
211      secure if something went wrong. */
212   if (stat (fname, &buf))
213     {
214       if (errno == ENOENT || errno == EPERM || errno == EACCES)
215         return 0;
216       log_error (_("fstat of `%s' failed in %s: %s\n"), fname,
217                  "is_secured_filename", strerror (errno));
218       return 1;
219     }
220 /*   log_debug ("is_secured_filename (%s) i=%lu.%lu\n", fname, */
221 /*              (unsigned long)buf.st_dev, (unsigned long)buf.st_ino); */
222   for (sf=secured_files; sf; sf = sf->next)
223     {
224       if (sf->ino == buf.st_ino && sf->dev == buf.st_dev)
225         return 1; /* Yes.  */
226     }
227 #else /*!ENABLE_SELINUX_HACKS*/
228   (void)fname;
229 #endif /*!ENABLE_SELINUX_HACKS*/
230   return 0; /* No. */
231 }
232
233
234
235 u16
236 checksum_u16( unsigned n )
237 {
238     u16 a;
239
240     a  = (n >> 8) & 0xff;
241     a += n & 0xff;
242     return a;
243 }
244
245
246 u16
247 checksum( byte *p, unsigned n )
248 {
249     u16 a;
250
251     for(a=0; n; n-- )
252         a += *p++;
253     return a;
254 }
255
256 u16
257 checksum_mpi (gcry_mpi_t a)
258 {
259   u16 csum;
260   byte *buffer;
261   size_t nbytes;
262
263   if ( gcry_mpi_print (GCRYMPI_FMT_PGP, NULL, 0, &nbytes, a) )
264     BUG ();
265   /* Fixme: For numbers not in secure memory we should use a stack
266    * based buffer and only allocate a larger one if mpi_print returns
267    * an error. */
268   buffer = (gcry_is_secure(a)?
269             gcry_xmalloc_secure (nbytes) : gcry_xmalloc (nbytes));
270   if ( gcry_mpi_print (GCRYMPI_FMT_PGP, buffer, nbytes, NULL, a) )
271     BUG ();
272   csum = checksum (buffer, nbytes);
273   xfree (buffer);
274   return csum;
275 }
276
277 u32
278 buffer_to_u32( const byte *buffer )
279 {
280     unsigned long a;
281     a =  *buffer << 24;
282     a |= buffer[1] << 16;
283     a |= buffer[2] << 8;
284     a |= buffer[3];
285     return a;
286 }
287
288 void
289 print_pubkey_algo_note( int algo )
290 {
291   if(algo >= 100 && algo <= 110)
292     {
293       static int warn=0;
294       if(!warn)
295         {
296           warn=1;
297           log_info (_("WARNING: using experimental public key algorithm %s\n"),
298                     openpgp_cipher_algo_name (algo));
299         }
300     }
301   else if (algo == 20)
302     {
303       log_info (_("WARNING: Elgamal sign+encrypt keys are deprecated\n"));
304     }
305 }
306
307 void
308 print_cipher_algo_note( int algo )
309 {
310   if(algo >= 100 && algo <= 110)
311     {
312       static int warn=0;
313       if(!warn)
314         {
315           warn=1;
316           log_info (_("WARNING: using experimental cipher algorithm %s\n"),
317                     openpgp_cipher_algo_name (algo));
318         }
319     }
320 }
321
322 void
323 print_digest_algo_note( int algo )
324 {
325   if(algo >= 100 && algo <= 110)
326     {
327       static int warn=0;
328       if(!warn)
329         {
330           warn=1;
331           log_info (_("WARNING: using experimental digest algorithm %s\n"),
332                     gcry_md_algo_name (algo));
333         }
334     }
335   else if(algo==DIGEST_ALGO_MD5)
336     log_info (_("WARNING: digest algorithm %s is deprecated\n"),
337               gcry_md_algo_name (algo));
338 }
339
340
341 /* Map OpenPGP algo numbers to those used by Libgcrypt.  We need to do
342    this for algorithms we implemented in Libgcrypt after they become
343    part of OpenPGP.  */
344 int
345 map_cipher_openpgp_to_gcry (int algo)
346 {
347   switch (algo)
348     {
349     case CIPHER_ALGO_CAMELLIA128: return 310; 
350     case CIPHER_ALGO_CAMELLIA192: return 311; 
351     case CIPHER_ALGO_CAMELLIA256: return 312; 
352     default: return algo;
353     }
354 }
355
356 /* The inverse fucntion of above.  */
357 static int
358 map_cipher_gcry_to_openpgp (int algo)
359 {
360   switch (algo)
361     {
362     case 310: return CIPHER_ALGO_CAMELLIA128;
363     case 311: return CIPHER_ALGO_CAMELLIA192;
364     case 312: return CIPHER_ALGO_CAMELLIA256;
365     default: return algo;
366     }
367 }
368
369 int
370 map_pk_openpgp_to_gcry (int algo)
371 {
372   return (algo==PUBKEY_ALGO_ECDSA ? GCRY_PK_ECDSA : (algo==PUBKEY_ALGO_ECDH ? GCRY_PK_ECDH : algo));
373 }
374
375
376 /* Return the block length of an OpenPGP cipher algorithm.  */
377 int 
378 openpgp_cipher_blocklen (int algo)
379 {
380   /* We use the numbers from OpenPGP to be sure that we get the right
381      block length.  This is so that the packet parsing code works even
382      for unknown algorithms (for which we assume 8 due to tradition).
383
384      NOTE: If you change the the returned blocklen above 16, check
385      the callers because they may use a fixed size buffer of that
386      size. */
387   switch (algo)
388     {
389     case 7: case 8: case 9: /* AES */
390     case 10: /* Twofish */
391     case 11: case 12: case 13: /* Camellia */
392       return 16;
393
394     default:
395       return 8;
396     }
397 }
398
399 /****************
400  * Wrapper around the libgcrypt function with additonal checks on
401  * the OpenPGP contraints for the algo ID.
402  */
403 int
404 openpgp_cipher_test_algo( int algo )
405 {
406   /* (5 and 6 are marked reserved by rfc4880.)  */
407   if ( algo < 0 || algo > 110 || algo == 5 || algo == 6 )
408     return gpg_error (GPG_ERR_CIPHER_ALGO);
409
410   return gcry_cipher_test_algo (map_cipher_openpgp_to_gcry (algo));
411 }
412
413 /* Map the OpenPGP cipher algorithm whose ID is contained in ALGORITHM to a
414    string representation of the algorithm name.  For unknown algorithm
415    IDs this function returns "?".  */
416 const char *
417 openpgp_cipher_algo_name (int algo) 
418 {
419   return gcry_cipher_algo_name (map_cipher_openpgp_to_gcry (algo));
420 }
421
422 const char *
423 openpgp_pk_algo_name (int algo) 
424 {
425   return gcry_pk_algo_name ( algo == PUBKEY_ALGO_ECDSA ? GCRY_PK_ECDSA : ( algo == PUBKEY_ALGO_ECDH ? GCRY_PK_ECDH : algo ) );
426 }
427
428 int
429 openpgp_pk_test_algo( int algo )
430 {
431   /* Dont't allow type 20 keys unless in rfc2440 mode.  */
432   if (!RFC2440 && algo == 20)
433     return gpg_error (GPG_ERR_PUBKEY_ALGO);
434     
435   if (algo == GCRY_PK_ELG_E)
436     algo = GCRY_PK_ELG;
437
438   if (algo < 0 || algo > 110)
439     return gpg_error (GPG_ERR_PUBKEY_ALGO);
440
441   if( algo == PUBKEY_ALGO_ECDSA )
442     algo = GCRY_PK_ECDSA;
443   else if( algo == PUBKEY_ALGO_ECDH )
444     algo = GCRY_PK_ECDH;
445
446   return gcry_pk_test_algo ( algo );
447 }
448
449 int
450 openpgp_pk_test_algo2( int algo, unsigned int use )
451 {
452   size_t use_buf = use;
453
454   /* Dont't allow type 20 keys unless in rfc2440 mode.  */
455   if (!RFC2440 && algo == 20)
456     return gpg_error (GPG_ERR_PUBKEY_ALGO);
457
458   if (algo == GCRY_PK_ELG_E)
459     algo = GCRY_PK_ELG;
460
461   if (algo < 0 || algo > 110)
462     return gpg_error (GPG_ERR_PUBKEY_ALGO);
463
464   if( algo == PUBKEY_ALGO_ECDSA )
465     algo = GCRY_PK_ECDSA;
466   else if( algo == PUBKEY_ALGO_ECDH )
467     algo = GCRY_PK_ECDH;
468
469   return gcry_pk_algo_info ( algo, GCRYCTL_TEST_ALGO, NULL, &use_buf);
470 }
471
472 int 
473 openpgp_pk_algo_usage ( int algo )
474 {
475     int use = 0; 
476     
477     /* They are hardwired in gpg 1.0. */
478     switch ( algo ) {    
479       case PUBKEY_ALGO_RSA:
480           use = (PUBKEY_USAGE_CERT | PUBKEY_USAGE_SIG
481                  | PUBKEY_USAGE_ENC | PUBKEY_USAGE_AUTH);
482           break;
483       case PUBKEY_ALGO_RSA_E:
484       case PUBKEY_ALGO_ECDH:
485           use = PUBKEY_USAGE_ENC;
486           break;
487       case PUBKEY_ALGO_RSA_S:
488           use = PUBKEY_USAGE_CERT | PUBKEY_USAGE_SIG;
489           break;
490       case PUBKEY_ALGO_ELGAMAL:
491           if (RFC2440)
492              use = PUBKEY_USAGE_ENC;
493           break;
494       case PUBKEY_ALGO_ELGAMAL_E:
495           use = PUBKEY_USAGE_ENC;
496           break;
497       case PUBKEY_ALGO_DSA:  
498           use = PUBKEY_USAGE_CERT | PUBKEY_USAGE_SIG | PUBKEY_USAGE_AUTH;
499           break;
500       case PUBKEY_ALGO_ECDSA:
501           use = PUBKEY_USAGE_CERT | PUBKEY_USAGE_SIG | PUBKEY_USAGE_AUTH;
502       default:
503           break;
504     }
505     return use;
506 }
507
508 /* Map the OpenPGP pubkey algorithm whose ID is contained in ALGO to a
509    string representation of the algorithm name.  For unknown algorithm
510    IDs this function returns "?".  
511 const char *
512 openpgp_pk_algo_name (int algo) 
513 {
514   switch (algo)
515     {    
516     case PUBKEY_ALGO_RSA:
517     case PUBKEY_ALGO_RSA_E:
518     case PUBKEY_ALGO_RSA_S: return "rsa";
519
520     case PUBKEY_ALGO_ELGAMAL:
521     case PUBKEY_ALGO_ELGAMAL_E: return "elg";
522
523     case PUBKEY_ALGO_DSA:  return "dsa";
524
525     default: return "?";
526     }
527 }
528 */
529
530
531 int
532 openpgp_md_test_algo( int algo )
533 {
534   /* Note: If the list of actual supported OpenPGP algorithms changes,
535      make sure that our hard coded values at
536      print_status_begin_signing() gets updated. */
537   /* 4, 5, 6, 7 are defined by rfc2440 but will be removed from the
538      next revision of the standard.  */
539   if (algo < 0 || algo > 110 || (algo >= 4 && algo <= 7))
540     return gpg_error (GPG_ERR_DIGEST_ALGO);
541   return gcry_md_test_algo (algo);
542 }
543
544
545 /* Map the OpenPGP digest algorithm whose ID is contained in ALGO to a
546    string representation of the algorithm name.  For unknown algorithm
547    IDs this function returns "?".  */
548 const char *
549 openpgp_md_algo_name (int algo) 
550 {
551   if (algo < 0 || algo > 110)
552     return "?";
553   return gcry_md_algo_name (algo);
554 }
555
556
557 #ifdef USE_IDEA
558 /* Special warning for the IDEA cipher */
559 void
560 idea_cipher_warn(int show)
561 {
562   static int warned=0;
563
564   if(!warned || show)
565     {
566       log_info(_("the IDEA cipher plugin is not present\n"));
567       log_info(_("please see %s for more information\n"),
568                "http://www.gnupg.org/faq/why-not-idea.html");
569       warned=1;
570     }
571 }
572 #endif
573
574
575 static unsigned long 
576 get_signature_count (PKT_public_key *pk)
577 {
578 #ifdef ENABLE_CARD_SUPPORT
579   struct agent_card_info_s info;
580 #warning fixme: We should check that the correct card has been inserted
581   if (!agent_scd_getattr ("SIG-COUNTER",&info))
582     return info.sig_counter;
583   else
584     return 0;
585 #else
586   (void)pk;
587   return 0;
588 #endif
589 }
590
591 /* Expand %-strings.  Returns a string which must be xfreed.  Returns
592    NULL if the string cannot be expanded (too large). */
593 char *
594 pct_expando(const char *string,struct expando_args *args)
595 {
596   const char *ch=string;
597   int idx=0,maxlen=0,done=0;
598   u32 pk_keyid[2]={0,0},sk_keyid[2]={0,0};
599   char *ret=NULL;
600
601   if(args->pk)
602     keyid_from_pk(args->pk,pk_keyid);
603
604   if(args->pksk)
605     keyid_from_pk (args->pksk, sk_keyid);
606
607   /* This is used so that %k works in photoid command strings in
608      --list-secret-keys (which of course has a sk, but no pk). */
609   if(!args->pk && args->pksk)
610     keyid_from_pk (args->pksk, pk_keyid);
611
612   while(*ch!='\0')
613     {
614       if(!done)
615         {
616           /* 8192 is way bigger than we'll need here */
617           if(maxlen>=8192)
618             goto fail;
619
620           maxlen+=1024;
621           ret=xrealloc(ret,maxlen);
622         }
623
624       done=0;
625
626       if(*ch=='%')
627         {
628           switch(*(ch+1))
629             {
630             case 's': /* short key id */
631               if(idx+8<maxlen)
632                 {
633                   sprintf(&ret[idx],"%08lX",(ulong)sk_keyid[1]);
634                   idx+=8;
635                   done=1;
636                 }
637               break;
638
639             case 'S': /* long key id */
640               if(idx+16<maxlen)
641                 {
642                   sprintf(&ret[idx],"%08lX%08lX",
643                           (ulong)sk_keyid[0],(ulong)sk_keyid[1]);
644                   idx+=16;
645                   done=1;
646                 }
647               break;
648
649             case 'k': /* short key id */
650               if(idx+8<maxlen)
651                 {
652                   sprintf(&ret[idx],"%08lX",(ulong)pk_keyid[1]);
653                   idx+=8;
654                   done=1;
655                 }
656               break;
657
658             case 'K': /* long key id */
659               if(idx+16<maxlen)
660                 {
661                   sprintf(&ret[idx],"%08lX%08lX",
662                           (ulong)pk_keyid[0],(ulong)pk_keyid[1]);
663                   idx+=16;
664                   done=1;
665                 }
666               break;
667
668             case 'c': /* signature count from card, if any. */
669               if(idx+10<maxlen)
670                 {
671                   sprintf (&ret[idx],"%lu", get_signature_count (args->pksk));
672                   idx+=strlen(&ret[idx]);
673                   done=1;
674                 }             
675               break;
676
677             case 'p': /* primary pk fingerprint of a sk */
678             case 'f': /* pk fingerprint */
679             case 'g': /* sk fingerprint */
680               {
681                 byte array[MAX_FINGERPRINT_LEN];
682                 size_t len;
683                 int i;
684
685                 if((*(ch+1))=='p' && args->pksk)
686                   {
687                     if(args->pksk->flags.primary)
688                       fingerprint_from_pk (args->pksk, array, &len);
689                     else if (args->pksk->main_keyid[0]
690                              || args->pksk->main_keyid[1])
691                       {
692                         /* FIXME: Document teh code and check whether
693                            it is still needed.  */
694                         PKT_public_key *pk=
695                           xmalloc_clear(sizeof(PKT_public_key));
696
697                         if (!get_pubkey_fast (pk,args->pksk->main_keyid))
698                           fingerprint_from_pk (pk, array, &len);
699                         else
700                           memset (array, 0, (len=MAX_FINGERPRINT_LEN));
701                         free_public_key (pk);
702                       }
703                     else
704                       memset(array,0,(len=MAX_FINGERPRINT_LEN));
705                   }
706                 else if((*(ch+1))=='f' && args->pk)
707                   fingerprint_from_pk (args->pk, array, &len);
708                 else if((*(ch+1))=='g' && args->pksk)
709                   fingerprint_from_pk (args->pksk, array, &len);
710                 else
711                   memset(array,0,(len=MAX_FINGERPRINT_LEN));
712
713                 if(idx+(len*2)<maxlen)
714                   {
715                     for(i=0;i<len;i++)
716                       {
717                         sprintf(&ret[idx],"%02X",array[i]);
718                         idx+=2;
719                       }
720                     done=1;
721                   }
722               }
723               break;
724
725             case 'v': /* validity letters */
726               if(args->validity_info && idx+1<maxlen)
727                 {
728                   ret[idx++]=args->validity_info;
729                   ret[idx]='\0';
730                   done=1;
731                 }
732               break;
733
734               /* The text string types */
735             case 't':
736             case 'T':
737             case 'V':
738               {
739                 const char *str=NULL;
740
741                 switch(*(ch+1))
742                   {
743                   case 't': /* e.g. "jpg" */
744                     str=image_type_to_string(args->imagetype,0);
745                     break;
746                   
747                   case 'T': /* e.g. "image/jpeg" */
748                     str=image_type_to_string(args->imagetype,2);
749                     break;
750
751                   case 'V': /* e.g. "full", "expired", etc. */
752                     str=args->validity_string;
753                     break;
754                   }
755
756                 if(str && idx+strlen(str)<maxlen)
757                   {
758                     strcpy(&ret[idx],str);
759                     idx+=strlen(str);
760                     done=1;
761                   }
762               }
763               break;
764
765             case '%':
766               if(idx+1<maxlen)
767                 {
768                   ret[idx++]='%';
769                   ret[idx]='\0';
770                   done=1;
771                 }
772               break;
773
774               /* Any unknown %-keys (like %i, %o, %I, and %O) are
775                  passed through for later expansion.  Note this also
776                  handles the case where the last character in the
777                  string is a '%' - the terminating \0 will end up here
778                  and properly terminate the string. */
779             default:
780               if(idx+2<maxlen)
781                 {
782                   ret[idx++]='%';
783                   ret[idx++]=*(ch+1);
784                   ret[idx]='\0';
785                   done=1;
786                 }
787               break;
788               }
789
790           if(done)
791             ch++;
792         }
793       else
794         {
795           if(idx+1<maxlen)
796             {
797               ret[idx++]=*ch;
798               ret[idx]='\0';
799               done=1;
800             }
801         }
802
803       if(done)
804         ch++;
805     }
806
807   return ret;
808
809  fail:
810   xfree(ret);
811   return NULL;
812 }
813
814 void
815 deprecated_warning(const char *configname,unsigned int configlineno,
816                    const char *option,const char *repl1,const char *repl2)
817 {
818   if(configname)
819     {
820       if(strncmp("--",option,2)==0)
821         option+=2;
822
823       if(strncmp("--",repl1,2)==0)
824         repl1+=2;
825
826       log_info(_("%s:%d: deprecated option \"%s\"\n"),
827                configname,configlineno,option);
828     }
829   else
830     log_info(_("WARNING: \"%s\" is a deprecated option\n"),option);
831
832   log_info(_("please use \"%s%s\" instead\n"),repl1,repl2);
833 }
834
835
836 void
837 deprecated_command (const char *name)
838 {
839   log_info(_("WARNING: \"%s\" is a deprecated command - do not use it\n"),
840            name);
841 }
842
843
844 void
845 obsolete_option (const char *configname, unsigned int configlineno, 
846                  const char *name)
847 {
848   if(configname)
849     log_info (_("%s:%u: obsolete option \"%s\" - it has no effect\n"),
850               configname, configlineno, name);
851   else
852     log_info (_("WARNING: \"%s\" is an obsolete option - it has no effect\n"),
853               name);
854 }
855
856
857 /*
858  * Wrapper around gcry_cipher_map_name to provide a fallback using the
859  * "Sn" syntax as used by the preference strings.
860  */
861 int 
862 string_to_cipher_algo (const char *string) 
863
864   int val;
865
866   val = map_cipher_gcry_to_openpgp (gcry_cipher_map_name (string));
867   if (!val && string && (string[0]=='S' || string[0]=='s'))
868     {
869       char *endptr;
870
871       string++;
872       val = strtol (string, &endptr, 10);
873       if (!*string || *endptr || openpgp_cipher_test_algo (val))
874         val = 0;
875     }
876
877   return val;
878 }
879
880 /*
881  * Wrapper around gcry_md_map_name to provide a fallback using the
882  * "Hn" syntax as used by the preference strings.
883  */
884 int 
885 string_to_digest_algo (const char *string) 
886
887   int val;
888
889   val = gcry_md_map_name (string);
890   if (!val && string && (string[0]=='H' || string[0]=='h'))
891     {
892       char *endptr;
893
894       string++;
895       val = strtol (string, &endptr, 10);
896       if (!*string || *endptr || openpgp_md_test_algo (val))
897         val = 0;
898     }
899
900   return val;
901 }
902
903
904
905 const char *
906 compress_algo_to_string(int algo)
907 {
908   const char *s=NULL;
909
910   switch(algo)
911     {
912     case COMPRESS_ALGO_NONE:
913       s=_("Uncompressed");
914       break;
915
916     case COMPRESS_ALGO_ZIP:
917       s="ZIP";
918       break;
919
920     case COMPRESS_ALGO_ZLIB:
921       s="ZLIB";
922       break;
923
924 #ifdef HAVE_BZIP2
925     case COMPRESS_ALGO_BZIP2:
926       s="BZIP2";
927       break;
928 #endif
929     }
930
931   return s;
932 }
933
934 int
935 string_to_compress_algo(const char *string)
936 {
937   /* TRANSLATORS: See doc/TRANSLATE about this string. */
938   if(match_multistr(_("uncompressed|none"),string))
939     return 0;
940   else if(ascii_strcasecmp(string,"uncompressed")==0)
941     return 0;
942   else if(ascii_strcasecmp(string,"none")==0)
943     return 0;
944   else if(ascii_strcasecmp(string,"zip")==0)
945     return 1;
946   else if(ascii_strcasecmp(string,"zlib")==0)
947     return 2;
948 #ifdef HAVE_BZIP2
949   else if(ascii_strcasecmp(string,"bzip2")==0)
950     return 3;
951 #endif
952   else if(ascii_strcasecmp(string,"z0")==0)
953     return 0;
954   else if(ascii_strcasecmp(string,"z1")==0)
955     return 1;
956   else if(ascii_strcasecmp(string,"z2")==0)
957     return 2;
958 #ifdef HAVE_BZIP2
959   else if(ascii_strcasecmp(string,"z3")==0)
960     return 3;
961 #endif
962   else
963     return -1;
964 }
965
966 int
967 check_compress_algo(int algo)
968 {
969   switch (algo)
970     {
971     case 0: return 0;
972 #ifdef HAVE_ZIP
973     case 1:  
974     case 2: return 0;
975 #endif
976 #ifdef HAVE_BZIP2
977     case 3: return 0;
978 #endif
979     default: return G10ERR_COMPR_ALGO;
980     }
981 }
982
983 int
984 default_cipher_algo(void)
985 {
986   if(opt.def_cipher_algo)
987     return opt.def_cipher_algo;
988   else if(opt.personal_cipher_prefs)
989     return opt.personal_cipher_prefs[0].value;
990   else
991     return opt.s2k_cipher_algo;
992 }
993
994 /* There is no default_digest_algo function, but see
995    sign.c:hash_for() */
996
997 int
998 default_compress_algo(void)
999 {
1000   if(opt.compress_algo!=-1)
1001     return opt.compress_algo;
1002   else if(opt.personal_compress_prefs)
1003     return opt.personal_compress_prefs[0].value;
1004   else
1005     return DEFAULT_COMPRESS_ALGO;
1006 }
1007
1008 const char *
1009 compliance_option_string(void)
1010 {
1011   char *ver="???";
1012
1013   switch(opt.compliance)
1014     {
1015     case CO_GNUPG:   return "--gnupg";
1016     case CO_RFC4880: return "--openpgp";
1017     case CO_RFC2440: return "--rfc2440";
1018     case CO_RFC1991: return "--rfc1991";
1019     case CO_PGP2:    return "--pgp2";
1020     case CO_PGP6:    return "--pgp6";
1021     case CO_PGP7:    return "--pgp7";
1022     case CO_PGP8:    return "--pgp8";
1023     }
1024
1025   return ver;
1026 }
1027
1028 void
1029 compliance_failure(void)
1030 {
1031   char *ver="???";
1032
1033   switch(opt.compliance)
1034     {
1035     case CO_GNUPG:
1036       ver="GnuPG";
1037       break;
1038
1039     case CO_RFC4880:
1040       ver="OpenPGP";
1041       break;
1042
1043     case CO_RFC2440:
1044       ver="OpenPGP (older)";
1045       break;
1046
1047     case CO_RFC1991:
1048       ver="old PGP";
1049       break;
1050
1051     case CO_PGP2:
1052       ver="PGP 2.x";
1053       break;
1054
1055     case CO_PGP6:
1056       ver="PGP 6.x";
1057       break;
1058
1059     case CO_PGP7:
1060       ver="PGP 7.x";
1061       break;
1062
1063     case CO_PGP8:
1064       ver="PGP 8.x";
1065       break;
1066     }
1067
1068   log_info(_("this message may not be usable by %s\n"),ver);
1069   opt.compliance=CO_GNUPG;
1070 }
1071
1072 /* Break a string into successive option pieces.  Accepts single word
1073    options and key=value argument options. */
1074 char *
1075 optsep(char **stringp)
1076 {
1077   char *tok,*end;
1078
1079   tok=*stringp;
1080   if(tok)
1081     {
1082       end=strpbrk(tok," ,=");
1083       if(end)
1084         {
1085           int sawequals=0;
1086           char *ptr=end;
1087
1088           /* what we need to do now is scan along starting with *end,
1089              If the next character we see (ignoring spaces) is an =
1090              sign, then there is an argument. */
1091
1092           while(*ptr)
1093             {
1094               if(*ptr=='=')
1095                 sawequals=1;
1096               else if(*ptr!=' ')
1097                 break;
1098               ptr++;
1099             }
1100
1101           /* There is an argument, so grab that too.  At this point,
1102              ptr points to the first character of the argument. */
1103           if(sawequals)
1104             {
1105               /* Is it a quoted argument? */
1106               if(*ptr=='"')
1107                 {
1108                   ptr++;
1109                   end=strchr(ptr,'"');
1110                   if(end)
1111                     end++;
1112                 }
1113               else
1114                 end=strpbrk(ptr," ,");
1115             }
1116
1117           if(end && *end)
1118             {
1119               *end='\0';
1120               *stringp=end+1;
1121             }
1122           else
1123             *stringp=NULL;
1124         }
1125       else
1126         *stringp=NULL;
1127     }
1128
1129   return tok;
1130 }
1131
1132 /* Breaks an option value into key and value.  Returns NULL if there
1133    is no value.  Note that "string" is modified to remove the =value
1134    part. */
1135 char *
1136 argsplit(char *string)
1137 {
1138   char *equals,*arg=NULL;
1139
1140   equals=strchr(string,'=');
1141   if(equals)
1142     {
1143       char *quote,*space;
1144
1145       *equals='\0';
1146       arg=equals+1;
1147
1148       /* Quoted arg? */
1149       quote=strchr(arg,'"');
1150       if(quote)
1151         {
1152           arg=quote+1;
1153
1154           quote=strchr(arg,'"');
1155           if(quote)
1156             *quote='\0';
1157         }
1158       else
1159         {
1160           size_t spaces;
1161
1162           /* Trim leading spaces off of the arg */
1163           spaces=strspn(arg," ");
1164           arg+=spaces;
1165         }
1166
1167       /* Trim tailing spaces off of the tag */
1168       space=strchr(string,' ');
1169       if(space)
1170         *space='\0';
1171     }
1172
1173   return arg;
1174 }
1175
1176 /* Return the length of the initial token, leaving off any
1177    argument. */
1178 static size_t
1179 optlen(const char *s)
1180 {
1181   char *end=strpbrk(s," =");
1182
1183   if(end)
1184     return end-s;
1185   else
1186     return strlen(s);
1187 }
1188
1189 int
1190 parse_options(char *str,unsigned int *options,
1191               struct parse_options *opts,int noisy)
1192 {
1193   char *tok;
1194
1195   if (str && !strcmp (str, "help"))
1196     {
1197       int i,maxlen=0;
1198
1199       /* Figure out the longest option name so we can line these up
1200          neatly. */
1201       for(i=0;opts[i].name;i++)
1202         if(opts[i].help && maxlen<strlen(opts[i].name))
1203           maxlen=strlen(opts[i].name);
1204
1205       for(i=0;opts[i].name;i++)
1206         if(opts[i].help)
1207           printf("%s%*s%s\n",opts[i].name,
1208                  maxlen+2-(int)strlen(opts[i].name),"",_(opts[i].help));
1209
1210       g10_exit(0);
1211     }
1212
1213   while((tok=optsep(&str)))
1214     {
1215       int i,rev=0;
1216       char *otok=tok;
1217
1218       if(tok[0]=='\0')
1219         continue;
1220
1221       if(ascii_strncasecmp("no-",tok,3)==0)
1222         {
1223           rev=1;
1224           tok+=3;
1225         }
1226
1227       for(i=0;opts[i].name;i++)
1228         {
1229           size_t toklen=optlen(tok);
1230
1231           if(ascii_strncasecmp(opts[i].name,tok,toklen)==0)
1232             {
1233               /* We have a match, but it might be incomplete */
1234               if(toklen!=strlen(opts[i].name))
1235                 {
1236                   int j;
1237
1238                   for(j=i+1;opts[j].name;j++)
1239                     {
1240                       if(ascii_strncasecmp(opts[j].name,tok,toklen)==0)
1241                         {
1242                           if(noisy)
1243                             log_info(_("ambiguous option `%s'\n"),otok);
1244                           return 0;
1245                         }
1246                     }
1247                 }
1248
1249               if(rev)
1250                 {
1251                   *options&=~opts[i].bit;
1252                   if(opts[i].value)
1253                     *opts[i].value=NULL;
1254                 }
1255               else
1256                 {
1257                   *options|=opts[i].bit;
1258                   if(opts[i].value)
1259                     *opts[i].value=argsplit(tok);
1260                 }
1261               break;
1262             }
1263         }
1264
1265       if(!opts[i].name)
1266         {
1267           if(noisy)
1268             log_info(_("unknown option `%s'\n"),otok);
1269           return 0;
1270         }
1271     }
1272
1273   return 1;
1274 }
1275
1276
1277 /* Check whether the string has characters not valid in an RFC-822
1278    address.  To cope with OpenPGP we ignore non-ascii characters
1279    so that for example umlauts are legal in an email address.  An
1280    OpenPGP user ID must be utf-8 encoded but there is no strict
1281    requirement for RFC-822.  Thus to avoid IDNA encoding we put the
1282    address verbatim as utf-8 into the user ID under the assumption
1283    that mail programs handle IDNA at a lower level and take OpenPGP
1284    user IDs as utf-8.  Note that we can't do an utf-8 encoding
1285    checking here because in keygen.c this function is called with the
1286    native encoding and native to utf-8 encoding is only done  later.  */
1287 int
1288 has_invalid_email_chars (const char *s)
1289 {
1290   int at_seen=0;
1291   const char *valid_chars=
1292     "01234567890_-.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
1293
1294   for ( ; *s; s++ ) 
1295     {
1296       if ( (*s & 0x80) )
1297         continue; /* We only care about ASCII.  */
1298       if ( *s == '@' )
1299         at_seen=1;
1300       else if ( !at_seen && !( !!strchr( valid_chars, *s ) || *s == '+' ) )
1301         return 1;
1302       else if ( at_seen && !strchr( valid_chars, *s ) )
1303         return 1;
1304     }
1305   return 0;
1306 }
1307
1308
1309 /* Check whether NAME represents a valid mailbox according to
1310    RFC822. Returns true if so. */
1311 int
1312 is_valid_mailbox (const char *name)
1313 {
1314   return !( !name
1315             || !*name
1316             || has_invalid_email_chars (name)
1317             || string_count_chr (name,'@') != 1
1318             || *name == '@'
1319             || name[strlen(name)-1] == '@'
1320             || name[strlen(name)-1] == '.'
1321             || strstr (name, "..") );
1322 }
1323
1324
1325 /* Similar to access(2), but uses PATH to find the file. */
1326 int
1327 path_access(const char *file,int mode)
1328 {
1329   char *envpath;
1330   int ret=-1;
1331
1332   envpath=getenv("PATH");
1333
1334   if(!envpath
1335 #ifdef HAVE_DRIVE_LETTERS
1336      || (((file[0]>='A' && file[0]<='Z')
1337           || (file[0]>='a' && file[0]<='z'))
1338          && file[1]==':')
1339 #else
1340      || file[0]=='/'
1341 #endif
1342      )
1343     return access(file,mode);
1344   else
1345     {
1346       /* At least as large as, but most often larger than we need. */
1347       char *buffer=xmalloc(strlen(envpath)+1+strlen(file)+1);
1348       char *split,*item,*path=xstrdup(envpath);
1349
1350       split=path;
1351
1352       while((item=strsep(&split,PATHSEP_S)))
1353         {
1354           strcpy(buffer,item);
1355           strcat(buffer,"/");
1356           strcat(buffer,file);
1357           ret=access(buffer,mode);
1358           if(ret==0)
1359             break;
1360         }
1361
1362       xfree(path);
1363       xfree(buffer);
1364     }
1365
1366   return ret;
1367 }
1368
1369
1370 \f
1371 /* Temporary helper. */
1372 int
1373 pubkey_get_npkey( int algo )
1374 {
1375   size_t n;
1376
1377   if (algo == GCRY_PK_ELG_E)
1378     algo = GCRY_PK_ELG;
1379   else if (algo == PUBKEY_ALGO_ECDSA)
1380     algo = GCRY_PK_ECDSA;
1381   else if (algo == PUBKEY_ALGO_ECDH)
1382     algo = GCRY_PK_ECDH;
1383   if (gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NPKEY, NULL, &n))
1384     n = 0;
1385   return n;
1386 }
1387
1388 /* Temporary helper. */
1389 int
1390 pubkey_get_nskey( int algo )
1391 {
1392   size_t n;
1393
1394   if (algo == GCRY_PK_ELG_E)
1395     algo = GCRY_PK_ELG;
1396   else if (algo == PUBKEY_ALGO_ECDSA)
1397     algo = GCRY_PK_ECDSA;
1398   else if (algo == PUBKEY_ALGO_ECDH)
1399     algo = GCRY_PK_ECDH;
1400   if (gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NSKEY, NULL, &n ))
1401     n = 0;
1402   return n;
1403 }
1404
1405 /* Temporary helper. */
1406 int
1407 pubkey_get_nsig( int algo )
1408 {
1409   size_t n;
1410
1411   if (algo == GCRY_PK_ELG_E)
1412     algo = GCRY_PK_ELG;
1413   else if (algo == PUBKEY_ALGO_ECDSA)
1414     algo = GCRY_PK_ECDSA;
1415   else if (algo == PUBKEY_ALGO_ECDH)
1416     algo = GCRY_PK_ECDH;
1417   if (gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NSIGN, NULL, &n))
1418     n = 0;
1419   return n;
1420 }
1421
1422 /* Temporary helper. */
1423 int
1424 pubkey_get_nenc( int algo )
1425 {
1426   size_t n;
1427   
1428   if (algo == GCRY_PK_ELG_E)
1429     algo = GCRY_PK_ELG;
1430   else if (algo == PUBKEY_ALGO_ECDSA)
1431     algo = GCRY_PK_ECDSA;
1432   else if (algo == PUBKEY_ALGO_ECDH)
1433     algo = GCRY_PK_ECDH;
1434   if (gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NENCR, NULL, &n ))
1435     n = 0;
1436   return n;
1437 }
1438
1439
1440 /* Temporary helper. */
1441 unsigned int
1442 pubkey_nbits( int algo, gcry_mpi_t *key )
1443 {
1444     int rc, nbits;
1445     gcry_sexp_t sexp;
1446
1447     assert( algo != GCRY_PK_ECDSA && algo != GCRY_PK_ECDH );
1448
1449     if( algo == GCRY_PK_DSA ) {
1450         rc = gcry_sexp_build ( &sexp, NULL,
1451                               "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))",
1452                                   key[0], key[1], key[2], key[3] );
1453     }
1454     else if( algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E ) {
1455         rc = gcry_sexp_build ( &sexp, NULL,
1456                               "(public-key(elg(p%m)(g%m)(y%m)))",
1457                                   key[0], key[1], key[2] );
1458     }
1459     else if( algo == GCRY_PK_RSA ) {
1460         rc = gcry_sexp_build ( &sexp, NULL,
1461                               "(public-key(rsa(n%m)(e%m)))",
1462                                   key[0], key[1] );
1463     }
1464     else if( algo == PUBKEY_ALGO_ECDSA || algo == PUBKEY_ALGO_ECDH ) {
1465         rc = gcry_sexp_build ( &sexp, NULL,
1466                               "(public-key(ecc(c%m)(q%m)))",
1467                                   key[0], key[1] /* not affecting the size calculation, so use 'ecc' == 'ecdsa' */ );
1468     }
1469     else
1470         return 0;
1471
1472     if ( rc )
1473         BUG ();
1474
1475     nbits = gcry_pk_get_nbits( sexp );
1476     gcry_sexp_release( sexp );
1477     return nbits;
1478 }
1479
1480
1481
1482 /* FIXME: Use gcry_mpi_print directly. */
1483 int
1484 mpi_print (estream_t fp, gcry_mpi_t a, int mode)
1485 {
1486   int n=0;
1487   
1488   if (!a)
1489     return es_fprintf (fp, "[MPI_NULL]");
1490   if (!mode)
1491     {
1492       unsigned int n1;
1493       n1 = gcry_mpi_get_nbits(a);
1494       n += es_fprintf (fp, "[%u bits]", n1);
1495     }
1496   else
1497     {
1498       unsigned char *buffer;
1499       
1500       if (gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buffer, NULL, a))
1501         BUG ();
1502       es_fputs (buffer, fp);
1503       n += strlen (buffer);
1504       gcry_free (buffer);
1505     }
1506   return n;
1507 }
1508
1509 /*
1510  * Write a special size+body mpi a, to OUT. The format of the content of the MPI is
1511  * one byte LEN, following by LEN bytes 
1512  */
1513 int
1514 iobuf_write_size_body_mpi (iobuf_t out, gcry_mpi_t a)
1515 {
1516   byte buffer[256]; /* Fixed buffer for a public parameter, max possible */
1517   size_t nbytes = (mpi_get_nbits (a)+7)/8;
1518   int rc;
1519
1520   if( nbytes > sizeof(buffer) )  {
1521       log_error("mpi with size+body is too large (%u bytes)\n", nbytes);
1522       return gpg_error (GPG_ERR_TOO_LARGE);
1523   }
1524   
1525   rc = gcry_mpi_print (GCRYMPI_FMT_USG, buffer, sizeof(buffer), &nbytes, a);
1526   if( rc )  {
1527     log_error("Failed to exported size+body mpi\n");
1528     return rc;
1529   }
1530   if( nbytes < 2 || buffer[0] != nbytes-1 )  {
1531     if( nbytes > 2 )
1532       log_error("Internal size mismatch in mpi size+body: %02x != %02x (other bytes: %02x %02x ... %02x %02x)\n", 
1533         buffer[0], nbytes-1, buffer[1], buffer[2], buffer[nbytes-2], buffer[nbytes-1]);
1534     else 
1535       log_error("Internal size mismatch in mpi size+body: only %d bytes\n", nbytes );
1536     return gpg_error (GPG_ERR_INV_DATA);
1537   }
1538   return iobuf_write( out, buffer, nbytes );
1539 }
1540
1541 /*
1542  * Read a special size+body from inp into body[body_max_size] and return it in a buffer and as MPI.
1543  * On success the number of consumed bytes will body[0]+1. 
1544  * The format of the content of the returned MPI is one byte LEN, following by LEN bytes.
1545  * Caller is expected to pre-allocate fixed-size 255 byte buffer (or smaller when appropriate).
1546  */
1547 int
1548 iobuf_read_size_body( iobuf_t inp, byte *body, int body_max_size, int pktlen, gcry_mpi_t *out )  {
1549   unsigned n;
1550   int rc;
1551   gcry_mpi_t result;
1552
1553   *out = NULL;
1554
1555   if( (n = iobuf_readbyte(inp)) == -1 ) {
1556     return G10ERR_INVALID_PACKET;
1557   }
1558   if( n >= body_max_size || n < 2)  {
1559     log_error("invalid size+body field\n");
1560     return G10ERR_INVALID_PACKET;
1561   }
1562   body[0] = n;  
1563   if( (n = iobuf_read(inp, body+1, n)) == -1 ) {
1564     log_error("invalid size+body field\n");
1565     return G10ERR_INVALID_PACKET;
1566   }
1567   if( n+1 > pktlen )  {
1568     log_error("size+body field is larger than the packet\n");
1569     return G10ERR_INVALID_PACKET;
1570   }
1571   rc = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, body, n+1, NULL);
1572   if (rc)
1573     log_fatal ("mpi_scan failed: %s\n", gpg_strerror (rc));
1574
1575   *out = result;
1576
1577   return rc;
1578 }
1579
1580
1581 /* pkey[1] or skey[1] is Q for ECDSA, which is an uncompressed point, i.e.  04 <x> <y> */
1582 int ecdsa_qbits_from_Q( int qbits )  {
1583         if( qbits%8>3 )  {
1584                 log_error(_("ECDSA public key is expected to be in SEC encoding multiple of 8 bits\n"));
1585                 return 0;
1586         }
1587         qbits -= qbits%8;
1588         qbits /= 2;
1589         return qbits;
1590 }
1591
1592
1593
1594