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