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