gpg: More robustly detect valid non-armored OpenPGP messages.
[gnupg.git] / g10 / armor.c
1 /* armor.c - Armor flter
2  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
3  *               2007 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 <errno.h>
26 #include <assert.h>
27 #include <ctype.h>
28
29 #include "gpg.h"
30 #include "status.h"
31 #include "iobuf.h"
32 #include "util.h"
33 #include "filter.h"
34 #include "packet.h"
35 #include "options.h"
36 #include "main.h"
37 #include "status.h"
38 #include "i18n.h"
39
40 #define MAX_LINELEN 20000
41
42 #define CRCINIT 0xB704CE
43 #define CRCPOLY 0X864CFB
44 #define CRCUPDATE(a,c) do {                                                 \
45                         a = ((a) << 8) ^ crc_table[((a)&0xff >> 16) ^ (c)]; \
46                         a &= 0x00ffffff;                                    \
47                     } while(0)
48 static u32 crc_table[256];
49 static byte bintoasc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
50                          "abcdefghijklmnopqrstuvwxyz"
51                          "0123456789+/";
52 static byte asctobin[256]; /* runtime initialized */
53 static int is_initialized;
54
55
56 typedef enum {
57     fhdrHASArmor = 0,
58     fhdrNOArmor,
59     fhdrINIT,
60     fhdrINITCont,
61     fhdrINITSkip,
62     fhdrCHECKBegin,
63     fhdrWAITHeader,
64     fhdrWAITClearsig,
65     fhdrSKIPHeader,
66     fhdrCLEARSIG,
67     fhdrREADClearsig,
68     fhdrNullClearsig,
69     fhdrEMPTYClearsig,
70     fhdrCHECKClearsig,
71     fhdrCHECKClearsig2,
72     fhdrCHECKDashEscaped,
73     fhdrCHECKDashEscaped2,
74     fhdrCHECKDashEscaped3,
75     fhdrREADClearsigNext,
76     fhdrENDClearsig,
77     fhdrENDClearsigHelp,
78     fhdrTESTSpaces,
79     fhdrCLEARSIGSimple,
80     fhdrCLEARSIGSimpleNext,
81     fhdrTEXT,
82     fhdrTEXTSimple,
83     fhdrERROR,
84     fhdrERRORShow,
85     fhdrEOF
86 } fhdr_state_t;
87
88
89 /* if we encounter this armor string with this index, go
90  * into a mode which fakes packets and wait for the next armor */
91 #define BEGIN_SIGNATURE 2
92 #define BEGIN_SIGNED_MSG_IDX 3
93 static char *head_strings[] = {
94     "BEGIN PGP MESSAGE",
95     "BEGIN PGP PUBLIC KEY BLOCK",
96     "BEGIN PGP SIGNATURE",
97     "BEGIN PGP SIGNED MESSAGE",
98     "BEGIN PGP ARMORED FILE",       /* gnupg extension */
99     "BEGIN PGP PRIVATE KEY BLOCK",
100     "BEGIN PGP SECRET KEY BLOCK",   /* only used by pgp2 */
101     NULL
102 };
103 static char *tail_strings[] = {
104     "END PGP MESSAGE",
105     "END PGP PUBLIC KEY BLOCK",
106     "END PGP SIGNATURE",
107     "END dummy",
108     "END PGP ARMORED FILE",
109     "END PGP PRIVATE KEY BLOCK",
110     "END PGP SECRET KEY BLOCK",
111     NULL
112 };
113
114
115 static int armor_filter ( void *opaque, int control,
116                           iobuf_t chain, byte *buf, size_t *ret_len);
117
118
119
120 \f
121 /* Create a new context for armor filters.  */
122 armor_filter_context_t *
123 new_armor_context (void)
124 {
125   armor_filter_context_t *afx;
126
127   afx = xcalloc (1, sizeof *afx);
128   afx->refcount = 1;
129
130   return afx;
131 }
132
133 /* Release an armor filter context.  Passing NULL is explicitly
134    allowed and a no-op.  */
135 void
136 release_armor_context (armor_filter_context_t *afx)
137 {
138   if (!afx)
139     return;
140   assert (afx->refcount);
141   if ( --afx->refcount )
142     return;
143   xfree (afx);
144 }
145
146 /* Push the armor filter onto the iobuf stream IOBUF.  */
147 int
148 push_armor_filter (armor_filter_context_t *afx, iobuf_t iobuf)
149 {
150   int rc;
151
152   afx->refcount++;
153   rc = iobuf_push_filter (iobuf, armor_filter, afx);
154   if (rc)
155     afx->refcount--;
156   return rc;
157 }
158
159
160
161
162
163 static void
164 initialize(void)
165 {
166     int i, j;
167     u32 t;
168     byte *s;
169
170     /* init the crc lookup table */
171     crc_table[0] = 0;
172     for(i=j=0; j < 128; j++ ) {
173         t = crc_table[j];
174         if( t & 0x00800000 ) {
175             t <<= 1;
176             crc_table[i++] = t ^ CRCPOLY;
177             crc_table[i++] = t;
178         }
179         else {
180             t <<= 1;
181             crc_table[i++] = t;
182             crc_table[i++] = t ^ CRCPOLY;
183         }
184     }
185     /* build the helptable for radix64 to bin conversion */
186     for(i=0; i < 256; i++ )
187         asctobin[i] = 255; /* used to detect invalid characters */
188     for(s=bintoasc,i=0; *s; s++,i++ )
189         asctobin[*s] = i;
190
191     is_initialized=1;
192 }
193
194 /****************
195  * Check whether this is an armored file or not See also
196  * parse-packet.c for details on this code.
197  * Returns: True if it seems to be armored
198  */
199 static int
200 is_armored( const byte *buf )
201 {
202   int ctb, pkttype;
203   int indeterminate_length_allowed;
204
205     ctb = *buf;
206     if( !(ctb & 0x80) )
207       /* The most significant bit of the CTB must be set.  Since it is
208          cleared, this is not a binary OpenPGP message.  Assume it is
209          armored.  */
210       return 1;
211
212     pkttype =  ctb & 0x40 ? (ctb & 0x3f) : ((ctb>>2)&0xf);
213     switch( pkttype ) {
214       case PKT_PUBKEY_ENC:
215       case PKT_SIGNATURE:
216       case PKT_SYMKEY_ENC:
217       case PKT_ONEPASS_SIG:
218       case PKT_SECRET_KEY:
219       case PKT_PUBLIC_KEY:
220       case PKT_SECRET_SUBKEY:
221       case PKT_MARKER:
222       case PKT_RING_TRUST:
223       case PKT_USER_ID:
224       case PKT_PUBLIC_SUBKEY:
225       case PKT_ATTRIBUTE:
226       case PKT_MDC:
227         indeterminate_length_allowed = 0;
228         break;
229
230       case PKT_COMPRESSED:
231       case PKT_ENCRYPTED:
232       case PKT_ENCRYPTED_MDC:
233       case PKT_PLAINTEXT:
234       case PKT_OLD_COMMENT:
235       case PKT_COMMENT:
236       case PKT_GPG_CONTROL:
237         indeterminate_length_allowed = 1;
238         break;
239
240       default:
241         /* Invalid packet type.  */
242         return 1;
243     }
244
245     if (! indeterminate_length_allowed)
246       /* It is only legal to use an indeterminate length with a few
247          packet types.  If a packet uses an indeterminate length, but
248          that is not allowed, then the data is not valid binary
249          OpenPGP data.  */
250       {
251         int new_format;
252         int indeterminate_length;
253
254         new_format = !! (ctb & (1 << 6));
255         if (new_format)
256           indeterminate_length = (buf[1] >= 224 && buf[1] < 255);
257         else
258           indeterminate_length = (ctb & 3) == 3;
259
260         if (indeterminate_length)
261           return 1;
262       }
263
264     /* The first CTB seems legit.  It is probably not armored
265        data.  */
266     return 0;
267 }
268
269
270 /****************
271  * Try to check whether the iobuf is armored
272  * Returns true if this may be the case; the caller should use the
273  *         filter to do further processing.
274  */
275 int
276 use_armor_filter( IOBUF a )
277 {
278     byte buf[1];
279     int n;
280
281     /* fixme: there might be a problem with iobuf_peek */
282     n = iobuf_peek(a, buf, 1 );
283     if( n == -1 )
284         return 0; /* EOF, doesn't matter whether armored or not */
285     if( !n )
286         return 1; /* can't check it: try armored */
287     return is_armored(buf);
288 }
289
290
291
292
293 static void
294 invalid_armor(void)
295 {
296     write_status(STATUS_BADARMOR);
297     g10_exit(1); /* stop here */
298 }
299
300
301 /****************
302  * check whether the armor header is valid on a signed message.
303  * this is for security reasons: the header lines are not included in the
304  * hash and by using some creative formatting rules, Mallory could fake
305  * any text at the beginning of a document; assuming it is read with
306  * a simple viewer. We only allow the Hash Header.
307  */
308 static int
309 parse_hash_header( const char *line )
310 {
311     const char *s, *s2;
312     unsigned found = 0;
313
314     if( strlen(line) < 6  || strlen(line) > 60 )
315         return 0; /* too short or too long */
316     if( memcmp( line, "Hash:", 5 ) )
317         return 0; /* invalid header */
318
319     for(s=line+5;;s=s2) {
320         for(; *s && (*s==' ' || *s == '\t'); s++ )
321             ;
322         if( !*s )
323             break;
324         for(s2=s+1; *s2 && *s2!=' ' && *s2 != '\t' && *s2 != ','; s2++ )
325             ;
326         if( !strncmp( s, "RIPEMD160", s2-s ) )
327             found |= 1;
328         else if( !strncmp( s, "SHA1", s2-s ) )
329             found |= 2;
330         else if( !strncmp( s, "SHA224", s2-s ) )
331             found |= 8;
332         else if( !strncmp( s, "SHA256", s2-s ) )
333             found |= 16;
334         else if( !strncmp( s, "SHA384", s2-s ) )
335             found |= 32;
336         else if( !strncmp( s, "SHA512", s2-s ) )
337             found |= 64;
338         else
339             return 0;
340         for(; *s2 && (*s2==' ' || *s2 == '\t'); s2++ )
341             ;
342         if( *s2 && *s2 != ',' )
343             return 0;
344         if( *s2 )
345             s2++;
346     }
347     return found;
348 }
349
350 /* Returns true if this is a valid armor tag as per RFC-2440bis-21. */
351 static int
352 is_armor_tag(const char *line)
353 {
354   if(strncmp(line,"Version",7)==0
355      || strncmp(line,"Comment",7)==0
356      || strncmp(line,"MessageID",9)==0
357      || strncmp(line,"Hash",4)==0
358      || strncmp(line,"Charset",7)==0)
359     return 1;
360
361   return 0;
362 }
363
364 /****************
365  * Check whether this is a armor line.
366  * returns: -1 if it is not a armor header or the index number of the
367  * armor header.
368  */
369 static int
370 is_armor_header( byte *line, unsigned len )
371 {
372     const char *s;
373     byte *save_p, *p;
374     int save_c;
375     int i;
376
377     if( len < 15 )
378         return -1; /* too short */
379     if( memcmp( line, "-----", 5 ) )
380         return -1; /* no */
381     p = strstr( line+5, "-----");
382     if( !p )
383         return -1;
384     save_p = p;
385     p += 5;
386
387     /* Some Windows environments seem to add whitespace to the end of
388        the line, so we strip it here.  This becomes strict if
389        --rfc2440 is set since 2440 reads "The header lines, therefore,
390        MUST start at the beginning of a line, and MUST NOT have text
391        following them on the same line."  It is unclear whether "text"
392        refers to all text or just non-whitespace text.  4880 clarified
393        this was only non-whitespace text. */
394
395     if(RFC2440)
396       {
397         if( *p == '\r' )
398           p++;
399         if( *p == '\n' )
400           p++;
401       }
402     else
403       while(*p==' ' || *p=='\r' || *p=='\n' || *p=='\t')
404         p++;
405
406     if( *p )
407         return -1; /* garbage after dashes */
408     save_c = *save_p; *save_p = 0;
409     p = line+5;
410     for(i=0; (s=head_strings[i]); i++ )
411         if( !strcmp(s, p) )
412             break;
413     *save_p = save_c;
414     if( !s )
415         return -1; /* unknown armor line */
416
417     if( opt.verbose > 1 )
418         log_info(_("armor: %s\n"), head_strings[i]);
419     return i;
420 }
421
422
423
424 /****************
425  * Parse a header lines
426  * Return 0: Empty line (end of header lines)
427  *       -1: invalid header line
428  *       >0: Good header line
429  */
430 static int
431 parse_header_line( armor_filter_context_t *afx, byte *line, unsigned int len )
432 {
433     byte *p;
434     int hashes=0;
435     unsigned int len2;
436
437     len2 = length_sans_trailing_ws ( line, len );
438     if( !len2 ) {
439         afx->buffer_pos = len2;  /* (it is not the fine way to do it here) */
440         return 0; /* WS only: same as empty line */
441     }
442
443     /*
444       This is fussy.  The spec says that a header line is delimited
445       with a colon-space pair.  This means that a line such as
446       "Comment: " (with nothing else) is actually legal as an empty
447       string comment.  However, email and cut-and-paste being what it
448       is, that trailing space may go away.  Therefore, we accept empty
449       headers delimited with only a colon.  --rfc2440, as always,
450       makes this strict and enforces the colon-space pair. -dms
451     */
452
453     p = strchr( line, ':');
454     if( !p || (RFC2440 && p[1]!=' ')
455         || (!RFC2440 && p[1]!=' ' && p[1]!='\n' && p[1]!='\r'))
456       {
457         log_error (_("invalid armor header: "));
458         es_write_sanitized (log_get_stream (), line, len, NULL, NULL);
459         log_printf ("\n");
460         return -1;
461       }
462
463     /* Chop off the whitespace we detected before */
464     len=len2;
465     line[len2]='\0';
466
467     if( opt.verbose ) {
468         log_info(_("armor header: "));
469         es_write_sanitized (log_get_stream (), line, len, NULL, NULL);
470         log_printf ("\n");
471     }
472
473     if( afx->in_cleartext )
474       {
475         if( (hashes=parse_hash_header( line )) )
476           afx->hashes |= hashes;
477         else if( strlen(line) > 15 && !memcmp( line, "NotDashEscaped:", 15 ) )
478           afx->not_dash_escaped = 1;
479         else
480           {
481             log_error(_("invalid clearsig header\n"));
482             return -1;
483           }
484       }
485     else if(!is_armor_tag(line))
486       {
487         /* Section 6.2: "Unknown keys should be reported to the user,
488            but OpenPGP should continue to process the message."  Note
489            that in a clearsigned message this applies to the signature
490            part (i.e. "BEGIN PGP SIGNATURE") and not the signed data
491            ("BEGIN PGP SIGNED MESSAGE").  The only key allowed in the
492            signed data section is "Hash". */
493
494         log_info(_("unknown armor header: "));
495         es_write_sanitized (log_get_stream (), line, len, NULL, NULL);
496         log_printf ("\n");
497       }
498
499     return 1;
500 }
501
502
503
504 /* figure out whether the data is armored or not */
505 static int
506 check_input( armor_filter_context_t *afx, IOBUF a )
507 {
508     int rc = 0;
509     int i;
510     byte *line;
511     unsigned len;
512     unsigned maxlen;
513     int hdr_line = -1;
514
515     /* read the first line to see whether this is armored data */
516     maxlen = MAX_LINELEN;
517     len = afx->buffer_len = iobuf_read_line( a, &afx->buffer,
518                                              &afx->buffer_size, &maxlen );
519     line = afx->buffer;
520     if( !maxlen ) {
521         /* line has been truncated: assume not armored */
522         afx->inp_checked = 1;
523         afx->inp_bypass = 1;
524         return 0;
525     }
526
527     if( !len ) {
528         return -1; /* eof */
529     }
530
531     /* (the line is always a C string but maybe longer) */
532     if( *line == '\n' || ( len && (*line == '\r' && line[1]=='\n') ) )
533         ;
534     else if( !is_armored( line ) ) {
535         afx->inp_checked = 1;
536         afx->inp_bypass = 1;
537         return 0;
538     }
539
540     /* find the armor header */
541     while(len) {
542         i = is_armor_header( line, len );
543         if( i >= 0 && !(afx->only_keyblocks && i != 1 && i != 5 && i != 6 )) {
544             hdr_line = i;
545             if( hdr_line == BEGIN_SIGNED_MSG_IDX ) {
546                 if( afx->in_cleartext ) {
547                     log_error(_("nested clear text signatures\n"));
548                     rc = gpg_error (GPG_ERR_INV_ARMOR);
549                 }
550                 afx->in_cleartext = 1;
551             }
552             break;
553         }
554         /* read the next line (skip all truncated lines) */
555         do {
556             maxlen = MAX_LINELEN;
557             afx->buffer_len = iobuf_read_line( a, &afx->buffer,
558                                                &afx->buffer_size, &maxlen );
559             line = afx->buffer;
560             len = afx->buffer_len;
561         } while( !maxlen );
562     }
563
564     /* Parse the header lines.  */
565     while(len) {
566         /* Read the next line (skip all truncated lines). */
567         do {
568             maxlen = MAX_LINELEN;
569             afx->buffer_len = iobuf_read_line( a, &afx->buffer,
570                                                &afx->buffer_size, &maxlen );
571             line = afx->buffer;
572             len = afx->buffer_len;
573         } while( !maxlen );
574
575         i = parse_header_line( afx, line, len );
576         if( i <= 0 ) {
577             if (i && RFC2440)
578                 rc = GPG_ERR_INV_ARMOR;
579             break;
580         }
581     }
582
583
584     if( rc )
585         invalid_armor();
586     else if( afx->in_cleartext )
587         afx->faked = 1;
588     else {
589         afx->inp_checked = 1;
590         afx->crc = CRCINIT;
591         afx->idx = 0;
592         afx->radbuf[0] = 0;
593     }
594
595     return rc;
596 }
597
598 #define PARTIAL_CHUNK 512
599 #define PARTIAL_POW   9
600
601 /****************
602  * Fake a literal data packet and wait for the next armor line
603  * fixme: empty line handling and null length clear text signature are
604  *        not implemented/checked.
605  */
606 static int
607 fake_packet( armor_filter_context_t *afx, IOBUF a,
608              size_t *retn, byte *buf, size_t size  )
609 {
610     int rc = 0;
611     size_t len = 0;
612     int lastline = 0;
613     unsigned maxlen, n;
614     byte *p;
615     byte tempbuf[PARTIAL_CHUNK];
616     size_t tempbuf_len=0;
617
618     while( !rc && size-len>=(PARTIAL_CHUNK+1)) {
619         /* copy what we have in the line buffer */
620         if( afx->faked == 1 )
621             afx->faked++; /* skip the first (empty) line */
622         else
623           {
624             /* It's full, so write this partial chunk */
625             if(tempbuf_len==PARTIAL_CHUNK)
626               {
627                 buf[len++]=0xE0+PARTIAL_POW;
628                 memcpy(&buf[len],tempbuf,PARTIAL_CHUNK);
629                 len+=PARTIAL_CHUNK;
630                 tempbuf_len=0;
631                 continue;
632               }
633
634             while( tempbuf_len < PARTIAL_CHUNK
635                    && afx->buffer_pos < afx->buffer_len )
636               tempbuf[tempbuf_len++] = afx->buffer[afx->buffer_pos++];
637             if( tempbuf_len==PARTIAL_CHUNK )
638               continue;
639           }
640
641         /* read the next line */
642         maxlen = MAX_LINELEN;
643         afx->buffer_pos = 0;
644         afx->buffer_len = iobuf_read_line( a, &afx->buffer,
645                                            &afx->buffer_size, &maxlen );
646         if( !afx->buffer_len ) {
647             rc = -1; /* eof (should not happen) */
648             continue;
649         }
650         if( !maxlen )
651             afx->truncated++;
652
653         p = afx->buffer;
654         n = afx->buffer_len;
655
656         /* Armor header or dash-escaped line? */
657         if(p[0]=='-')
658           {
659             /* 2440bis-10: When reversing dash-escaping, an
660                implementation MUST strip the string "- " if it occurs
661                at the beginning of a line, and SHOULD warn on "-" and
662                any character other than a space at the beginning of a
663                line.  */
664
665             if(p[1]==' ' && !afx->not_dash_escaped)
666               {
667                 /* It's a dash-escaped line, so skip over the
668                    escape. */
669                 afx->buffer_pos = 2;
670               }
671             else if(p[1]=='-' && p[2]=='-' && p[3]=='-' && p[4]=='-')
672               {
673                 /* Five dashes in a row mean it's probably armor
674                    header. */
675                 int type = is_armor_header( p, n );
676                 if( afx->not_dash_escaped && type != BEGIN_SIGNATURE )
677                   ; /* this is okay */
678                 else
679                   {
680                     if( type != BEGIN_SIGNATURE )
681                       {
682                         log_info(_("unexpected armor: "));
683                         es_write_sanitized (log_get_stream (), p, n,
684                                             NULL, NULL);
685                         log_printf ("\n");
686                       }
687
688                     lastline = 1;
689                     rc = -1;
690                   }
691               }
692             else if(!afx->not_dash_escaped)
693               {
694                 /* Bad dash-escaping. */
695                 log_info (_("invalid dash escaped line: "));
696                 es_write_sanitized (log_get_stream (), p, n, NULL, NULL);
697                 log_printf ("\n");
698               }
699           }
700
701         /* Now handle the end-of-line canonicalization */
702         if( !afx->not_dash_escaped )
703           {
704             int crlf = n > 1 && p[n-2] == '\r' && p[n-1]=='\n';
705
706             afx->buffer_len=
707               trim_trailing_chars( &p[afx->buffer_pos], n-afx->buffer_pos,
708                                    " \t\r\n");
709             afx->buffer_len+=afx->buffer_pos;
710             /* the buffer is always allocated with enough space to append
711              * the removed [CR], LF and a Nul
712              * The reason for this complicated procedure is to keep at least
713              * the original type of lineending - handling of the removed
714              * trailing spaces seems to be impossible in our method
715              * of faking a packet; either we have to use a temporary file
716              * or calculate the hash here in this module and somehow find
717              * a way to send the hash down the processing line (well, a special
718              * faked packet could do the job).
719              */
720             if( crlf )
721               afx->buffer[afx->buffer_len++] = '\r';
722             afx->buffer[afx->buffer_len++] = '\n';
723             afx->buffer[afx->buffer_len] = '\0';
724           }
725     }
726
727     if( lastline ) { /* write last (ending) length header */
728         if(tempbuf_len<192)
729           buf[len++]=tempbuf_len;
730         else
731           {
732             buf[len++]=((tempbuf_len-192)/256) + 192;
733             buf[len++]=(tempbuf_len-192) % 256;
734           }
735         memcpy(&buf[len],tempbuf,tempbuf_len);
736         len+=tempbuf_len;
737
738         rc = 0;
739         afx->faked = 0;
740         afx->in_cleartext = 0;
741         /* and now read the header lines */
742         afx->buffer_pos = 0;
743         for(;;) {
744             int i;
745
746             /* read the next line (skip all truncated lines) */
747             do {
748                 maxlen = MAX_LINELEN;
749                 afx->buffer_len = iobuf_read_line( a, &afx->buffer,
750                                                  &afx->buffer_size, &maxlen );
751             } while( !maxlen );
752             p = afx->buffer;
753             n = afx->buffer_len;
754             if( !n ) {
755                 rc = -1;
756                 break; /* eof */
757             }
758             i = parse_header_line( afx, p , n );
759             if( i <= 0 ) {
760                 if( i )
761                     invalid_armor();
762                 break;
763             }
764         }
765         afx->inp_checked = 1;
766         afx->crc = CRCINIT;
767         afx->idx = 0;
768         afx->radbuf[0] = 0;
769     }
770
771     *retn = len;
772     return rc;
773 }
774
775
776 static int
777 invalid_crc(void)
778 {
779   if ( opt.ignore_crc_error )
780     return 0;
781   log_inc_errorcount();
782   return gpg_error (GPG_ERR_INV_ARMOR);
783 }
784
785
786 static int
787 radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
788               byte *buf, size_t size )
789 {
790     byte val;
791     int c=0, c2; /*init c because gcc is not clever enough for the continue*/
792     int checkcrc=0;
793     int rc = 0;
794     size_t n = 0;
795     int  idx, i, onlypad=0;
796     u32 crc;
797
798     crc = afx->crc;
799     idx = afx->idx;
800     val = afx->radbuf[0];
801     for( n=0; n < size; ) {
802
803         if( afx->buffer_pos < afx->buffer_len )
804             c = afx->buffer[afx->buffer_pos++];
805         else { /* read the next line */
806             unsigned maxlen = MAX_LINELEN;
807             afx->buffer_pos = 0;
808             afx->buffer_len = iobuf_read_line( a, &afx->buffer,
809                                                &afx->buffer_size, &maxlen );
810             if( !maxlen )
811                 afx->truncated++;
812             if( !afx->buffer_len )
813                 break; /* eof */
814             continue;
815         }
816
817       again:
818         if( c == '\n' || c == ' ' || c == '\r' || c == '\t' )
819             continue;
820         else if( c == '=' ) { /* pad character: stop */
821             /* some mailers leave quoted-printable encoded characters
822              * so we try to workaround this */
823             if( afx->buffer_pos+2 < afx->buffer_len ) {
824                 int cc1, cc2, cc3;
825                 cc1 = afx->buffer[afx->buffer_pos];
826                 cc2 = afx->buffer[afx->buffer_pos+1];
827                 cc3 = afx->buffer[afx->buffer_pos+2];
828                 if( isxdigit(cc1) && isxdigit(cc2)
829                                   && strchr( "=\n\r\t ", cc3 )) {
830                     /* well it seems to be the case - adjust */
831                     c = isdigit(cc1)? (cc1 - '0'): (ascii_toupper(cc1)-'A'+10);
832                     c <<= 4;
833                     c |= isdigit(cc2)? (cc2 - '0'): (ascii_toupper(cc2)-'A'+10);
834                     afx->buffer_pos += 2;
835                     afx->qp_detected = 1;
836                     goto again;
837                 }
838             }
839
840             /* Occasionally a bug MTA will leave the = escaped as
841                =3D.  If the 4 characters following that are valid
842                Radix64 characters and they are following by a new
843                line, assume that this is the case and skip the
844                3D.  */
845             if (afx->buffer_pos + 6 < afx->buffer_len
846                 && afx->buffer[afx->buffer_pos + 0] == '3'
847                 && afx->buffer[afx->buffer_pos + 1] == 'D'
848                 && asctobin[afx->buffer[afx->buffer_pos + 2]] != 255
849                 && asctobin[afx->buffer[afx->buffer_pos + 3]] != 255
850                 && asctobin[afx->buffer[afx->buffer_pos + 4]] != 255
851                 && asctobin[afx->buffer[afx->buffer_pos + 5]] != 255
852                 && afx->buffer[afx->buffer_pos + 6] == '\n')
853               {
854                 afx->buffer_pos += 2;
855                 afx->qp_detected = 1;
856               }
857
858             if (!n)
859               onlypad = 1;
860
861             if( idx == 1 )
862                 buf[n++] = val;
863             checkcrc++;
864             break;
865         }
866         else if( (c = asctobin[(c2=c)]) == 255 ) {
867             log_error(_("invalid radix64 character %02X skipped\n"), c2);
868             continue;
869         }
870         switch(idx) {
871           case 0: val =  c << 2; break;
872           case 1: val |= (c>>4)&3; buf[n++]=val;val=(c<<4)&0xf0;break;
873           case 2: val |= (c>>2)&15; buf[n++]=val;val=(c<<6)&0xc0;break;
874           case 3: val |= c&0x3f; buf[n++] = val; break;
875         }
876         idx = (idx+1) % 4;
877     }
878
879     for(i=0; i < n; i++ )
880         crc = (crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ buf[i]];
881     crc &= 0x00ffffff;
882     afx->crc = crc;
883     afx->idx = idx;
884     afx->radbuf[0] = val;
885
886     if( checkcrc ) {
887         afx->any_data = 1;
888         afx->inp_checked=0;
889         afx->faked = 0;
890         for(;;) { /* skip lf and pad characters */
891             if( afx->buffer_pos < afx->buffer_len )
892                 c = afx->buffer[afx->buffer_pos++];
893             else { /* read the next line */
894                 unsigned maxlen = MAX_LINELEN;
895                 afx->buffer_pos = 0;
896                 afx->buffer_len = iobuf_read_line( a, &afx->buffer,
897                                                    &afx->buffer_size, &maxlen );
898                 if( !maxlen )
899                     afx->truncated++;
900                 if( !afx->buffer_len )
901                     break; /* eof */
902                 continue;
903             }
904             if( c == '\n' || c == ' ' || c == '\r'
905                 || c == '\t' || c == '=' )
906                 continue;
907             break;
908         }
909         if( c == -1 )
910             log_error(_("premature eof (no CRC)\n"));
911         else {
912             u32 mycrc = 0;
913             idx = 0;
914             do {
915                 if( (c = asctobin[c]) == 255 )
916                     break;
917                 switch(idx) {
918                   case 0: val =  c << 2; break;
919                   case 1: val |= (c>>4)&3; mycrc |= val << 16;val=(c<<4)&0xf0;break;
920                   case 2: val |= (c>>2)&15; mycrc |= val << 8;val=(c<<6)&0xc0;break;
921                   case 3: val |= c&0x3f; mycrc |= val; break;
922                 }
923                 for(;;) {
924                     if( afx->buffer_pos < afx->buffer_len )
925                         c = afx->buffer[afx->buffer_pos++];
926                     else { /* read the next line */
927                         unsigned maxlen = MAX_LINELEN;
928                         afx->buffer_pos = 0;
929                         afx->buffer_len = iobuf_read_line( a, &afx->buffer,
930                                                            &afx->buffer_size,
931                                                                 &maxlen );
932                         if( !maxlen )
933                             afx->truncated++;
934                         if( !afx->buffer_len )
935                             break; /* eof */
936                         continue;
937                     }
938                     break;
939                 }
940                 if( !afx->buffer_len )
941                     break; /* eof */
942             } while( ++idx < 4 );
943             if( c == -1 ) {
944                 log_info(_("premature eof (in CRC)\n"));
945                 rc = invalid_crc();
946             }
947             else if( idx == 0 ) {
948                 /* No CRC at all is legal ("MAY") */
949                 rc=0;
950             }
951             else if( idx != 4 ) {
952                 log_info(_("malformed CRC\n"));
953                 rc = invalid_crc();
954             }
955             else if( mycrc != afx->crc ) {
956                 log_info (_("CRC error; %06lX - %06lX\n"),
957                                     (ulong)afx->crc, (ulong)mycrc);
958                 rc = invalid_crc();
959             }
960             else {
961                 rc = 0;
962                 /* FIXME: Here we should emit another control packet,
963                  * so that we know in mainproc that we are processing
964                  * a clearsign message */
965 #if 0
966                 for(rc=0;!rc;) {
967                     rc = 0 /*check_trailer( &fhdr, c )*/;
968                     if( !rc ) {
969                         if( (c=iobuf_get(a)) == -1 )
970                             rc = 2;
971                     }
972                 }
973                 if( rc == -1 )
974                     rc = 0;
975                 else if( rc == 2 ) {
976                     log_error(_("premature eof (in trailer)\n"));
977                     rc = GPG_ERR_INVALID_ARMOR;
978                 }
979                 else {
980                     log_error(_("error in trailer line\n"));
981                     rc = GPG_ERR_INVALID_ARMOR;
982                 }
983 #endif
984             }
985         }
986     }
987
988     if( !n && !onlypad )
989         rc = -1;
990
991     *retn = n;
992     return rc;
993 }
994
995 /****************
996  * This filter is used to handle the armor stuff
997  */
998 static int
999 armor_filter( void *opaque, int control,
1000              IOBUF a, byte *buf, size_t *ret_len)
1001 {
1002     size_t size = *ret_len;
1003     armor_filter_context_t *afx = opaque;
1004     int rc=0, i, c;
1005     byte radbuf[3];
1006     int  idx, idx2;
1007     size_t n=0;
1008     u32 crc;
1009 #if 0
1010     static FILE *fp ;
1011
1012     if( !fp ) {
1013         fp = fopen("armor.out", "w");
1014         assert(fp);
1015     }
1016 #endif
1017
1018     if( DBG_FILTER )
1019         log_debug("armor-filter: control: %d\n", control );
1020     if( control == IOBUFCTRL_UNDERFLOW && afx->inp_bypass ) {
1021         n = 0;
1022         if( afx->buffer_len ) {
1023             for(; n < size && afx->buffer_pos < afx->buffer_len; n++ )
1024                 buf[n++] = afx->buffer[afx->buffer_pos++];
1025             if( afx->buffer_pos >= afx->buffer_len )
1026                 afx->buffer_len = 0;
1027         }
1028         for(; n < size; n++ ) {
1029             if( (c=iobuf_get(a)) == -1 )
1030                 break;
1031             buf[n] = c & 0xff;
1032         }
1033         if( !n )
1034             rc = -1;
1035         *ret_len = n;
1036     }
1037     else if( control == IOBUFCTRL_UNDERFLOW ) {
1038         /* We need some space for the faked packet.  The minmum
1039          * required size is the PARTIAL_CHUNK size plus a byte for the
1040          * length itself */
1041         if( size < PARTIAL_CHUNK+1 )
1042             BUG(); /* supplied buffer too short */
1043
1044         if( afx->faked )
1045             rc = fake_packet( afx, a, &n, buf, size );
1046         else if( !afx->inp_checked ) {
1047             rc = check_input( afx, a );
1048             if( afx->inp_bypass ) {
1049                 for(n=0; n < size && afx->buffer_pos < afx->buffer_len; )
1050                     buf[n++] = afx->buffer[afx->buffer_pos++];
1051                 if( afx->buffer_pos >= afx->buffer_len )
1052                     afx->buffer_len = 0;
1053                 if( !n )
1054                     rc = -1;
1055             }
1056             else if( afx->faked ) {
1057                 unsigned int hashes = afx->hashes;
1058                 const byte *sesmark;
1059                 size_t sesmarklen;
1060
1061                 sesmark = get_session_marker( &sesmarklen );
1062                 if ( sesmarklen > 20 )
1063                     BUG();
1064
1065                 /* the buffer is at least 15+n*15 bytes long, so it
1066                  * is easy to construct the packets */
1067
1068                 hashes &= 1|2|8|16|32|64;
1069                 if( !hashes ) {
1070                     hashes |= 2;  /* Default to SHA-1. */
1071                 }
1072                 n=0;
1073                 /* First a gpg control packet... */
1074                 buf[n++] = 0xff; /* new format, type 63, 1 length byte */
1075                 n++;   /* see below */
1076                 memcpy(buf+n, sesmark, sesmarklen ); n+= sesmarklen;
1077                 buf[n++] = CTRLPKT_CLEARSIGN_START;
1078                 buf[n++] = afx->not_dash_escaped? 0:1; /* sigclass */
1079                 if( hashes & 1 )
1080                     buf[n++] = DIGEST_ALGO_RMD160;
1081                 if( hashes & 2 )
1082                     buf[n++] = DIGEST_ALGO_SHA1;
1083                 if( hashes & 8 )
1084                     buf[n++] = DIGEST_ALGO_SHA224;
1085                 if( hashes & 16 )
1086                     buf[n++] = DIGEST_ALGO_SHA256;
1087                 if( hashes & 32 )
1088                     buf[n++] = DIGEST_ALGO_SHA384;
1089                 if( hashes & 64 )
1090                     buf[n++] = DIGEST_ALGO_SHA512;
1091                 buf[1] = n - 2;
1092
1093                 /* ...followed by an invented plaintext packet.
1094                    Amusingly enough, this packet is not compliant with
1095                    2440 as the initial partial length is less than 512
1096                    bytes.  Of course, we'll accept it anyway ;) */
1097
1098                 buf[n++] = 0xCB; /* new packet format, type 11 */
1099                 buf[n++] = 0xE1; /* 2^1 == 2 bytes */
1100                 buf[n++] = 't';  /* canonical text mode */
1101                 buf[n++] = 0;    /* namelength */
1102                 buf[n++] = 0xE2; /* 2^2 == 4 more bytes */
1103                 memset(buf+n, 0, 4); /* timestamp */
1104                 n += 4;
1105             }
1106             else if( !rc )
1107                 rc = radix64_read( afx, a, &n, buf, size );
1108         }
1109         else
1110             rc = radix64_read( afx, a, &n, buf, size );
1111 #if 0
1112         if( n )
1113             if( fwrite(buf, n, 1, fp ) != 1 )
1114                 BUG();
1115 #endif
1116         *ret_len = n;
1117     }
1118     else if( control == IOBUFCTRL_FLUSH && !afx->cancel ) {
1119         if( !afx->status ) { /* write the header line */
1120             const char *s;
1121             strlist_t comment=opt.comments;
1122
1123             if( afx->what >= DIM(head_strings) )
1124                 log_bug("afx->what=%d", afx->what);
1125             iobuf_writestr(a, "-----");
1126             iobuf_writestr(a, head_strings[afx->what] );
1127             iobuf_writestr(a, "-----" );
1128             iobuf_writestr(a,afx->eol);
1129             if (opt.emit_version)
1130               {
1131                 iobuf_writestr (a, "Version: "GNUPG_NAME" v");
1132                 for (s=VERSION; *s && *s != '.'; s++)
1133                   iobuf_writebyte (a, *s);
1134                 if (opt.emit_version > 1 && *s)
1135                   {
1136                     iobuf_writebyte (a, *s++);
1137                     for (; *s && *s != '.'; s++)
1138                       iobuf_writebyte (a, *s);
1139                     if (opt.emit_version > 2)
1140                       {
1141                         for (; *s && *s != '-' && !spacep (s); s++)
1142                           iobuf_writebyte (a, *s);
1143                         if (opt.emit_version > 3)
1144                           iobuf_writestr (a, " (" PRINTABLE_OS_NAME ")");
1145                       }
1146                   }
1147                 iobuf_writestr(a,afx->eol);
1148               }
1149
1150             /* write the comment strings */
1151             for(s=comment->d;comment;comment=comment->next,s=comment->d)
1152               {
1153                 iobuf_writestr(a, "Comment: " );
1154                 for( ; *s; s++ )
1155                   {
1156                     if( *s == '\n' )
1157                       iobuf_writestr(a, "\\n" );
1158                     else if( *s == '\r' )
1159                       iobuf_writestr(a, "\\r" );
1160                     else if( *s == '\v' )
1161                       iobuf_writestr(a, "\\v" );
1162                     else
1163                       iobuf_put(a, *s );
1164                   }
1165
1166                 iobuf_writestr(a,afx->eol);
1167               }
1168
1169             if ( afx->hdrlines ) {
1170                 for ( s = afx->hdrlines; *s; s++ ) {
1171 #ifdef HAVE_DOSISH_SYSTEM
1172                     if ( *s == '\n' )
1173                         iobuf_put( a, '\r');
1174 #endif
1175                     iobuf_put(a, *s );
1176                 }
1177             }
1178
1179             iobuf_writestr(a,afx->eol);
1180             afx->status++;
1181             afx->idx = 0;
1182             afx->idx2 = 0;
1183             afx->crc = CRCINIT;
1184
1185         }
1186         crc = afx->crc;
1187         idx = afx->idx;
1188         idx2 = afx->idx2;
1189         for(i=0; i < idx; i++ )
1190             radbuf[i] = afx->radbuf[i];
1191
1192         for(i=0; i < size; i++ )
1193             crc = (crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ buf[i]];
1194         crc &= 0x00ffffff;
1195
1196         for( ; size; buf++, size-- ) {
1197             radbuf[idx++] = *buf;
1198             if( idx > 2 ) {
1199                 idx = 0;
1200                 c = bintoasc[(*radbuf >> 2) & 077];
1201                 iobuf_put(a, c);
1202                 c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
1203                 iobuf_put(a, c);
1204                 c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
1205                 iobuf_put(a, c);
1206                 c = bintoasc[radbuf[2]&077];
1207                 iobuf_put(a, c);
1208                 if( ++idx2 >= (64/4) )
1209                   { /* pgp doesn't like 72 here */
1210                     iobuf_writestr(a,afx->eol);
1211                     idx2=0;
1212                   }
1213             }
1214         }
1215         for(i=0; i < idx; i++ )
1216             afx->radbuf[i] = radbuf[i];
1217         afx->idx = idx;
1218         afx->idx2 = idx2;
1219         afx->crc  = crc;
1220     }
1221     else if( control == IOBUFCTRL_INIT )
1222       {
1223         if( !is_initialized )
1224           initialize();
1225
1226         /* Figure out what we're using for line endings if the caller
1227            didn't specify. */
1228         if(afx->eol[0]==0)
1229           {
1230 #ifdef HAVE_DOSISH_SYSTEM
1231             afx->eol[0]='\r';
1232             afx->eol[1]='\n';
1233 #else
1234             afx->eol[0]='\n';
1235 #endif
1236           }
1237       }
1238     else if( control == IOBUFCTRL_CANCEL ) {
1239         afx->cancel = 1;
1240     }
1241     else if( control == IOBUFCTRL_FREE ) {
1242         if( afx->cancel )
1243             ;
1244         else if( afx->status ) { /* pad, write cecksum, and bottom line */
1245             crc = afx->crc;
1246             idx = afx->idx;
1247             idx2 = afx->idx2;
1248             if( idx ) {
1249                 c = bintoasc[(afx->radbuf[0]>>2)&077];
1250                 iobuf_put(a, c);
1251                 if( idx == 1 ) {
1252                     c = bintoasc[((afx->radbuf[0] << 4) & 060) & 077];
1253                     iobuf_put(a, c);
1254                     iobuf_put(a, '=');
1255                     iobuf_put(a, '=');
1256                 }
1257                 else { /* 2 */
1258                     c = bintoasc[(((afx->radbuf[0]<<4)&060)
1259                                   |((afx->radbuf[1]>>4)&017))&077];
1260                     iobuf_put(a, c);
1261                     c = bintoasc[((afx->radbuf[1] << 2) & 074) & 077];
1262                     iobuf_put(a, c);
1263                     iobuf_put(a, '=');
1264                 }
1265                 if( ++idx2 >= (64/4) )
1266                   { /* pgp doesn't like 72 here */
1267                     iobuf_writestr(a,afx->eol);
1268                     idx2=0;
1269                   }
1270             }
1271             /* may need a linefeed */
1272             if( idx2 )
1273               iobuf_writestr(a,afx->eol);
1274             /* write the CRC */
1275             iobuf_put(a, '=');
1276             radbuf[0] = crc >>16;
1277             radbuf[1] = crc >> 8;
1278             radbuf[2] = crc;
1279             c = bintoasc[(*radbuf >> 2) & 077];
1280             iobuf_put(a, c);
1281             c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
1282             iobuf_put(a, c);
1283             c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
1284             iobuf_put(a, c);
1285             c = bintoasc[radbuf[2]&077];
1286             iobuf_put(a, c);
1287             iobuf_writestr(a,afx->eol);
1288             /* and the the trailer */
1289             if( afx->what >= DIM(tail_strings) )
1290                 log_bug("afx->what=%d", afx->what);
1291             iobuf_writestr(a, "-----");
1292             iobuf_writestr(a, tail_strings[afx->what] );
1293             iobuf_writestr(a, "-----" );
1294             iobuf_writestr(a,afx->eol);
1295         }
1296         else if( !afx->any_data && !afx->inp_bypass ) {
1297             log_error(_("no valid OpenPGP data found.\n"));
1298             afx->no_openpgp_data = 1;
1299             write_status_text( STATUS_NODATA, "1" );
1300         }
1301         if( afx->truncated )
1302             log_info(_("invalid armor: line longer than %d characters\n"),
1303                       MAX_LINELEN );
1304         /* issue an error to enforce dissemination of correct software */
1305         if( afx->qp_detected )
1306             log_error(_("quoted printable character in armor - "
1307                         "probably a buggy MTA has been used\n") );
1308         xfree( afx->buffer );
1309         afx->buffer = NULL;
1310         release_armor_context (afx);
1311     }
1312     else if( control == IOBUFCTRL_DESC )
1313         mem2str (buf, "armor_filter", *ret_len);
1314     return rc;
1315 }
1316
1317
1318 /****************
1319  * create a radix64 encoded string.
1320  */
1321 char *
1322 make_radix64_string( const byte *data, size_t len )
1323 {
1324     char *buffer, *p;
1325
1326     buffer = p = xmalloc( (len+2)/3*4 + 1 );
1327     for( ; len >= 3 ; len -= 3, data += 3 ) {
1328         *p++ = bintoasc[(data[0] >> 2) & 077];
1329         *p++ = bintoasc[(((data[0] <<4)&060)|((data[1] >> 4)&017))&077];
1330         *p++ = bintoasc[(((data[1]<<2)&074)|((data[2]>>6)&03))&077];
1331         *p++ = bintoasc[data[2]&077];
1332     }
1333     if( len == 2 ) {
1334         *p++ = bintoasc[(data[0] >> 2) & 077];
1335         *p++ = bintoasc[(((data[0] <<4)&060)|((data[1] >> 4)&017))&077];
1336         *p++ = bintoasc[((data[1]<<2)&074)];
1337     }
1338     else if( len == 1 ) {
1339         *p++ = bintoasc[(data[0] >> 2) & 077];
1340         *p++ = bintoasc[(data[0] <<4)&060];
1341     }
1342     *p = 0;
1343     return buffer;
1344 }
1345
1346
1347 /***********************************************
1348  *  For the pipemode command we can't use the armor filter for various
1349  *  reasons, so we use this new unarmor_pump stuff to remove the armor
1350  */
1351
1352 enum unarmor_state_e {
1353     STA_init = 0,
1354     STA_bypass,
1355     STA_wait_newline,
1356     STA_wait_dash,
1357     STA_first_dash,
1358     STA_compare_header,
1359     STA_found_header_wait_newline,
1360     STA_skip_header_lines,
1361     STA_skip_header_lines_non_ws,
1362     STA_read_data,
1363     STA_wait_crc,
1364     STA_read_crc,
1365     STA_ready
1366 };
1367
1368 struct unarmor_pump_s {
1369     enum unarmor_state_e state;
1370     byte val;
1371     int checkcrc;
1372     int pos;   /* counts from 0..3 */
1373     u32 crc;
1374     u32 mycrc; /* the one store in the data */
1375 };
1376
1377
1378
1379 UnarmorPump
1380 unarmor_pump_new (void)
1381 {
1382     UnarmorPump x;
1383
1384     if( !is_initialized )
1385         initialize();
1386     x = xmalloc_clear (sizeof *x);
1387     return x;
1388 }
1389
1390 void
1391 unarmor_pump_release (UnarmorPump x)
1392 {
1393     xfree (x);
1394 }
1395
1396 /*
1397  * Get the next character from the ascii armor taken from the IOBUF
1398  * created earlier by unarmor_pump_new().
1399  * Return:  c = Character
1400  *        256 = ignore this value
1401  *         -1 = End of current armor
1402  *         -2 = Premature EOF (not used)
1403  *         -3 = Invalid armor
1404  */
1405 int
1406 unarmor_pump (UnarmorPump x, int c)
1407 {
1408     int rval = 256; /* default is to ignore the return value */
1409
1410     switch (x->state) {
1411       case STA_init:
1412         {
1413             byte tmp[1];
1414             tmp[0] = c;
1415             if ( is_armored (tmp) )
1416                 x->state = c == '-'? STA_first_dash : STA_wait_newline;
1417             else {
1418                 x->state = STA_bypass;
1419                 return c;
1420             }
1421         }
1422         break;
1423       case STA_bypass:
1424         return c; /* return here to avoid crc calculation */
1425       case STA_wait_newline:
1426         if (c == '\n')
1427             x->state = STA_wait_dash;
1428         break;
1429       case STA_wait_dash:
1430         x->state = c == '-'? STA_first_dash : STA_wait_newline;
1431         break;
1432       case STA_first_dash: /* just need for initalization */
1433         x->pos = 0;
1434         x->state = STA_compare_header;
1435       case STA_compare_header:
1436         if ( "-----BEGIN PGP SIGNATURE-----"[++x->pos] == c ) {
1437             if ( x->pos == 28 )
1438                 x->state = STA_found_header_wait_newline;
1439         }
1440         else
1441             x->state = c == '\n'? STA_wait_dash : STA_wait_newline;
1442         break;
1443       case STA_found_header_wait_newline:
1444         /* to make CR,LF issues easier we simply allow for white space
1445            behind the 5 dashes */
1446         if ( c == '\n' )
1447             x->state = STA_skip_header_lines;
1448         else if ( c != '\r' && c != ' ' && c != '\t' )
1449             x->state = STA_wait_dash; /* garbage after the header line */
1450         break;
1451       case STA_skip_header_lines:
1452         /* i.e. wait for one empty line */
1453         if ( c == '\n' ) {
1454             x->state = STA_read_data;
1455             x->crc = CRCINIT;
1456             x->val = 0;
1457             x->pos = 0;
1458         }
1459         else if ( c != '\r' && c != ' ' && c != '\t' )
1460             x->state = STA_skip_header_lines_non_ws;
1461         break;
1462       case STA_skip_header_lines_non_ws:
1463         /* like above but we already encountered non white space */
1464         if ( c == '\n' )
1465             x->state = STA_skip_header_lines;
1466         break;
1467       case STA_read_data:
1468         /* fixme: we don't check for the trailing dash lines but rely
1469          * on the armor stop characters */
1470         if( c == '\n' || c == ' ' || c == '\r' || c == '\t' )
1471             break; /* skip all kind of white space */
1472
1473         if( c == '=' ) { /* pad character: stop */
1474             if( x->pos == 1 ) /* in this case val has some value */
1475                 rval = x->val;
1476             x->state = STA_wait_crc;
1477             break;
1478         }
1479
1480         {
1481             int c2;
1482             if( (c = asctobin[(c2=c)]) == 255 ) {
1483                 log_error(_("invalid radix64 character %02X skipped\n"), c2);
1484                 break;
1485             }
1486         }
1487
1488         switch(x->pos) {
1489           case 0:
1490             x->val = c << 2;
1491             break;
1492           case 1:
1493             x->val |= (c>>4)&3;
1494             rval = x->val;
1495             x->val = (c<<4)&0xf0;
1496             break;
1497           case 2:
1498             x->val |= (c>>2)&15;
1499             rval = x->val;
1500             x->val = (c<<6)&0xc0;
1501             break;
1502           case 3:
1503             x->val |= c&0x3f;
1504             rval = x->val;
1505             break;
1506         }
1507         x->pos = (x->pos+1) % 4;
1508         break;
1509       case STA_wait_crc:
1510         if( c == '\n' || c == ' ' || c == '\r' || c == '\t' || c == '=' )
1511             break; /* skip ws and pad characters */
1512         /* assume that we are at the next line */
1513         x->state = STA_read_crc;
1514         x->pos = 0;
1515         x->mycrc = 0;
1516       case STA_read_crc:
1517         if( (c = asctobin[c]) == 255 ) {
1518             rval = -1; /* ready */
1519             if( x->crc != x->mycrc ) {
1520                 log_info (_("CRC error; %06lX - %06lX\n"),
1521                           (ulong)x->crc, (ulong)x->mycrc);
1522                 if ( invalid_crc() )
1523                     rval = -3;
1524             }
1525             x->state = STA_ready; /* not sure whether this is correct */
1526             break;
1527         }
1528
1529         switch(x->pos) {
1530           case 0:
1531             x->val = c << 2;
1532             break;
1533           case 1:
1534             x->val |= (c>>4)&3;
1535             x->mycrc |= x->val << 16;
1536             x->val = (c<<4)&0xf0;
1537             break;
1538           case 2:
1539             x->val |= (c>>2)&15;
1540             x->mycrc |= x->val << 8;
1541             x->val = (c<<6)&0xc0;
1542             break;
1543           case 3:
1544             x->val |= c&0x3f;
1545             x->mycrc |= x->val;
1546             break;
1547         }
1548         x->pos = (x->pos+1) % 4;
1549         break;
1550       case STA_ready:
1551         rval = -1;
1552         break;
1553     }
1554
1555     if ( !(rval & ~255) ) { /* compute the CRC */
1556         x->crc = (x->crc << 8) ^ crc_table[((x->crc >> 16)&0xff) ^ rval];
1557         x->crc &= 0x00ffffff;
1558     }
1559
1560     return rval;
1561 }