See ChangeLog: Wed Dec 23 17:12:24 CET 1998 Werner Koch
[gnupg.git] / g10 / armor.c
1 /* armor.c - Armor flter
2  *      Copyright (C) 1998 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
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
28 #include "errors.h"
29 #include "iobuf.h"
30 #include "memory.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
40 #define CRCINIT 0xB704CE
41 #define CRCPOLY 0X864CFB
42 #define CRCUPDATE(a,c) do {                                                 \
43                         a = ((a) << 8) ^ crc_table[((a)&0xff >> 16) ^ (c)]; \
44                         a &= 0x00ffffff;                                    \
45                     } while(0)
46 static u32 crc_table[256];
47 static byte bintoasc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
48                          "abcdefghijklmnopqrstuvwxyz"
49                          "0123456789+/";
50 static byte asctobin[256]; /* runtime initialized */
51 static int is_initialized;
52
53
54 typedef enum {
55     fhdrHASArmor = 0,
56     fhdrNOArmor,
57     fhdrINIT,
58     fhdrINITCont,
59     fhdrINITSkip,
60     fhdrCHECKBegin,
61     fhdrWAITHeader,
62     fhdrWAITClearsig,
63     fhdrSKIPHeader,
64     fhdrCLEARSIG,
65     fhdrREADClearsig,
66     fhdrNullClearsig,
67     fhdrEMPTYClearsig,
68     fhdrCHECKClearsig,
69     fhdrCHECKClearsig2,
70     fhdrCHECKDashEscaped,
71     fhdrCHECKDashEscaped2,
72     fhdrCHECKDashEscaped3,
73     fhdrREADClearsigNext,
74     fhdrENDClearsig,
75     fhdrENDClearsigHelp,
76     fhdrTESTSpaces,
77     fhdrCLEARSIGSimple,
78     fhdrCLEARSIGSimpleNext,
79     fhdrTEXT,
80     fhdrTEXTSimple,
81     fhdrERROR,
82     fhdrERRORShow,
83     fhdrEOF
84 } fhdr_state_t;
85
86
87 /* if we encounter this armor string with this index, go
88  * into a mode which fakes packets and wait for the next armor */
89 #define BEGIN_SIGNED_MSG_IDX 3
90 static char *head_strings[] = {
91     "BEGIN PGP MESSAGE",
92     "BEGIN PGP PUBLIC KEY BLOCK",
93     "BEGIN PGP SIGNATURE",
94     "BEGIN PGP SIGNED MESSAGE",
95     "BEGIN PGP ARMORED FILE",       /* gnupg extension */
96     "BEGIN PGP PRIVATE KEY BLOCK",
97     "BEGIN PGP SECRET KEY BLOCK",   /* only used by pgp2 */
98     NULL
99 };
100 static char *tail_strings[] = {
101     "END PGP MESSAGE",
102     "END PGP PUBLIC KEY BLOCK",
103     "END PGP SIGNATURE",
104     "END dummy",
105     "END PGP ARMORED FILE",
106     "END PGP PRIVATE KEY BLOCK",
107     "END PGP SECRET KEY BLOCK",
108     NULL
109 };
110
111
112 static fhdr_state_t find_header( fhdr_state_t state,
113                                  byte *buf, size_t *r_buflen,
114                                  IOBUF a, size_t n,
115                                  unsigned *r_empty, int *r_hashes,
116                                  int only_keyblocks, int *not_dashed );
117
118
119 static void
120 initialize(void)
121 {
122     int i, j;
123     u32 t;
124     byte *s;
125
126     /* init the crc lookup table */
127     crc_table[0] = 0;
128     for(i=j=0; j < 128; j++ ) {
129         t = crc_table[j];
130         if( t & 0x00800000 ) {
131             t <<= 1;
132             crc_table[i++] = t ^ CRCPOLY;
133             crc_table[i++] = t;
134         }
135         else {
136             t <<= 1;
137             crc_table[i++] = t;
138             crc_table[i++] = t ^ CRCPOLY;
139         }
140     }
141     /* build the helptable for radix64 to bin conversion */
142     for(i=0; i < 256; i++ )
143         asctobin[i] = 255; /* used to detect invalid characters */
144     for(s=bintoasc,i=0; *s; s++,i++ )
145         asctobin[*s] = i;
146
147     is_initialized=1;
148 }
149
150 /****************
151  * Check whether this is an armored file or not
152  * See also parse-packet.c for details on this code
153  * Returns: True if it seems to be armored
154  */
155 static int
156 is_armored( byte *buf )
157 {
158     int ctb, pkttype;
159
160     ctb = *buf;
161     if( !(ctb & 0x80) )
162         return 1; /* invalid packet: assume it is armored */
163     pkttype =  ctb & 0x40 ? (ctb & 0x3f) : ((ctb>>2)&0xf);
164     switch( pkttype ) {
165       case PKT_MARKER:
166       case PKT_SYMKEY_ENC:
167       case PKT_PUBLIC_KEY:
168       case PKT_SECRET_KEY:
169       case PKT_PUBKEY_ENC:
170       case PKT_SIGNATURE:
171       case PKT_COMMENT:
172       case PKT_OLD_COMMENT:
173       case PKT_PLAINTEXT:
174       case PKT_COMPRESSED:
175       case PKT_ENCRYPTED:
176         return 0; /* seems to be a regular packet: not armored */
177     }
178
179     return 1;
180 }
181
182
183 /****************
184  * Try to check whether the iobuf is armored
185  * Returns true if this may be the case; the caller should use the
186  *         filter to do further processing.
187  */
188 int
189 use_armor_filter( IOBUF a )
190 {
191     byte buf[1];
192     int n;
193
194     n = iobuf_peek(a, buf, 1 );
195     if( n == -1 )
196         return 0; /* EOF, doesn't matter whether armored or not */
197     if( !n )
198         return 1; /* can't check it: try armored */
199     return is_armored(buf);
200 }
201
202
203
204
205 static void
206 invalid_armor(void)
207 {
208     write_status(STATUS_BADARMOR);
209     g10_exit(1); /* stop here */
210 }
211
212
213 /****************
214  * check whether the armor header is valid on a signed message.
215  * this is for security reasons: the header lines are not included in the
216  * hash and by using some creative formatting rules, Mallory could fake
217  * any text at the beginning of a document; assuming it is read with
218  * a simple viewer. We only allow the Hash Header.
219  */
220 static int
221 parse_hash_header( const char *line )
222 {
223     const char *s, *s2;
224     unsigned found = 0;
225
226     if( strlen(line) < 6  || strlen(line) > 60 )
227         return 0; /* too short or too long */
228     if( memcmp( line, "Hash:", 5 ) )
229         return 0; /* invalid header */
230     s = line+5;
231     for(s=line+5;;s=s2) {
232         for(; *s && (*s==' ' || *s == '\t'); s++ )
233             ;
234         if( !*s )
235             break;
236         for(s2=s+1; *s2 && *s2!=' ' && *s2 != '\t' && *s2 != ','; s2++ )
237             ;
238         if( !strncmp( s, "RIPEMD160", s2-s ) )
239             found |= 1;
240         else if( !strncmp( s, "SHA1", s2-s ) )
241             found |= 2;
242         else if( !strncmp( s, "MD5", s2-s ) )
243             found |= 4;
244         else if( !strncmp( s, "TIGER", s2-s ) )
245             found |= 8;
246         else
247             return 0;
248         for(; *s2 && (*s2==' ' || *s2 == '\t'); s2++ )
249             ;
250         if( *s2 && *s2 != ',' )
251             return 0;
252         if( *s2 )
253             s2++;
254     }
255     return found;
256 }
257
258
259 /****************
260  * parse an ascii armor.
261  * Returns: the state,
262  *          the remaining bytes in BUF are returned in RBUFLEN.
263  *          r_empty return the # of empty lines before the buffer
264  */
265 static fhdr_state_t
266 find_header( fhdr_state_t state, byte *buf, size_t *r_buflen,
267              IOBUF a, size_t n, unsigned *r_empty, int *r_hashes,
268              int only_keyblocks, int *not_dashed )
269 {
270     int c=0, i;
271     const char *s;
272     byte *p;
273     size_t buflen;
274     int cont;
275     int clearsig=0;
276     int hdr_line=0;
277     unsigned empty = 0;
278
279     buflen = *r_buflen;
280     assert(buflen >= 100 );
281     buflen -= 4; /* reserved room for CR,LF, and two extra */
282
283     do {
284         switch( state ) {
285           case fhdrHASArmor:
286             /* read at least the first byte to check whether it is armored
287              * or not */
288             c = 0;
289             for(n=0; n < 28 && (c=iobuf_get(a)) != -1 && c != '\n'; )
290                 buf[n++] = c;
291             if( !n && c == '\n' )
292                 state = fhdrCHECKBegin;
293             else if( !n  || c == -1 )
294                 state = fhdrNOArmor; /* too short */
295             else if( !is_armored( buf ) ) {
296                 state = fhdrNOArmor;
297                 if( c == '\n' )
298                     buf[n++] = c;
299             }
300             else if( c == '\n' )
301                 state = fhdrCHECKBegin;
302             else
303                 state = fhdrINITCont;
304             break;
305
306           case fhdrINIT: /* read some stuff into buffer */
307             n = 0;
308           case fhdrINITCont: /* read more stuff into buffer */
309             c = 0;
310             for(; n < buflen && (c=iobuf_get(a)) != -1 && c != '\n'; )
311                 buf[n++] = c;
312             state = c == '\n' ? fhdrCHECKBegin :
313                      c == -1  ? fhdrEOF : fhdrINITSkip;
314             break;
315
316           case fhdrINITSkip:
317             if( c == '\n' )
318                 n = 0;
319             else {
320                 while( (c=iobuf_get(a)) != -1 && c != '\n' )
321                     ;
322             }
323             state =  c == -1? fhdrEOF : fhdrINIT;
324             break;
325
326           case fhdrSKIPHeader:
327             while( (c=iobuf_get(a)) != -1 && c != '\n' )
328                 ;
329             state =  c == -1? fhdrEOF : fhdrWAITHeader;
330             break;
331
332           case fhdrWAITHeader: /* wait for Header lines */
333             c = 0;
334             for(n=0; n < buflen && (c=iobuf_get(a)) != -1 && c != '\n'; )
335                 buf[n++] = c;
336             buf[n] = 0;
337             if( n < buflen || c == '\n' ) {
338                 if( n && buf[0] != '\r') { /* maybe a header */
339                     if( strchr( buf, ':') ) { /* yes */
340                         int hashes=0;
341                         if( buf[n-1] == '\r' )
342                             buf[--n] = 0;
343                         if( opt.verbose ) {
344                             log_info(_("armor header: "));
345                             print_string( stderr, buf, n, 0 );
346                             putc('\n', stderr);
347                         }
348                         if( clearsig && !(hashes=parse_hash_header( buf )) ) {
349                             if( strlen(buf) > 15
350                                 && !memcmp( buf, "NotDashEscaped:", 15 ) ) {
351                                 *not_dashed = 1;
352                                 state = fhdrWAITHeader;
353                             }
354                             else {
355                                 log_error(_("invalid clearsig header\n"));
356                                 state = fhdrERROR;
357                             }
358                         }
359                         else {
360                             state = fhdrWAITHeader;
361                             if( r_hashes )
362                                 *r_hashes |= hashes;
363                         }
364                     }
365                     else if( clearsig && n > 15 && !memcmp(buf, "-----", 5 ) )
366                         state = fhdrNullClearsig;
367                     else
368                         state = fhdrCHECKDashEscaped3;
369                 }
370                 else if( !n || (buf[0] == '\r' && !buf[1]) ) { /* empty line */
371                     if( clearsig )
372                         state = fhdrWAITClearsig;
373                     else {
374                         /* this is not really correct: if we do not have
375                          * a clearsig and no armor lines we are not allowed
376                          * to have an empty line */
377                         n = 0;
378                         state = fhdrTEXT;
379                     }
380                 }
381                 else {
382                     log_error(_("invalid armor header: "));
383                     print_string( stderr, buf, n, 0 );
384                     putc('\n', stderr);
385                     state = fhdrERROR;
386                 }
387             }
388             else if( c != -1 ) {
389                 if( strchr( buf, ':') ) { /* buffer to short, but this is okay*/
390                     if( opt.verbose ) {
391                         log_info(_("armor header: "));
392                         print_string( stderr, buf, n, 0 );
393                         fputs("[...]\n", stderr);  /* indicate it is truncated */
394                     }
395                     state = fhdrSKIPHeader;  /* skip rest of line */
396                 }
397                 else /* line too long */
398                     state = fhdrERROR;
399             }
400             else
401                 state = fhdrEOF;
402             break;
403
404           case fhdrWAITClearsig: /* skip the empty line (for clearsig) */
405             c = 0;
406             for(n=0; n < buflen && (c=iobuf_get(a)) != -1 && c != '\n'; )
407                 buf[n++] = c;
408             if( c != -1 ) {
409                 if( n > 15 && !memcmp(buf, "-----", 5 ) )
410                     state = fhdrNullClearsig;
411                 else if( c != '\n' )
412                     state = fhdrREADClearsigNext;
413                 else
414                     state = fhdrCHECKDashEscaped3;
415             }
416             else {
417                 /* fixme: we should check whether this line continues
418                  *   it is possible that we have only read ws until here
419                  *   and more stuff is to come */
420                 state = fhdrEOF;
421             }
422             break;
423
424           case fhdrNullClearsig: /* zero length cleartext */
425             state = fhdrENDClearsig;
426             break;
427
428           case fhdrENDClearsig:
429           case fhdrCHECKBegin:
430             state = state == fhdrCHECKBegin ? fhdrINITSkip : fhdrERRORShow;
431             if( n < 15 )
432                 break;  /* too short */
433             if( memcmp( buf, "-----", 5 ) )
434                 break;
435             buf[n] = 0;
436             p = strstr(buf+5, "-----");
437             if( !p )
438                 break;
439             *p = 0;
440             p += 5;
441             if( *p == '\r' )
442                 p++;
443             if( *p )
444                 break; /* garbage after dashes */
445             p = buf+5;
446             for(i=0; (s=head_strings[i]); i++ )
447                 if( !strcmp(s, p) )
448                     break;
449             if( !s )
450                 break; /* unknown begin line */
451             if( only_keyblocks && i != 1 && i != 5 && i != 6 )
452                 break; /* not a keyblock armor */
453
454             /* found the begin line */
455             hdr_line = i;
456             state = fhdrWAITHeader;
457             *not_dashed = 0;
458             if( hdr_line == BEGIN_SIGNED_MSG_IDX )
459                 clearsig = 1;
460             if( opt.verbose > 1 )
461                 log_info(_("armor: %s\n"), head_strings[hdr_line]);
462             break;
463
464           case fhdrCLEARSIGSimple:
465             /* we are at the begin of a new line */
466           case fhdrCLEARSIGSimpleNext:
467             n = 0;
468             c = 0;
469             while( n < buflen && (c=iobuf_get(a)) != -1 ) {
470                 buf[n++] = c;
471                 if( c == '\n' )
472                     break;
473             }
474             buf[n] = 0;
475             if( c == -1 )
476                 state = fhdrEOF;
477             else if( state == fhdrCLEARSIGSimple
478                      && n > 15 && !memcmp(buf, "-----", 5 ) ) {
479                 if( c == '\n' )
480                     buf[n-1] = 0;
481                 state = fhdrENDClearsig;
482             }
483             else if( c == '\n' )
484                 state = fhdrCLEARSIGSimple;
485             else
486                 state = fhdrCLEARSIGSimpleNext;
487             break;
488
489           case fhdrCLEARSIG:
490           case fhdrEMPTYClearsig:
491           case fhdrREADClearsig:
492             /* we are at the start of a line: read a clearsig into the buffer
493              * we have to look for a header line or dashed escaped text*/
494             n = 0;
495             c = 0;
496             while( n < buflen && (c=iobuf_get(a)) != -1 && c != '\n' )
497                 buf[n++] = c;
498             buf[n] = 0;
499             if( c == -1 )
500                 state = fhdrEOF;
501             else if( !n || ( buf[0]=='\r' && !buf[1] ) ) {
502                 state = fhdrEMPTYClearsig;
503                 empty++;
504             }
505             else if( c == '\n' )
506                 state = fhdrCHECKClearsig2;
507             else
508                 state = fhdrCHECKClearsig;
509             break;
510
511           case fhdrCHECKDashEscaped3:
512             if( *not_dashed ) {
513                 state = fhdrTEXTSimple;
514                 break;
515             }
516             if( !(n > 1 && buf[0] == '-' && buf[1] == ' ' ) ) {
517                 state = fhdrTEXT;
518                 break;
519             }
520             /* fall through */
521           case fhdrCHECKDashEscaped2:
522           case fhdrCHECKDashEscaped:
523             /* check dash escaped line */
524             if( buf[2] == '-' || ( n > 6 && !memcmp(buf+2, "From ", 5))) {
525                 for(i=2; i < n; i++ )
526                     buf[i-2] = buf[i];
527                 n -= 2;
528                 buf[n] = 0; /* not really needed */
529                 state = state == fhdrCHECKDashEscaped3 ? fhdrTEXT :
530                         state == fhdrCHECKDashEscaped2 ?
531                                  fhdrREADClearsig : fhdrTESTSpaces;
532             }
533             else {
534                 log_error(_("invalid dash escaped line: "));
535                 print_string( stderr, buf, n, 0 );
536                 putc('\n', stderr);
537                 state = fhdrERROR;
538             }
539             break;
540
541           case fhdrCHECKClearsig:
542             /* check the clearsig line */
543             if( n > 15 && !memcmp(buf, "-----", 5 ) )
544                 state = fhdrENDClearsig;
545             else if( buf[0] == '-' && buf[1] == ' ' && !*not_dashed )
546                 state = fhdrCHECKDashEscaped;
547             else {
548                 state = fhdrTESTSpaces;
549             }
550             break;
551
552           case fhdrCHECKClearsig2:
553             /* check the clearsig line */
554             if( n > 15 && !memcmp(buf, "-----", 5 ) )
555                 state = fhdrENDClearsig;
556             else if( buf[0] == '-' && buf[1] == ' ' && !*not_dashed )
557                 state = fhdrCHECKDashEscaped2;
558             else {
559                 state = fhdrREADClearsig;
560             }
561             break;
562
563           case fhdrREADClearsigNext:
564             /* Read to the end of the line, do not care about checking
565              * for dashed escaped text of headers */
566             c = 0;
567             n = 0;
568             while( n < buflen && (c=iobuf_get(a)) != -1 && c != '\n' )
569                 buf[n++] = c;
570             buf[n] = 0;
571             if( c == -1 )
572                 state = fhdrEOF;
573             else if( c == '\n' )
574                 state = fhdrREADClearsig;
575             else
576                 state = fhdrTESTSpaces;
577             break;
578
579           case fhdrTESTSpaces: {
580             /* but must check whether the rest of the line
581              * only contains white spaces; this is problematic
582              * since we may have to restore the stuff.  simply
583              * counting spaces is not enough, because it may be a
584              * mix of different white space characters */
585             IOBUF b = iobuf_temp();
586             while( (c=iobuf_get(a)) != -1 && c != '\n' ) {
587                 iobuf_put(b,c);
588                 if( c != ' ' && c != '\t' && c != '\r' )
589                     break;
590             }
591             if( c == '\n' ) {
592                 /* okay we can skip the rest of the line */
593                 iobuf_close(b);
594                 state = fhdrREADClearsig;
595             }
596             else {
597                 iobuf_unget_and_close_temp(a,b);
598                 state = fhdrREADClearsigNext;
599             }
600           } break;
601
602           case fhdrERRORShow:
603             log_error(_("invalid clear text header: "));
604             print_string( stderr, buf, n, 0 );
605             putc('\n', stderr);
606             state = fhdrERROR;
607             break;
608
609           default: BUG();
610         }
611         switch( state ) {
612           case fhdrINIT:
613           case fhdrINITCont:
614           case fhdrINITSkip:
615           case fhdrCHECKBegin:
616           case fhdrWAITHeader:
617           case fhdrWAITClearsig:
618           case fhdrSKIPHeader:
619           case fhdrEMPTYClearsig:
620           case fhdrCHECKClearsig:
621           case fhdrCHECKClearsig2:
622           case fhdrCHECKDashEscaped:
623           case fhdrCHECKDashEscaped2:
624           case fhdrCHECKDashEscaped3:
625           case fhdrTESTSpaces:
626           case fhdrERRORShow:
627             cont = 1;
628             break;
629           default: cont = 0;
630         }
631     } while( cont );
632
633     if( clearsig && state == fhdrTEXT )
634         state = fhdrCLEARSIG;
635     else if( clearsig && state == fhdrTEXTSimple ) {
636         state = fhdrCLEARSIGSimple;
637         buf[n] = '\n';
638         n++;
639     }
640
641     if( state == fhdrCLEARSIG || state == fhdrREADClearsig ) {
642         /* append CR,LF after removing trailing wspaces */
643         for(p=buf+n-1; n; n--, p-- ) {
644             assert( *p != '\n' );
645             if( *p != ' ' && *p != '\t' && *p != '\r' ) {
646                 p[1] = '\r';
647                 p[2] = '\n';
648                 n += 2;
649                 break;
650             }
651         }
652         if( !n ) {
653             buf[0] = '\r';
654             buf[1] = '\n';
655             n = 2;
656         }
657     }
658
659     *r_buflen = n;
660     *r_empty = empty;
661     return state;
662 }
663
664
665 /* figure out whether the data is armored or not */
666 static int
667 check_input( armor_filter_context_t *afx, IOBUF a )
668 {
669     int rc = 0;
670     size_t n;
671     fhdr_state_t state = afx->parse_state;
672     unsigned emplines;
673
674     if( state != fhdrENDClearsig )
675         state = fhdrHASArmor;
676
677     n = DIM(afx->helpbuf);
678     state = find_header( state, afx->helpbuf, &n, a,
679                                 afx->helplen, &emplines, &afx->hashes,
680                                 afx->only_keyblocks, &afx->not_dash_escaped );
681     switch( state ) {
682       case fhdrNOArmor:
683         afx->inp_checked = 1;
684         afx->inp_bypass = 1;
685         afx->helplen = n;
686         break;
687
688       case fhdrERROR:
689         invalid_armor();
690         break;
691
692       case fhdrEOF:
693         rc = -1;
694         break;
695
696       case fhdrNullClearsig:
697       case fhdrCLEARSIG: /* start fake package mode (for clear signatures) */
698       case fhdrREADClearsigNext:
699       case fhdrCLEARSIGSimple:
700       case fhdrCLEARSIGSimpleNext:
701         afx->helplen = n;
702         afx->helpidx = 0;
703         afx->faked = 1;
704         break;
705
706       case fhdrTEXT:
707         afx->helplen = n;
708         afx->helpidx = 0;
709         afx->inp_checked = 1;
710         afx->crc = CRCINIT;
711         afx->idx = 0;
712         afx->radbuf[0] = 0;
713         break;
714
715       default: BUG();
716     }
717
718     afx->parse_state = state;
719     return rc;
720 }
721
722
723
724 /* fake a literal data packet and wait for an armor line */
725 static int
726 fake_packet( armor_filter_context_t *afx, IOBUF a,
727              size_t *retn, byte *buf, size_t size  )
728 {
729     int rc = 0;
730     size_t len = 0;
731     size_t n, nn;
732     fhdr_state_t state = afx->parse_state;
733     unsigned emplines = afx->empty;
734
735     len = 2;    /* reserve 2 bytes for the length header */
736     size -= 3;  /* and 1 for empline handling and 2 for the term header */
737     while( !rc && len < size ) {
738         if( emplines ) {
739             while( emplines && len < size ) {
740                 buf[len++] = '\r';
741                 buf[len++] = '\n';
742                 emplines--;
743             }
744             continue;
745         }
746         if( state == fhdrENDClearsigHelp ) {
747             state = fhdrENDClearsig;
748             afx->faked = 0;
749             rc = -1;
750             continue;
751         }
752         if( state != fhdrNullClearsig
753             && afx->helpidx < afx->helplen ) { /* flush the last buffer */
754             n = afx->helplen;
755             for(nn=afx->helpidx; len < size && nn < n ; nn++ )
756                 buf[len++] = afx->helpbuf[nn];
757             afx->helpidx = nn;
758             continue;
759         }
760         if( state == fhdrEOF ) {
761             rc = -1;
762             continue;
763         }
764         /* read a new one */
765         n = DIM(afx->helpbuf);
766         afx->helpidx = 0;
767         state = find_header( state, afx->helpbuf, &n, a,
768                               state == fhdrNullClearsig? afx->helplen:0,
769                                                 &emplines, &afx->hashes,
770                                                 afx->only_keyblocks,
771                                                 &afx->not_dash_escaped );
772         switch( state) {
773           case fhdrERROR:
774             invalid_armor();
775             break;
776
777           case fhdrEOF:
778             rc = -1;
779             break;
780
781           case fhdrCLEARSIG:
782             BUG();
783
784           case fhdrREADClearsig:
785           case fhdrREADClearsigNext:
786           case fhdrCLEARSIGSimple:
787           case fhdrCLEARSIGSimpleNext:
788             afx->helplen = n;
789             break;
790
791           case fhdrENDClearsig:
792             state = fhdrENDClearsigHelp;
793             afx->helplen = n;
794             break;
795
796           default: BUG();
797         }
798     }
799     buf[0] = (len-2) >> 8;
800     buf[1] = (len-2);
801     if( state == fhdrENDClearsig ) { /* write last (ending) length header */
802         if( buf[0] || buf[1] ) { /* write only if length of text is > 0 */
803             buf[len++] = 0;
804             buf[len++] = 0;
805         }
806         rc = 0;
807     }
808
809     afx->parse_state = state;
810     afx->empty = emplines;
811     *retn = len;
812     return rc;
813 }
814
815
816
817 static int
818 radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
819               byte *buf, size_t size )
820 {
821     byte val;
822     int c, c2;
823     int checkcrc=0;
824     int rc = 0;
825     size_t n = 0;
826     int  idx, i;
827     u32 crc;
828
829     crc = afx->crc;
830     idx = afx->idx;
831     val = afx->radbuf[0];
832     for( n=0; n < size; ) {
833         if( afx->helpidx < afx->helplen )
834             c = afx->helpbuf[afx->helpidx++];
835         else if( (c=iobuf_get(a)) == -1 )
836             break;
837         if( c == '\n' || c == ' ' || c == '\r' || c == '\t' )
838             continue;
839         else if( c == '=' ) { /* pad character: stop */
840             if( idx == 1 )
841                 buf[n++] = val;
842             checkcrc++;
843             break;
844         }
845         else if( (c = asctobin[(c2=c)]) == 255 ) {
846             log_error(_("invalid radix64 character %02x skipped\n"), c2);
847             continue;
848         }
849         switch(idx) {
850           case 0: val =  c << 2; break;
851           case 1: val |= (c>>4)&3; buf[n++]=val;val=(c<<4)&0xf0;break;
852           case 2: val |= (c>>2)&15; buf[n++]=val;val=(c<<6)&0xc0;break;
853           case 3: val |= c&0x3f; buf[n++] = val; break;
854         }
855         idx = (idx+1) % 4;
856     }
857     for(i=0; i < n; i++ )
858         crc = (crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ buf[i]];
859     crc &= 0x00ffffff;
860     afx->crc = crc;
861     afx->idx = idx;
862     afx->radbuf[0] = val;
863     if( checkcrc ) {
864         afx->any_data = 1;
865         afx->inp_checked=0;
866         afx->faked = 0;
867         afx->parse_state = 0;
868         for(;;) { /* skip lf and pad characters */
869             if( afx->helpidx < afx->helplen )
870                 c = afx->helpbuf[afx->helpidx++];
871             else if( (c=iobuf_get(a)) == -1 )
872                 break;
873             if( c == '\n' || c == ' ' || c == '\r'
874                 || c == '\t' || c == '=' )
875                 continue;
876             break;
877         }
878         if( c == -1 )
879             log_error(_("premature eof (no CRC)\n"));
880         else {
881             u32 mycrc = 0;
882             idx = 0;
883             do {
884                 if( (c = asctobin[c]) == 255 )
885                     break;
886                 switch(idx) {
887                   case 0: val =  c << 2; break;
888                   case 1: val |= (c>>4)&3; mycrc |= val << 16;val=(c<<4)&0xf0;break;
889                   case 2: val |= (c>>2)&15; mycrc |= val << 8;val=(c<<6)&0xc0;break;
890                   case 3: val |= c&0x3f; mycrc |= val; break;
891                 }
892                 if( afx->helpidx < afx->helplen )
893                     c = afx->helpbuf[afx->helpidx++];
894                 else if( (c=iobuf_get(a)) == -1 )
895                     break;
896             } while( ++idx < 4 );
897             if( c == -1 ) {
898                 log_error(_("premature eof (in CRC)\n"));
899                 rc = G10ERR_INVALID_ARMOR;
900             }
901             else if( idx != 4 ) {
902                 log_error(_("malformed CRC\n"));
903                 rc = G10ERR_INVALID_ARMOR;
904             }
905             else if( mycrc != afx->crc ) {
906                 log_error(_("CRC error; %06lx - %06lx\n"),
907                                     (ulong)afx->crc, (ulong)mycrc);
908                 rc = G10ERR_INVALID_ARMOR;
909             }
910             else {
911                 rc = 0;
912               #if 0
913                 for(rc=0;!rc;) {
914                     rc = 0 /*check_trailer( &fhdr, c )*/;
915                     if( !rc ) {
916                         if( afx->helpidx < afx->helplen )
917                             c = afx->helpbuf[afx->helpidx++];
918                         else if( (c=iobuf_get(a)) == -1 )
919                             rc = 2;
920                     }
921                 }
922                 if( rc == -1 )
923                     rc = 0;
924                 else if( rc == 2 ) {
925                     log_error(_("premature eof (in Trailer)\n"));
926                     rc = G10ERR_INVALID_ARMOR;
927                 }
928                 else {
929                     log_error(_("error in trailer line\n"));
930                     rc = G10ERR_INVALID_ARMOR;
931                 }
932               #endif
933             }
934         }
935     }
936
937     if( !n )
938         rc = -1;
939
940     *retn = n;
941     return rc;
942 }
943
944 /****************
945  * This filter is used to handle the armor stuff
946  */
947 int
948 armor_filter( void *opaque, int control,
949              IOBUF a, byte *buf, size_t *ret_len)
950 {
951     size_t size = *ret_len;
952     armor_filter_context_t *afx = opaque;
953     int rc=0, i, c;
954     byte radbuf[3];
955     int  idx, idx2;
956     size_t n=0;
957     u32 crc;
958   #if 0
959     static FILE *fp ;
960
961     if( !fp ) {
962         fp = fopen("armor.out", "w");
963         assert(fp);
964     }
965   #endif
966
967     if( DBG_FILTER )
968         log_debug("armor-filter: control: %d\n", control );
969     if( control == IOBUFCTRL_UNDERFLOW && afx->inp_bypass ) {
970         for( n=0; n < size; n++ ) {
971             if( (c=iobuf_get(a)) == -1 )
972                 break;
973             buf[n] = c & 0xff;
974         }
975         if( !n )
976             rc = -1;
977         *ret_len = n;
978     }
979     else if( control == IOBUFCTRL_UNDERFLOW ) {
980         if( size < 15+(4*15) )  /* need space for up to 4 onepass_sigs */
981             BUG(); /* supplied buffer too short */
982
983         if( afx->faked )
984             rc = fake_packet( afx, a, &n, buf, size );
985         else if( !afx->inp_checked ) {
986             rc = check_input( afx, a );
987             if( afx->inp_bypass ) {
988                 for( n=0; n < size && n < afx->helplen; n++ )
989                     buf[n] = afx->helpbuf[n];
990                 if( !n )
991                     rc = -1;
992                 assert( n == afx->helplen );
993                 afx->helplen = 0;
994             }
995             else if( afx->faked ) {
996                 unsigned hashes = afx->hashes;
997                 /* the buffer is at least 15+n*15 bytes long, so it
998                  * is easy to construct the packets */
999
1000                 hashes &= 1|2|4|8;
1001                 if( !hashes )
1002                     hashes |= 4;  /* default to MD 5 */
1003                 n=0;
1004                 do {
1005                     /* first some onepass signature packets */
1006                     buf[n++] = 0x90; /* old format, type 4, 1 length byte */
1007                     buf[n++] = 13;   /* length */
1008                     buf[n++] = 3;    /* version */
1009                     buf[n++] = 0x01; /* sigclass 0x01 (canonical text mode)*/
1010                     if( hashes & 1 ) {
1011                         hashes &= ~1;
1012                         buf[n++] = DIGEST_ALGO_RMD160;
1013                     }
1014                     else if( hashes & 2 ) {
1015                         hashes &= ~2;
1016                         buf[n++] = DIGEST_ALGO_SHA1;
1017                     }
1018                     else if( hashes & 4 ) {
1019                         hashes &= ~4;
1020                         buf[n++] = DIGEST_ALGO_MD5;
1021                     }
1022                     else if( hashes & 8 ) {
1023                         hashes &= ~8;
1024                         buf[n++] = DIGEST_ALGO_TIGER;
1025                     }
1026                     else
1027                         buf[n++] = 0;    /* (don't know) */
1028
1029                     buf[n++] = 0;    /* public key algo (don't know) */
1030                     memset(buf+n, 0, 8); /* don't know the keyid */
1031                     n += 8;
1032                     buf[n++] = !hashes;   /* last one */
1033                 } while( hashes );
1034
1035                 /* followed by a plaintext packet */
1036                 buf[n++] = 0xaf; /* old packet format, type 11, var length */
1037                 buf[n++] = 0;    /* set the length header */
1038                 buf[n++] = 6;
1039                 buf[n++] = 't';  /* canonical text mode */
1040                 buf[n++] = 0;    /* namelength */
1041                 memset(buf+n, 0, 4); /* timestamp */
1042                 n += 4;
1043             }
1044             else if( !rc )
1045                 rc = radix64_read( afx, a, &n, buf, size );
1046         }
1047         else
1048             rc = radix64_read( afx, a, &n, buf, size );
1049       #if 0
1050         if( n )
1051             if( fwrite(buf, n, 1, fp ) != 1 )
1052                 BUG();
1053       #endif
1054         *ret_len = n;
1055     }
1056     else if( control == IOBUFCTRL_FLUSH ) {
1057         if( !afx->status ) { /* write the header line */
1058             if( afx->what >= DIM(head_strings) )
1059                 log_bug("afx->what=%d", afx->what);
1060             iobuf_writestr(a, "-----");
1061             iobuf_writestr(a, head_strings[afx->what] );
1062             iobuf_writestr(a, "-----\n");
1063             iobuf_writestr(a, "Version: GnuPG v"  VERSION " ("
1064                                             PRINTABLE_OS_NAME ")\n");
1065
1066             if( opt.comment_string ) {
1067                 const char *s = opt.comment_string;
1068                 iobuf_writestr(a, "Comment: " );
1069                 for( ; *s; s++ ) {
1070                     if( *s == '\n' )
1071                         iobuf_writestr(a, "\\n" );
1072                     else if( *s == '\r' )
1073                         iobuf_writestr(a, "\\r" );
1074                     else if( *s == '\v' )
1075                         iobuf_writestr(a, "\\v" );
1076                     else
1077                         iobuf_put(a, *s );
1078                 }
1079                 iobuf_put(a, '\n' );
1080             }
1081             else
1082                 iobuf_writestr(a,
1083                     "Comment: For info see www.gnupg.org");
1084             if( afx->hdrlines )
1085                 iobuf_writestr(a, afx->hdrlines);
1086             iobuf_put(a, '\n');
1087             afx->status++;
1088             afx->idx = 0;
1089             afx->idx2 = 0;
1090             afx->crc = CRCINIT;
1091         }
1092         crc = afx->crc;
1093         idx = afx->idx;
1094         idx2 = afx->idx2;
1095         for(i=0; i < idx; i++ )
1096             radbuf[i] = afx->radbuf[i];
1097
1098         for(i=0; i < size; i++ )
1099             crc = (crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ buf[i]];
1100         crc &= 0x00ffffff;
1101
1102         for( ; size; buf++, size-- ) {
1103             radbuf[idx++] = *buf;
1104             if( idx > 2 ) {
1105                 idx = 0;
1106                 c = bintoasc[(*radbuf >> 2) & 077];
1107                 iobuf_put(a, c);
1108                 c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
1109                 iobuf_put(a, c);
1110                 c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
1111                 iobuf_put(a, c);
1112                 c = bintoasc[radbuf[2]&077];
1113                 iobuf_put(a, c);
1114                 if( ++idx2 >= (64/4) ) { /* pgp doesn't like 72 here */
1115                     iobuf_put(a, '\n');
1116                     idx2=0;
1117                 }
1118             }
1119         }
1120         for(i=0; i < idx; i++ )
1121             afx->radbuf[i] = radbuf[i];
1122         afx->idx = idx;
1123         afx->idx2 = idx2;
1124         afx->crc  = crc;
1125     }
1126     else if( control == IOBUFCTRL_INIT ) {
1127         if( !is_initialized )
1128             initialize();
1129     }
1130     else if( control == IOBUFCTRL_FREE ) {
1131         if( afx->status ) { /* pad, write cecksum, and bottom line */
1132             crc = afx->crc;
1133             idx = afx->idx;
1134             idx2 = afx->idx2;
1135             for(i=0; i < idx; i++ )
1136                 radbuf[i] = afx->radbuf[i];
1137             if( idx ) {
1138                 c = bintoasc[(*radbuf>>2)&077];
1139                 iobuf_put(a, c);
1140                 if( idx == 1 ) {
1141                     c = bintoasc[((*radbuf << 4) & 060) & 077];
1142                     iobuf_put(a, c);
1143                     iobuf_put(a, '=');
1144                     iobuf_put(a, '=');
1145                 }
1146                 else { /* 2 */
1147                     c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1]>>4)&017))&077];
1148                     iobuf_put(a, c);
1149                     c = bintoasc[((radbuf[1] << 2) & 074) & 077];
1150                     iobuf_put(a, c);
1151                     iobuf_put(a, '=');
1152                 }
1153                 if( ++idx2 >= (64/4) ) { /* pgp doesn't like 72 here */
1154                     iobuf_put(a, '\n');
1155                     idx2=0;
1156                 }
1157             }
1158             /* may need a linefeed */
1159             if( idx2 )
1160                 iobuf_put(a, '\n');
1161             /* write the CRC */
1162             iobuf_put(a, '=');
1163             radbuf[0] = crc >>16;
1164             radbuf[1] = crc >> 8;
1165             radbuf[2] = crc;
1166             c = bintoasc[(*radbuf >> 2) & 077];
1167             iobuf_put(a, c);
1168             c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
1169             iobuf_put(a, c);
1170             c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
1171             iobuf_put(a, c);
1172             c = bintoasc[radbuf[2]&077];
1173             iobuf_put(a, c);
1174             iobuf_put(a, '\n');
1175             /* and the the trailer */
1176             if( afx->what >= DIM(tail_strings) )
1177                 log_bug("afx->what=%d", afx->what);
1178             iobuf_writestr(a, "-----");
1179             iobuf_writestr(a, tail_strings[afx->what] );
1180             iobuf_writestr(a, "-----\n");
1181         }
1182         else if( !afx->any_data && !afx->inp_bypass )
1183             log_error(_("no valid OpenPGP data found.\n"));
1184     }
1185     else if( control == IOBUFCTRL_DESC )
1186         *(char**)buf = "armor_filter";
1187     return rc;
1188 }
1189
1190
1191