See ChangeLog: Sun Jan 10 19:36:42 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 "iobuf.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 static unsigned
260 trim_trailing_spaces( byte *line, unsigned len )
261 {
262     byte *p, *mark;
263     unsigned n;
264
265     for(mark=NULL, p=line, n=0; n < len; n++, p++ ) {
266         if( strchr(" \t\r\n", *p ) ) {
267             if( !mark )
268                 mark = p;
269         }
270         else
271             mark = NULL;
272     }
273
274     if( mark ) {
275         *mark = 0;
276         return mark - line;
277     }
278     return len;
279 }
280
281
282
283 /****************
284  * Check whether this is a armor line.
285  * returns: -1 if it is not a armor header or the index number of the
286  * armor header.
287  */
288 static int
289 is_armor_header( byte *line, unsigned len )
290 {
291     const char *s;
292     byte *save_p, *p;
293     int save_c;
294     int i;
295
296     if( len < 15 )
297         return -1; /* too short */
298     if( memcmp( line, "-----", 5 ) )
299         return -1; /* no */
300     p = strstr( line+5, "-----");
301     if( !p )
302         return -1;
303     save_p = p;
304     p += 5;
305     if( *p == '\r' )
306         p++;
307     if( *p == '\n' )
308         p++;
309     if( *p )
310         return -1; /* garbage after dashes */
311     save_c = *save_p; *save_p = 0;
312     p = line+5;
313     for(i=0; (s=head_strings[i]); i++ )
314         if( !strcmp(s, p) )
315             break;
316     *save_p = save_c;
317     if( !s )
318         return -1; /* unknown armor line */
319
320     if( opt.verbose > 1 )
321         log_info(_("armor: %s\n"), head_strings[i]);
322     return i;
323 }
324
325
326
327 /****************
328  * Parse a header lines
329  * Return 0: Empty line (end of header lines)
330  *       -1: invalid header line
331  *       >0: Good header line
332  */
333 static int
334 parse_header_line( armor_filter_context_t *afx, byte *line, unsigned len )
335 {
336     byte *p;
337     int hashes=0;
338
339     if( *line == '\n' || ( len && (*line == '\r' && line[1]=='\n') ) )
340         return 0; /* empty line */
341     len = trim_trailing_spaces( line, len );
342     p = strchr( line, ':');
343     if( !p || !p[1] ) {
344         log_error(_("invalid armor header: "));
345         print_string( stderr, line, len, 0 );
346         putc('\n', stderr);
347         return -1;
348     }
349
350     if( opt.verbose ) {
351         log_info(_("armor header: "));
352         print_string( stderr, line, len, 0 );
353         putc('\n', stderr);
354     }
355
356     if( afx->in_cleartext ) {
357         if( (hashes=parse_hash_header( line )) )
358             afx->hashes |= hashes;
359         else if( strlen(line) > 15 && !memcmp( line, "NotDashEscaped:", 15 ) )
360             afx->not_dash_escaped = 1;
361         else {
362             log_error(_("invalid clearsig header\n"));
363             return -1;
364         }
365     }
366     return 1;
367 }
368
369
370
371 /* figure out whether the data is armored or not */
372 static int
373 check_input( armor_filter_context_t *afx, IOBUF a )
374 {
375     int rc = 0;
376     int i;
377     byte *line;
378     unsigned len;
379     unsigned maxlen;
380     int hdr_line = -1;
381
382     /* read the first line to see whether this is armored data */
383     maxlen = MAX_LINELEN;
384     len = afx->buffer_len = iobuf_read_line( a, &afx->buffer,
385                                              &afx->buffer_size, &maxlen );
386     line = afx->buffer;
387     if( !maxlen ) {
388         /* line has been truncated: assume not armored */
389         afx->inp_checked = 1;
390         afx->inp_bypass = 1;
391         return 0;
392     }
393
394     if( !len ) {
395         return -1; /* eof */
396     }
397
398     /* (the line is always a C string but maybe longer) */
399     if( *line == '\n' || ( len && (*line == '\r' && line[1]=='\n') ) )
400         ;
401     else if( !is_armored( line ) ) {
402         afx->inp_checked = 1;
403         afx->inp_bypass = 1;
404         return 0;
405     }
406
407     /* find the armor header */
408     while(len) {
409         i = is_armor_header( line, len );
410         if( i >= 0 && !(afx->only_keyblocks && i != 1 && i != 5 && i != 6 )) {
411             hdr_line = i;
412             if( hdr_line == BEGIN_SIGNED_MSG_IDX ) {
413                 if( afx->in_cleartext ) {
414                     log_error(_("nested clear text signatures\n"));
415                     rc = G10ERR_INVALID_ARMOR;
416                 }
417                 afx->in_cleartext = 1;
418             }
419             break;
420         }
421         /* read the next line (skip all truncated lines) */
422         do {
423             maxlen = MAX_LINELEN;
424             afx->buffer_len = iobuf_read_line( a, &afx->buffer,
425                                                &afx->buffer_size, &maxlen );
426             line = afx->buffer;
427             len = afx->buffer_len;
428         } while( !maxlen );
429     }
430
431     /* parse the header lines */
432     while(len) {
433         /* read the next line (skip all truncated lines) */
434         do {
435             maxlen = MAX_LINELEN;
436             afx->buffer_len = iobuf_read_line( a, &afx->buffer,
437                                                &afx->buffer_size, &maxlen );
438             line = afx->buffer;
439             len = afx->buffer_len;
440         } while( !maxlen );
441
442         i = parse_header_line( afx, line, len );
443         if( i <= 0 ) {
444             if( i )
445                 rc = G10ERR_INVALID_ARMOR;
446             break;
447         }
448     }
449
450
451     if( rc )
452         invalid_armor();
453     else if( afx->in_cleartext ) {
454         afx->faked = 1;
455     }
456     else {
457         afx->inp_checked = 1;
458         afx->crc = CRCINIT;
459         afx->idx = 0;
460         afx->radbuf[0] = 0;
461     }
462
463     return rc;
464 }
465
466
467
468 /****************
469  * Fake a literal data packet and wait for the next armor line
470  * fixme: empty line handling and null length clear text signature are
471  *        not implemented/checked.
472  */
473 static int
474 fake_packet( armor_filter_context_t *afx, IOBUF a,
475              size_t *retn, byte *buf, size_t size  )
476 {
477     int rc = 0;
478     size_t len = 0;
479     unsigned emplines = afx->empty;
480     int lastline = 0;
481     unsigned maxlen, n;
482     byte *p;
483
484     len = 2;    /* reserve 2 bytes for the length header */
485     size -= 3;  /* and 1 for empline handling and 2 for the term header */
486                 /* or the appended CR,LF */
487     while( !rc && len < size ) {
488         if( emplines ) {
489             while( emplines && len < size ) {
490                 buf[len++] = '\r';
491                 buf[len++] = '\n';
492                 emplines--;
493             }
494             continue;
495         }
496
497         if( afx->faked == 1 )
498             afx->faked++;  /* skip the first (empty) line */
499         else {
500             while( len < size && afx->buffer_pos < afx->buffer_len )
501                 buf[len++] = afx->buffer[afx->buffer_pos++];
502             if( afx->buffer_pos >= afx->buffer_len
503                 && !afx->not_dash_escaped ) {
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         if( !afx->not_dash_escaped )
523             afx->buffer_len = trim_trailing_spaces( afx->buffer,
524                                                     afx->buffer_len );
525         p = afx->buffer;
526         n = afx->buffer_len;
527
528         if( n > 2 && *p == '-' ) {
529             /* check for dash escaped or armor header */
530             if( p[1] == ' ' && !afx->not_dash_escaped ) {
531                 /* issue a warning if it is not regular encoded */
532                 if( p[2] != '-' && !( n > 6 && !memcmp(p+2, "From ", 5))) {
533                     log_info(_("invalid dash escaped line: "));
534                     print_string( stderr, p, n, 0 );
535                     putc('\n', stderr);
536                 }
537                 afx->buffer_pos = 2; /* skip */
538             }
539             else if( n >= 15 &&  p[1] == '-' && p[2] == '-' && p[3] == '-' ) {
540                 if( is_armor_header( p, n ) != BEGIN_SIGNATURE ) {
541                     log_info(_("unexpected armor:"));
542                     print_string( stderr, p, n, 0 );
543                     putc('\n', stderr);
544                 }
545                 lastline = 1;
546                 if( len >= 2 && !afx->not_dash_escaped )
547                     len -= 2; /* remove the last CR,LF */
548                 rc = -1;
549             }
550         }
551     }
552
553     buf[0] = (len-2) >> 8;
554     buf[1] = (len-2);
555     if( lastline ) { /* write last (ending) length header */
556         if( buf[0] || buf[1] ) { /* only if we have some text */
557             buf[len++] = 0;
558             buf[len++] = 0;
559         }
560         rc = 0;
561         afx->faked = 0;
562         afx->in_cleartext = 0;
563         /* and now read the header lines */
564         afx->buffer_pos = 0;
565         for(;;) {
566             int i;
567
568             /* read the next line (skip all truncated lines) */
569             do {
570                 maxlen = MAX_LINELEN;
571                 afx->buffer_len = iobuf_read_line( a, &afx->buffer,
572                                                  &afx->buffer_size, &maxlen );
573             } while( !maxlen );
574             p = afx->buffer;
575             n = afx->buffer_len;
576             if( !n ) {
577                 rc = -1;
578                 break; /* eof */
579             }
580             i = parse_header_line( afx, p , n );
581             if( i <= 0 ) {
582                 if( i )
583                     invalid_armor();
584                 break;
585             }
586         }
587         afx->inp_checked = 1;
588         afx->crc = CRCINIT;
589         afx->idx = 0;
590         afx->radbuf[0] = 0;
591     }
592
593     afx->empty = emplines;
594     *retn = len;
595     return rc;
596 }
597
598
599
600 static int
601 radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
602               byte *buf, size_t size )
603 {
604     byte val;
605     int c, c2;
606     int checkcrc=0;
607     int rc = 0;
608     size_t n = 0;
609     int  idx, i;
610     u32 crc;
611
612     crc = afx->crc;
613     idx = afx->idx;
614     val = afx->radbuf[0];
615     for( n=0; n < size; ) {
616         if( (c=iobuf_get(a)) == -1 )
617             break;
618         if( c == '\n' || c == ' ' || c == '\r' || c == '\t' )
619             continue;
620         else if( c == '=' ) { /* pad character: stop */
621             if( idx == 1 )
622                 buf[n++] = val;
623             checkcrc++;
624             break;
625         }
626         else if( (c = asctobin[(c2=c)]) == 255 ) {
627             log_error(_("invalid radix64 character %02x skipped\n"), c2);
628             continue;
629         }
630         switch(idx) {
631           case 0: val =  c << 2; break;
632           case 1: val |= (c>>4)&3; buf[n++]=val;val=(c<<4)&0xf0;break;
633           case 2: val |= (c>>2)&15; buf[n++]=val;val=(c<<6)&0xc0;break;
634           case 3: val |= c&0x3f; buf[n++] = val; break;
635         }
636         idx = (idx+1) % 4;
637     }
638     for(i=0; i < n; i++ )
639         crc = (crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ buf[i]];
640     crc &= 0x00ffffff;
641     afx->crc = crc;
642     afx->idx = idx;
643     afx->radbuf[0] = val;
644     if( checkcrc ) {
645         afx->any_data = 1;
646         afx->inp_checked=0;
647         afx->faked = 0;
648         for(;;) { /* skip lf and pad characters */
649             if( (c=iobuf_get(a)) == -1 )
650                 break;
651             if( c == '\n' || c == ' ' || c == '\r'
652                 || c == '\t' || c == '=' )
653                 continue;
654             break;
655         }
656         if( c == -1 )
657             log_error(_("premature eof (no CRC)\n"));
658         else {
659             u32 mycrc = 0;
660             idx = 0;
661             do {
662                 if( (c = asctobin[c]) == 255 )
663                     break;
664                 switch(idx) {
665                   case 0: val =  c << 2; break;
666                   case 1: val |= (c>>4)&3; mycrc |= val << 16;val=(c<<4)&0xf0;break;
667                   case 2: val |= (c>>2)&15; mycrc |= val << 8;val=(c<<6)&0xc0;break;
668                   case 3: val |= c&0x3f; mycrc |= val; break;
669                 }
670                 if( (c=iobuf_get(a)) == -1 )
671                     break;
672             } while( ++idx < 4 );
673             if( c == -1 ) {
674                 log_error(_("premature eof (in CRC)\n"));
675                 rc = G10ERR_INVALID_ARMOR;
676             }
677             else if( idx != 4 ) {
678                 log_error(_("malformed CRC\n"));
679                 rc = G10ERR_INVALID_ARMOR;
680             }
681             else if( mycrc != afx->crc ) {
682                 log_error(_("CRC error; %06lx - %06lx\n"),
683                                     (ulong)afx->crc, (ulong)mycrc);
684                 rc = G10ERR_INVALID_ARMOR;
685             }
686             else {
687                 rc = 0;
688               #if 0
689                 for(rc=0;!rc;) {
690                     rc = 0 /*check_trailer( &fhdr, c )*/;
691                     if( !rc ) {
692                         if( (c=iobuf_get(a)) == -1 )
693                             rc = 2;
694                     }
695                 }
696                 if( rc == -1 )
697                     rc = 0;
698                 else if( rc == 2 ) {
699                     log_error(_("premature eof (in Trailer)\n"));
700                     rc = G10ERR_INVALID_ARMOR;
701                 }
702                 else {
703                     log_error(_("error in trailer line\n"));
704                     rc = G10ERR_INVALID_ARMOR;
705                 }
706               #endif
707             }
708         }
709     }
710
711     if( !n )
712         rc = -1;
713
714     *retn = n;
715     return rc;
716 }
717
718 /****************
719  * This filter is used to handle the armor stuff
720  */
721 int
722 armor_filter( void *opaque, int control,
723              IOBUF a, byte *buf, size_t *ret_len)
724 {
725     size_t size = *ret_len;
726     armor_filter_context_t *afx = opaque;
727     int rc=0, i, c;
728     byte radbuf[3];
729     int  idx, idx2;
730     size_t n=0;
731     u32 crc;
732   #if 0
733     static FILE *fp ;
734
735     if( !fp ) {
736         fp = fopen("armor.out", "w");
737         assert(fp);
738     }
739   #endif
740
741     if( DBG_FILTER )
742         log_debug("armor-filter: control: %d\n", control );
743     if( control == IOBUFCTRL_UNDERFLOW && afx->inp_bypass ) {
744         n = 0;
745         if( afx->buffer_len ) {
746             for(; n < size && afx->buffer_pos < afx->buffer_len; n++ )
747                 buf[n++] = afx->buffer[afx->buffer_pos++];
748             if( afx->buffer_pos >= afx->buffer_len )
749                 afx->buffer_len = 0;
750         }
751         for(; n < size; n++ ) {
752             if( (c=iobuf_get(a)) == -1 )
753                 break;
754             buf[n] = c & 0xff;
755         }
756         if( !n )
757             rc = -1;
758         *ret_len = n;
759     }
760     else if( control == IOBUFCTRL_UNDERFLOW ) {
761         if( size < 15+(4*15) )  /* need space for up to 4 onepass_sigs */
762             BUG(); /* supplied buffer too short */
763
764         if( afx->faked )
765             rc = fake_packet( afx, a, &n, buf, size );
766         else if( !afx->inp_checked ) {
767             rc = check_input( afx, a );
768             if( afx->inp_bypass ) {
769                 for(n=0; n < size && afx->buffer_pos < afx->buffer_len; n++ )
770                     buf[n++] = afx->buffer[afx->buffer_pos++];
771                 if( afx->buffer_pos >= afx->buffer_len )
772                     afx->buffer_len = 0;
773                 if( !n )
774                     rc = -1;
775             }
776             else if( afx->faked ) {
777                 unsigned hashes = afx->hashes;
778                 /* the buffer is at least 15+n*15 bytes long, so it
779                  * is easy to construct the packets */
780
781                 hashes &= 1|2|4|8;
782                 if( !hashes )
783                     hashes |= 4;  /* default to MD 5 */
784                 n=0;
785                 do {
786                     /* first some onepass signature packets */
787                     buf[n++] = 0x90; /* old format, type 4, 1 length byte */
788                     buf[n++] = 13;   /* length */
789                     buf[n++] = 3;    /* version */
790                     buf[n++] = 0x01; /* sigclass 0x01 (canonical text mode)*/
791                     if( hashes & 1 ) {
792                         hashes &= ~1;
793                         buf[n++] = DIGEST_ALGO_RMD160;
794                     }
795                     else if( hashes & 2 ) {
796                         hashes &= ~2;
797                         buf[n++] = DIGEST_ALGO_SHA1;
798                     }
799                     else if( hashes & 4 ) {
800                         hashes &= ~4;
801                         buf[n++] = DIGEST_ALGO_MD5;
802                     }
803                     else if( hashes & 8 ) {
804                         hashes &= ~8;
805                         buf[n++] = DIGEST_ALGO_TIGER;
806                     }
807                     else
808                         buf[n++] = 0;    /* (don't know) */
809
810                     buf[n++] = 0;    /* public key algo (don't know) */
811                     memset(buf+n, 0, 8); /* don't know the keyid */
812                     n += 8;
813                     buf[n++] = !hashes;   /* last one */
814                 } while( hashes );
815
816                 /* followed by a plaintext packet */
817                 buf[n++] = 0xaf; /* old packet format, type 11, var length */
818                 buf[n++] = 0;    /* set the length header */
819                 buf[n++] = 6;
820                 buf[n++] = 't';  /* canonical text mode */
821                 buf[n++] = 0;    /* namelength */
822                 memset(buf+n, 0, 4); /* timestamp */
823                 n += 4;
824             }
825             else if( !rc )
826                 rc = radix64_read( afx, a, &n, buf, size );
827         }
828         else
829             rc = radix64_read( afx, a, &n, buf, size );
830       #if 0
831         if( n )
832             if( fwrite(buf, n, 1, fp ) != 1 )
833                 BUG();
834       #endif
835         *ret_len = n;
836     }
837     else if( control == IOBUFCTRL_FLUSH ) {
838         if( !afx->status ) { /* write the header line */
839             if( afx->what >= DIM(head_strings) )
840                 log_bug("afx->what=%d", afx->what);
841             iobuf_writestr(a, "-----");
842             iobuf_writestr(a, head_strings[afx->what] );
843             iobuf_writestr(a, "-----\n");
844             iobuf_writestr(a, "Version: GnuPG v"  VERSION " ("
845                                             PRINTABLE_OS_NAME ")\n");
846
847             if( opt.comment_string ) {
848                 const char *s = opt.comment_string;
849                 iobuf_writestr(a, "Comment: " );
850                 for( ; *s; s++ ) {
851                     if( *s == '\n' )
852                         iobuf_writestr(a, "\\n" );
853                     else if( *s == '\r' )
854                         iobuf_writestr(a, "\\r" );
855                     else if( *s == '\v' )
856                         iobuf_writestr(a, "\\v" );
857                     else
858                         iobuf_put(a, *s );
859                 }
860                 iobuf_put(a, '\n' );
861             }
862             else
863                 iobuf_writestr(a,
864                     "Comment: For info see http://www.gnupg.org\n");
865             if( afx->hdrlines )
866                 iobuf_writestr(a, afx->hdrlines);
867             iobuf_put(a, '\n');
868             afx->status++;
869             afx->idx = 0;
870             afx->idx2 = 0;
871             afx->crc = CRCINIT;
872         }
873         crc = afx->crc;
874         idx = afx->idx;
875         idx2 = afx->idx2;
876         for(i=0; i < idx; i++ )
877             radbuf[i] = afx->radbuf[i];
878
879         for(i=0; i < size; i++ )
880             crc = (crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ buf[i]];
881         crc &= 0x00ffffff;
882
883         for( ; size; buf++, size-- ) {
884             radbuf[idx++] = *buf;
885             if( idx > 2 ) {
886                 idx = 0;
887                 c = bintoasc[(*radbuf >> 2) & 077];
888                 iobuf_put(a, c);
889                 c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
890                 iobuf_put(a, c);
891                 c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
892                 iobuf_put(a, c);
893                 c = bintoasc[radbuf[2]&077];
894                 iobuf_put(a, c);
895                 if( ++idx2 >= (64/4) ) { /* pgp doesn't like 72 here */
896                     iobuf_put(a, '\n');
897                     idx2=0;
898                 }
899             }
900         }
901         for(i=0; i < idx; i++ )
902             afx->radbuf[i] = radbuf[i];
903         afx->idx = idx;
904         afx->idx2 = idx2;
905         afx->crc  = crc;
906     }
907     else if( control == IOBUFCTRL_INIT ) {
908         if( !is_initialized )
909             initialize();
910     }
911     else if( control == IOBUFCTRL_FREE ) {
912         if( afx->status ) { /* pad, write cecksum, and bottom line */
913             crc = afx->crc;
914             idx = afx->idx;
915             idx2 = afx->idx2;
916             for(i=0; i < idx; i++ )
917                 radbuf[i] = afx->radbuf[i];
918             if( idx ) {
919                 c = bintoasc[(*radbuf>>2)&077];
920                 iobuf_put(a, c);
921                 if( idx == 1 ) {
922                     c = bintoasc[((*radbuf << 4) & 060) & 077];
923                     iobuf_put(a, c);
924                     iobuf_put(a, '=');
925                     iobuf_put(a, '=');
926                 }
927                 else { /* 2 */
928                     c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1]>>4)&017))&077];
929                     iobuf_put(a, c);
930                     c = bintoasc[((radbuf[1] << 2) & 074) & 077];
931                     iobuf_put(a, c);
932                     iobuf_put(a, '=');
933                 }
934                 if( ++idx2 >= (64/4) ) { /* pgp doesn't like 72 here */
935                     iobuf_put(a, '\n');
936                     idx2=0;
937                 }
938             }
939             /* may need a linefeed */
940             if( idx2 )
941                 iobuf_put(a, '\n');
942             /* write the CRC */
943             iobuf_put(a, '=');
944             radbuf[0] = crc >>16;
945             radbuf[1] = crc >> 8;
946             radbuf[2] = crc;
947             c = bintoasc[(*radbuf >> 2) & 077];
948             iobuf_put(a, c);
949             c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
950             iobuf_put(a, c);
951             c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
952             iobuf_put(a, c);
953             c = bintoasc[radbuf[2]&077];
954             iobuf_put(a, c);
955             iobuf_put(a, '\n');
956             /* and the the trailer */
957             if( afx->what >= DIM(tail_strings) )
958                 log_bug("afx->what=%d", afx->what);
959             iobuf_writestr(a, "-----");
960             iobuf_writestr(a, tail_strings[afx->what] );
961             iobuf_writestr(a, "-----\n");
962         }
963         else if( !afx->any_data && !afx->inp_bypass )
964             log_error(_("no valid OpenPGP data found.\n"));
965         if( afx->truncated )
966             log_info(_("invalid armor: line longer than %d characters\n"),
967                       MAX_LINELEN );
968         m_free( afx->buffer );
969         afx->buffer = NULL;
970     }
971     else if( control == IOBUFCTRL_DESC )
972         *(char**)buf = "armor_filter";
973     return rc;
974 }
975
976
977