See ChangeLog: Tue Dec 29 14:41:47 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     do {
283         switch( state ) {
284           case fhdrHASArmor:
285             /* read at least the first byte to check whether it is armored
286              * or not */
287             c = 0;
288             for(n=0; n < 28 && (c=iobuf_get(a)) != -1 && c != '\n'; )
289                 buf[n++] = c;
290             if( !n && c == '\n' )
291                 state = fhdrCHECKBegin;
292             else if( !n  || c == -1 )
293                 state = fhdrNOArmor; /* too short */
294             else if( !is_armored( buf ) ) {
295                 state = fhdrNOArmor;
296                 if( c == '\n' )
297                     buf[n++] = c;
298             }
299             else if( c == '\n' )
300                 state = fhdrCHECKBegin;
301             else
302                 state = fhdrINITCont;
303             break;
304
305           case fhdrINIT: /* read some stuff into buffer */
306             n = 0;
307           case fhdrINITCont: /* read more stuff into buffer */
308             c = 0;
309             for(; n < buflen && (c=iobuf_get(a)) != -1 && c != '\n'; )
310                 buf[n++] = c;
311             state = c == '\n' ? fhdrCHECKBegin :
312                      c == -1  ? fhdrEOF : fhdrINITSkip;
313             break;
314
315           case fhdrINITSkip:
316             if( c == '\n' )
317                 n = 0;
318             else {
319                 while( (c=iobuf_get(a)) != -1 && c != '\n' )
320                     ;
321             }
322             state =  c == -1? fhdrEOF : fhdrINIT;
323             break;
324
325           case fhdrSKIPHeader:
326             while( (c=iobuf_get(a)) != -1 && c != '\n' )
327                 ;
328             state =  c == -1? fhdrEOF : fhdrWAITHeader;
329             break;
330
331           case fhdrWAITHeader: /* wait for Header lines */
332             c = 0;
333             for(n=0; n < buflen && (c=iobuf_get(a)) != -1 && c != '\n'; )
334                 buf[n++] = c;
335             buf[n] = 0;
336             if( n < buflen || c == '\n' ) {
337                 if( n && buf[0] != '\r') { /* maybe a header */
338                     if( strchr( buf, ':') ) { /* yes */
339                         int hashes=0;
340                         if( buf[n-1] == '\r' )
341                             buf[--n] = 0;
342                         if( opt.verbose ) {
343                             log_info(_("armor header: "));
344                             print_string( stderr, buf, n, 0 );
345                             putc('\n', stderr);
346                         }
347                         if( clearsig && !(hashes=parse_hash_header( buf )) ) {
348                             if( strlen(buf) > 15
349                                 && !memcmp( buf, "NotDashEscaped:", 15 ) ) {
350                                 *not_dashed = 1;
351                                 state = fhdrWAITHeader;
352                             }
353                             else {
354                                 log_error(_("invalid clearsig header\n"));
355                                 state = fhdrERROR;
356                             }
357                         }
358                         else {
359                             state = fhdrWAITHeader;
360                             if( r_hashes )
361                                 *r_hashes |= hashes;
362                         }
363                     }
364                     else if( clearsig && n > 15 && !memcmp(buf, "-----", 5 ) )
365                         state = fhdrNullClearsig;
366                     else
367                         state = fhdrCHECKDashEscaped3;
368                 }
369                 else if( !n || (buf[0] == '\r' && !buf[1]) ) { /* empty line */
370                     if( clearsig )
371                         state = fhdrWAITClearsig;
372                     else {
373                         /* this is not really correct: if we do not have
374                          * a clearsig and no armor lines we are not allowed
375                          * to have an empty line */
376                         n = 0;
377                         state = fhdrTEXT;
378                     }
379                 }
380                 else {
381                     log_error(_("invalid armor header: "));
382                     print_string( stderr, buf, n, 0 );
383                     putc('\n', stderr);
384                     state = fhdrERROR;
385                 }
386             }
387             else if( c != -1 ) {
388                 if( strchr( buf, ':') ) { /* buffer to short, but this is okay*/
389                     if( opt.verbose ) {
390                         log_info(_("armor header: "));
391                         print_string( stderr, buf, n, 0 );
392                         fputs("[...]\n", stderr);  /* indicate it is truncated */
393                     }
394                     state = fhdrSKIPHeader;  /* skip rest of line */
395                 }
396                 else /* line too long */
397                     state = fhdrERROR;
398             }
399             else
400                 state = fhdrEOF;
401             break;
402
403           case fhdrWAITClearsig: /* skip the empty line (for clearsig) */
404             c = 0;
405             for(n=0; n < buflen && (c=iobuf_get(a)) != -1 && c != '\n'; )
406                 buf[n++] = c;
407             if( c != -1 ) {
408                 if( n > 15 && !memcmp(buf, "-----", 5 ) )
409                     state = fhdrNullClearsig;
410                 else if( c != '\n' )
411                     state = fhdrREADClearsigNext;
412                 else
413                     state = fhdrCHECKDashEscaped3;
414             }
415             else {
416                 /* fixme: we should check whether this line continues
417                  *   it is possible that we have only read ws until here
418                  *   and more stuff is to come */
419                 state = fhdrEOF;
420             }
421             break;
422
423           case fhdrNullClearsig: /* zero length cleartext */
424             state = fhdrENDClearsig;
425             break;
426
427           case fhdrENDClearsig:
428           case fhdrCHECKBegin:
429             state = state == fhdrCHECKBegin ? fhdrINITSkip : fhdrERRORShow;
430             if( n < 15 )
431                 break;  /* too short */
432             if( memcmp( buf, "-----", 5 ) )
433                 break;
434             buf[n] = 0;
435             p = strstr(buf+5, "-----");
436             if( !p )
437                 break;
438             *p = 0;
439             p += 5;
440             if( *p == '\r' )
441                 p++;
442             if( *p )
443                 break; /* garbage after dashes */
444             p = buf+5;
445             for(i=0; (s=head_strings[i]); i++ )
446                 if( !strcmp(s, p) )
447                     break;
448             if( !s )
449                 break; /* unknown begin line */
450             if( only_keyblocks && i != 1 && i != 5 && i != 6 )
451                 break; /* not a keyblock armor */
452
453             /* found the begin line */
454             hdr_line = i;
455             state = fhdrWAITHeader;
456             *not_dashed = 0;
457             if( hdr_line == BEGIN_SIGNED_MSG_IDX )
458                 clearsig = 1;
459             if( opt.verbose > 1 )
460                 log_info(_("armor: %s\n"), head_strings[hdr_line]);
461             break;
462
463           case fhdrCLEARSIGSimple:
464             /* we are at the begin of a new line */
465           case fhdrCLEARSIGSimpleNext:
466             n = 0;
467             c = 0;
468             while( n < buflen && (c=iobuf_get(a)) != -1 ) {
469                 buf[n++] = c;
470                 if( c == '\n' )
471                     break;
472             }
473             buf[n] = 0;
474             if( c == -1 )
475                 state = fhdrEOF;
476             else if( state == fhdrCLEARSIGSimple
477                      && n > 15 && !memcmp(buf, "-----", 5 ) ) {
478                 if( c == '\n' )
479                     buf[n-1] = 0;
480                 state = fhdrENDClearsig;
481             }
482             else if( c == '\n' )
483                 state = fhdrCLEARSIGSimple;
484             else
485                 state = fhdrCLEARSIGSimpleNext;
486             break;
487
488           case fhdrCLEARSIG:
489           case fhdrEMPTYClearsig:
490           case fhdrREADClearsig:
491             /* we are at the start of a line: read a clearsig into the buffer
492              * we have to look for a header line or dashed escaped text*/
493             n = 0;
494             c = 0;
495             while( n < buflen && (c=iobuf_get(a)) != -1 && c != '\n' )
496                 buf[n++] = c;
497             buf[n] = 0;
498             if( c == -1 )
499                 state = fhdrEOF;
500             else if( !n || ( buf[0]=='\r' && !buf[1] ) ) {
501                 state = fhdrEMPTYClearsig;
502                 empty++;
503             }
504             else if( c == '\n' )
505                 state = fhdrCHECKClearsig2;
506             else
507                 state = fhdrCHECKClearsig;
508             break;
509
510           case fhdrCHECKDashEscaped3:
511             if( *not_dashed ) {
512                 state = fhdrTEXTSimple;
513                 break;
514             }
515             if( !(n > 1 && buf[0] == '-' && buf[1] == ' ' ) ) {
516                 state = fhdrTEXT;
517                 break;
518             }
519             /* fall through */
520           case fhdrCHECKDashEscaped2:
521           case fhdrCHECKDashEscaped:
522             /* check dash escaped line */
523             if( buf[2] == '-' || ( n > 6 && !memcmp(buf+2, "From ", 5))) {
524                 for(i=2; i < n; i++ )
525                     buf[i-2] = buf[i];
526                 n -= 2;
527                 buf[n] = 0; /* not really needed */
528                 state = state == fhdrCHECKDashEscaped3 ? fhdrTEXT :
529                         state == fhdrCHECKDashEscaped2 ?
530                                  fhdrREADClearsig : fhdrTESTSpaces;
531             }
532             else {
533                 log_error(_("invalid dash escaped line: "));
534                 print_string( stderr, buf, n, 0 );
535                 putc('\n', stderr);
536                 state = fhdrERROR;
537             }
538             break;
539
540           case fhdrCHECKClearsig:
541             /* check the clearsig line */
542             if( n > 15 && !memcmp(buf, "-----", 5 ) )
543                 state = fhdrENDClearsig;
544             else if( buf[0] == '-' && buf[1] == ' ' && !*not_dashed )
545                 state = fhdrCHECKDashEscaped;
546             else {
547                 state = fhdrTESTSpaces;
548             }
549             break;
550
551           case fhdrCHECKClearsig2:
552             /* check the clearsig line */
553             if( n > 15 && !memcmp(buf, "-----", 5 ) )
554                 state = fhdrENDClearsig;
555             else if( buf[0] == '-' && buf[1] == ' ' && !*not_dashed )
556                 state = fhdrCHECKDashEscaped2;
557             else {
558                 state = fhdrREADClearsig;
559             }
560             break;
561
562           case fhdrREADClearsigNext:
563             /* Read to the end of the line, do not care about checking
564              * for dashed escaped text of headers */
565             c = 0;
566             n = 0;
567             while( n < buflen && (c=iobuf_get(a)) != -1 && c != '\n' )
568                 buf[n++] = c;
569             buf[n] = 0;
570             if( c == -1 )
571                 state = fhdrEOF;
572             else if( c == '\n' )
573                 state = fhdrREADClearsig;
574             else
575                 state = fhdrTESTSpaces;
576             break;
577
578           case fhdrTESTSpaces: {
579             /* but must check whether the rest of the line
580              * only contains white spaces; this is problematic
581              * since we may have to restore the stuff.  simply
582              * counting spaces is not enough, because it may be a
583              * mix of different white space characters */
584             IOBUF b = iobuf_temp();
585             while( (c=iobuf_get(a)) != -1 && c != '\n' ) {
586                 iobuf_put(b,c);
587                 if( c != ' ' && c != '\t' && c != '\r' )
588                     break;
589             }
590             if( c == '\n' ) {
591                 /* okay we can skip the rest of the line */
592                 iobuf_close(b);
593                 state = fhdrREADClearsig;
594             }
595             else {
596                 iobuf_unget_and_close_temp(a,b);
597                 state = fhdrREADClearsigNext;
598             }
599           } break;
600
601           case fhdrERRORShow:
602             log_error(_("invalid clear text header: "));
603             print_string( stderr, buf, n, 0 );
604             putc('\n', stderr);
605             state = fhdrERROR;
606             break;
607
608           default: BUG();
609         }
610         switch( state ) {
611           case fhdrINIT:
612           case fhdrINITCont:
613           case fhdrINITSkip:
614           case fhdrCHECKBegin:
615           case fhdrWAITHeader:
616           case fhdrWAITClearsig:
617           case fhdrSKIPHeader:
618           case fhdrEMPTYClearsig:
619           case fhdrCHECKClearsig:
620           case fhdrCHECKClearsig2:
621           case fhdrCHECKDashEscaped:
622           case fhdrCHECKDashEscaped2:
623           case fhdrCHECKDashEscaped3:
624           case fhdrTESTSpaces:
625           case fhdrERRORShow:
626             cont = 1;
627             break;
628           default: cont = 0;
629         }
630     } while( cont );
631
632     if( clearsig && state == fhdrTEXT ) {
633         state = fhdrCLEARSIG;
634     }
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 http://www.gnupg.org\n");
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