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