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