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