c80e902d27137844f20eebc6860ea51dc665191b
[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 "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             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         for(; n < size; n++ ) {
1035             if( (c=iobuf_get(a)) == -1 )
1036                 break;
1037             buf[n] = c & 0xff;
1038         }
1039         if( !n )
1040             rc = -1;
1041         *ret_len = n;
1042     }
1043     else if( control == IOBUFCTRL_UNDERFLOW ) {
1044         /* We need some space for the faked packet.  The minmum
1045          * required size is the PARTIAL_CHUNK size plus a byte for the
1046          * length itself */
1047         if( size < PARTIAL_CHUNK+1 )
1048             BUG(); /* supplied buffer too short */
1049
1050         if( afx->faked )
1051             rc = fake_packet( afx, a, &n, buf, size );
1052         else if( !afx->inp_checked ) {
1053             rc = check_input( afx, a );
1054             if( afx->inp_bypass ) {
1055                 for(n=0; n < size && afx->buffer_pos < afx->buffer_len; )
1056                     buf[n++] = afx->buffer[afx->buffer_pos++];
1057                 if( afx->buffer_pos >= afx->buffer_len )
1058                     afx->buffer_len = 0;
1059                 if( !n )
1060                     rc = -1;
1061             }
1062             else if( afx->faked ) {
1063                 unsigned int hashes = afx->hashes;
1064                 const byte *sesmark;
1065                 size_t sesmarklen;
1066
1067                 sesmark = get_session_marker( &sesmarklen );
1068                 if ( sesmarklen > 20 )
1069                     BUG();
1070
1071                 /* the buffer is at least 15+n*15 bytes long, so it
1072                  * is easy to construct the packets */
1073
1074                 hashes &= 1|2|8|16|32|64;
1075                 if( !hashes ) {
1076                     hashes |= 2;  /* Default to SHA-1. */
1077                 }
1078                 n=0;
1079                 /* First a gpg control packet... */
1080                 buf[n++] = 0xff; /* new format, type 63, 1 length byte */
1081                 n++;   /* see below */
1082                 memcpy(buf+n, sesmark, sesmarklen ); n+= sesmarklen;
1083                 buf[n++] = CTRLPKT_CLEARSIGN_START;
1084                 buf[n++] = afx->not_dash_escaped? 0:1; /* sigclass */
1085                 if( hashes & 1 )
1086                     buf[n++] = DIGEST_ALGO_RMD160;
1087                 if( hashes & 2 )
1088                     buf[n++] = DIGEST_ALGO_SHA1;
1089                 if( hashes & 8 )
1090                     buf[n++] = DIGEST_ALGO_SHA224;
1091                 if( hashes & 16 )
1092                     buf[n++] = DIGEST_ALGO_SHA256;
1093                 if( hashes & 32 )
1094                     buf[n++] = DIGEST_ALGO_SHA384;
1095                 if( hashes & 64 )
1096                     buf[n++] = DIGEST_ALGO_SHA512;
1097                 buf[1] = n - 2;
1098
1099                 /* ...followed by an invented plaintext packet.
1100                    Amusingly enough, this packet is not compliant with
1101                    2440 as the initial partial length is less than 512
1102                    bytes.  Of course, we'll accept it anyway ;) */
1103
1104                 buf[n++] = 0xCB; /* new packet format, type 11 */
1105                 buf[n++] = 0xE1; /* 2^1 == 2 bytes */
1106                 buf[n++] = 't';  /* canonical text mode */
1107                 buf[n++] = 0;    /* namelength */
1108                 buf[n++] = 0xE2; /* 2^2 == 4 more bytes */
1109                 memset(buf+n, 0, 4); /* timestamp */
1110                 n += 4;
1111             }
1112             else if( !rc )
1113                 rc = radix64_read( afx, a, &n, buf, size );
1114         }
1115         else
1116             rc = radix64_read( afx, a, &n, buf, size );
1117 #if 0
1118         if( n )
1119             if( fwrite(buf, n, 1, fp ) != 1 )
1120                 BUG();
1121 #endif
1122         *ret_len = n;
1123     }
1124     else if( control == IOBUFCTRL_FLUSH && !afx->cancel ) {
1125         if( !afx->status ) { /* write the header line */
1126             const char *s;
1127             strlist_t comment=opt.comments;
1128
1129             if( afx->what >= DIM(head_strings) )
1130                 log_bug("afx->what=%d", afx->what);
1131             iobuf_writestr(a, "-----");
1132             iobuf_writestr(a, head_strings[afx->what] );
1133             iobuf_writestr(a, "-----" );
1134             iobuf_writestr(a,afx->eol);
1135             if (opt.emit_version)
1136               {
1137                 iobuf_writestr (a, "Version: "GNUPG_NAME" v");
1138                 for (s=VERSION; *s && *s != '.'; s++)
1139                   iobuf_writebyte (a, *s);
1140                 if (opt.emit_version > 1 && *s)
1141                   {
1142                     iobuf_writebyte (a, *s++);
1143                     for (; *s && *s != '.'; s++)
1144                       iobuf_writebyte (a, *s);
1145                     if (opt.emit_version > 2)
1146                       {
1147                         for (; *s && *s != '-' && !spacep (s); s++)
1148                           iobuf_writebyte (a, *s);
1149                         if (opt.emit_version > 3)
1150                           iobuf_writestr (a, " (" PRINTABLE_OS_NAME ")");
1151                       }
1152                   }
1153                 iobuf_writestr(a,afx->eol);
1154               }
1155
1156             /* write the comment strings */
1157             for(s=comment->d;comment;comment=comment->next,s=comment->d)
1158               {
1159                 iobuf_writestr(a, "Comment: " );
1160                 for( ; *s; s++ )
1161                   {
1162                     if( *s == '\n' )
1163                       iobuf_writestr(a, "\\n" );
1164                     else if( *s == '\r' )
1165                       iobuf_writestr(a, "\\r" );
1166                     else if( *s == '\v' )
1167                       iobuf_writestr(a, "\\v" );
1168                     else
1169                       iobuf_put(a, *s );
1170                   }
1171
1172                 iobuf_writestr(a,afx->eol);
1173               }
1174
1175             if ( afx->hdrlines ) {
1176                 for ( s = afx->hdrlines; *s; s++ ) {
1177 #ifdef HAVE_DOSISH_SYSTEM
1178                     if ( *s == '\n' )
1179                         iobuf_put( a, '\r');
1180 #endif
1181                     iobuf_put(a, *s );
1182                 }
1183             }
1184
1185             iobuf_writestr(a,afx->eol);
1186             afx->status++;
1187             afx->idx = 0;
1188             afx->idx2 = 0;
1189             afx->crc = CRCINIT;
1190
1191         }
1192         crc = afx->crc;
1193         idx = afx->idx;
1194         idx2 = afx->idx2;
1195         for(i=0; i < idx; i++ )
1196             radbuf[i] = afx->radbuf[i];
1197
1198         for(i=0; i < size; i++ )
1199             crc = (crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ buf[i]];
1200         crc &= 0x00ffffff;
1201
1202         for( ; size; buf++, size-- ) {
1203             radbuf[idx++] = *buf;
1204             if( idx > 2 ) {
1205                 idx = 0;
1206                 c = bintoasc[(*radbuf >> 2) & 077];
1207                 iobuf_put(a, c);
1208                 c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
1209                 iobuf_put(a, c);
1210                 c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
1211                 iobuf_put(a, c);
1212                 c = bintoasc[radbuf[2]&077];
1213                 iobuf_put(a, c);
1214                 if( ++idx2 >= (64/4) )
1215                   { /* pgp doesn't like 72 here */
1216                     iobuf_writestr(a,afx->eol);
1217                     idx2=0;
1218                   }
1219             }
1220         }
1221         for(i=0; i < idx; i++ )
1222             afx->radbuf[i] = radbuf[i];
1223         afx->idx = idx;
1224         afx->idx2 = idx2;
1225         afx->crc  = crc;
1226     }
1227     else if( control == IOBUFCTRL_INIT )
1228       {
1229         if( !is_initialized )
1230           initialize();
1231
1232         /* Figure out what we're using for line endings if the caller
1233            didn't specify. */
1234         if(afx->eol[0]==0)
1235           {
1236 #ifdef HAVE_DOSISH_SYSTEM
1237             afx->eol[0]='\r';
1238             afx->eol[1]='\n';
1239 #else
1240             afx->eol[0]='\n';
1241 #endif
1242           }
1243       }
1244     else if( control == IOBUFCTRL_CANCEL ) {
1245         afx->cancel = 1;
1246     }
1247     else if( control == IOBUFCTRL_FREE ) {
1248         if( afx->cancel )
1249             ;
1250         else if( afx->status ) { /* pad, write cecksum, and bottom line */
1251             crc = afx->crc;
1252             idx = afx->idx;
1253             idx2 = afx->idx2;
1254             if( idx ) {
1255                 c = bintoasc[(afx->radbuf[0]>>2)&077];
1256                 iobuf_put(a, c);
1257                 if( idx == 1 ) {
1258                     c = bintoasc[((afx->radbuf[0] << 4) & 060) & 077];
1259                     iobuf_put(a, c);
1260                     iobuf_put(a, '=');
1261                     iobuf_put(a, '=');
1262                 }
1263                 else { /* 2 */
1264                     c = bintoasc[(((afx->radbuf[0]<<4)&060)
1265                                   |((afx->radbuf[1]>>4)&017))&077];
1266                     iobuf_put(a, c);
1267                     c = bintoasc[((afx->radbuf[1] << 2) & 074) & 077];
1268                     iobuf_put(a, c);
1269                     iobuf_put(a, '=');
1270                 }
1271                 if( ++idx2 >= (64/4) )
1272                   { /* pgp doesn't like 72 here */
1273                     iobuf_writestr(a,afx->eol);
1274                     idx2=0;
1275                   }
1276             }
1277             /* may need a linefeed */
1278             if( idx2 )
1279               iobuf_writestr(a,afx->eol);
1280             /* write the CRC */
1281             iobuf_put(a, '=');
1282             radbuf[0] = crc >>16;
1283             radbuf[1] = crc >> 8;
1284             radbuf[2] = crc;
1285             c = bintoasc[(*radbuf >> 2) & 077];
1286             iobuf_put(a, c);
1287             c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
1288             iobuf_put(a, c);
1289             c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
1290             iobuf_put(a, c);
1291             c = bintoasc[radbuf[2]&077];
1292             iobuf_put(a, c);
1293             iobuf_writestr(a,afx->eol);
1294             /* and the the trailer */
1295             if( afx->what >= DIM(tail_strings) )
1296                 log_bug("afx->what=%d", afx->what);
1297             iobuf_writestr(a, "-----");
1298             iobuf_writestr(a, tail_strings[afx->what] );
1299             iobuf_writestr(a, "-----" );
1300             iobuf_writestr(a,afx->eol);
1301         }
1302         else if( !afx->any_data && !afx->inp_bypass ) {
1303             log_error(_("no valid OpenPGP data found.\n"));
1304             afx->no_openpgp_data = 1;
1305             write_status_text( STATUS_NODATA, "1" );
1306         }
1307         if( afx->truncated )
1308             log_info(_("invalid armor: line longer than %d characters\n"),
1309                       MAX_LINELEN );
1310         /* issue an error to enforce dissemination of correct software */
1311         if( afx->qp_detected )
1312             log_error(_("quoted printable character in armor - "
1313                         "probably a buggy MTA has been used\n") );
1314         xfree( afx->buffer );
1315         afx->buffer = NULL;
1316         release_armor_context (afx);
1317     }
1318     else if( control == IOBUFCTRL_DESC )
1319         mem2str (buf, "armor_filter", *ret_len);
1320     return rc;
1321 }
1322
1323
1324 /****************
1325  * create a radix64 encoded string.
1326  */
1327 char *
1328 make_radix64_string( const byte *data, size_t len )
1329 {
1330     char *buffer, *p;
1331
1332     buffer = p = xmalloc( (len+2)/3*4 + 1 );
1333     for( ; len >= 3 ; len -= 3, data += 3 ) {
1334         *p++ = bintoasc[(data[0] >> 2) & 077];
1335         *p++ = bintoasc[(((data[0] <<4)&060)|((data[1] >> 4)&017))&077];
1336         *p++ = bintoasc[(((data[1]<<2)&074)|((data[2]>>6)&03))&077];
1337         *p++ = bintoasc[data[2]&077];
1338     }
1339     if( len == 2 ) {
1340         *p++ = bintoasc[(data[0] >> 2) & 077];
1341         *p++ = bintoasc[(((data[0] <<4)&060)|((data[1] >> 4)&017))&077];
1342         *p++ = bintoasc[((data[1]<<2)&074)];
1343     }
1344     else if( len == 1 ) {
1345         *p++ = bintoasc[(data[0] >> 2) & 077];
1346         *p++ = bintoasc[(data[0] <<4)&060];
1347     }
1348     *p = 0;
1349     return buffer;
1350 }
1351
1352
1353 /***********************************************
1354  *  For the pipemode command we can't use the armor filter for various
1355  *  reasons, so we use this new unarmor_pump stuff to remove the armor
1356  */
1357
1358 enum unarmor_state_e {
1359     STA_init = 0,
1360     STA_bypass,
1361     STA_wait_newline,
1362     STA_wait_dash,
1363     STA_first_dash,
1364     STA_compare_header,
1365     STA_found_header_wait_newline,
1366     STA_skip_header_lines,
1367     STA_skip_header_lines_non_ws,
1368     STA_read_data,
1369     STA_wait_crc,
1370     STA_read_crc,
1371     STA_ready
1372 };
1373
1374 struct unarmor_pump_s {
1375     enum unarmor_state_e state;
1376     byte val;
1377     int checkcrc;
1378     int pos;   /* counts from 0..3 */
1379     u32 crc;
1380     u32 mycrc; /* the one store in the data */
1381 };
1382
1383
1384
1385 UnarmorPump
1386 unarmor_pump_new (void)
1387 {
1388     UnarmorPump x;
1389
1390     if( !is_initialized )
1391         initialize();
1392     x = xmalloc_clear (sizeof *x);
1393     return x;
1394 }
1395
1396 void
1397 unarmor_pump_release (UnarmorPump x)
1398 {
1399     xfree (x);
1400 }
1401
1402 /*
1403  * Get the next character from the ascii armor taken from the IOBUF
1404  * created earlier by unarmor_pump_new().
1405  * Return:  c = Character
1406  *        256 = ignore this value
1407  *         -1 = End of current armor
1408  *         -2 = Premature EOF (not used)
1409  *         -3 = Invalid armor
1410  */
1411 int
1412 unarmor_pump (UnarmorPump x, int c)
1413 {
1414     int rval = 256; /* default is to ignore the return value */
1415
1416     switch (x->state) {
1417       case STA_init:
1418         {
1419             byte tmp[2];
1420             tmp[0] = c;
1421             tmp[1] = 0;
1422             if ( is_armored (tmp) )
1423                 x->state = c == '-'? STA_first_dash : STA_wait_newline;
1424             else {
1425                 x->state = STA_bypass;
1426                 return c;
1427             }
1428         }
1429         break;
1430       case STA_bypass:
1431         return c; /* return here to avoid crc calculation */
1432       case STA_wait_newline:
1433         if (c == '\n')
1434             x->state = STA_wait_dash;
1435         break;
1436       case STA_wait_dash:
1437         x->state = c == '-'? STA_first_dash : STA_wait_newline;
1438         break;
1439       case STA_first_dash: /* just need for initialization */
1440         x->pos = 0;
1441         x->state = STA_compare_header;
1442       case STA_compare_header:
1443         if ( "-----BEGIN PGP SIGNATURE-----"[++x->pos] == c ) {
1444             if ( x->pos == 28 )
1445                 x->state = STA_found_header_wait_newline;
1446         }
1447         else
1448             x->state = c == '\n'? STA_wait_dash : STA_wait_newline;
1449         break;
1450       case STA_found_header_wait_newline:
1451         /* to make CR,LF issues easier we simply allow for white space
1452            behind the 5 dashes */
1453         if ( c == '\n' )
1454             x->state = STA_skip_header_lines;
1455         else if ( c != '\r' && c != ' ' && c != '\t' )
1456             x->state = STA_wait_dash; /* garbage after the header line */
1457         break;
1458       case STA_skip_header_lines:
1459         /* i.e. wait for one empty line */
1460         if ( c == '\n' ) {
1461             x->state = STA_read_data;
1462             x->crc = CRCINIT;
1463             x->val = 0;
1464             x->pos = 0;
1465         }
1466         else if ( c != '\r' && c != ' ' && c != '\t' )
1467             x->state = STA_skip_header_lines_non_ws;
1468         break;
1469       case STA_skip_header_lines_non_ws:
1470         /* like above but we already encountered non white space */
1471         if ( c == '\n' )
1472             x->state = STA_skip_header_lines;
1473         break;
1474       case STA_read_data:
1475         /* fixme: we don't check for the trailing dash lines but rely
1476          * on the armor stop characters */
1477         if( c == '\n' || c == ' ' || c == '\r' || c == '\t' )
1478             break; /* skip all kind of white space */
1479
1480         if( c == '=' ) { /* pad character: stop */
1481             if( x->pos == 1 ) /* in this case val has some value */
1482                 rval = x->val;
1483             x->state = STA_wait_crc;
1484             break;
1485         }
1486
1487         {
1488             int c2;
1489             if( (c = asctobin[(c2=c)]) == 255 ) {
1490                 log_error(_("invalid radix64 character %02X skipped\n"), c2);
1491                 break;
1492             }
1493         }
1494
1495         switch(x->pos) {
1496           case 0:
1497             x->val = c << 2;
1498             break;
1499           case 1:
1500             x->val |= (c>>4)&3;
1501             rval = x->val;
1502             x->val = (c<<4)&0xf0;
1503             break;
1504           case 2:
1505             x->val |= (c>>2)&15;
1506             rval = x->val;
1507             x->val = (c<<6)&0xc0;
1508             break;
1509           case 3:
1510             x->val |= c&0x3f;
1511             rval = x->val;
1512             break;
1513         }
1514         x->pos = (x->pos+1) % 4;
1515         break;
1516       case STA_wait_crc:
1517         if( c == '\n' || c == ' ' || c == '\r' || c == '\t' || c == '=' )
1518             break; /* skip ws and pad characters */
1519         /* assume that we are at the next line */
1520         x->state = STA_read_crc;
1521         x->pos = 0;
1522         x->mycrc = 0;
1523       case STA_read_crc:
1524         if( (c = asctobin[c]) == 255 ) {
1525             rval = -1; /* ready */
1526             if( x->crc != x->mycrc ) {
1527                 log_info (_("CRC error; %06lX - %06lX\n"),
1528                           (ulong)x->crc, (ulong)x->mycrc);
1529                 if ( invalid_crc() )
1530                     rval = -3;
1531             }
1532             x->state = STA_ready; /* not sure whether this is correct */
1533             break;
1534         }
1535
1536         switch(x->pos) {
1537           case 0:
1538             x->val = c << 2;
1539             break;
1540           case 1:
1541             x->val |= (c>>4)&3;
1542             x->mycrc |= x->val << 16;
1543             x->val = (c<<4)&0xf0;
1544             break;
1545           case 2:
1546             x->val |= (c>>2)&15;
1547             x->mycrc |= x->val << 8;
1548             x->val = (c<<6)&0xc0;
1549             break;
1550           case 3:
1551             x->val |= c&0x3f;
1552             x->mycrc |= x->val;
1553             break;
1554         }
1555         x->pos = (x->pos+1) % 4;
1556         break;
1557       case STA_ready:
1558         rval = -1;
1559         break;
1560     }
1561
1562     if ( !(rval & ~255) ) { /* compute the CRC */
1563         x->crc = (x->crc << 8) ^ crc_table[((x->crc >> 16)&0xff) ^ rval];
1564         x->crc &= 0x00ffffff;
1565     }
1566
1567     return rval;
1568 }