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