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