ready to release 0.4.3
[gnupg.git] / g10 / armor.c
1 /* armor.c - Armor filter
2  *      Copyright (C) 1998 Free Software Foundation, Inc.
3  *
4  * This file is part of GNUPG.
5  *
6  * GNUPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GNUPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <assert.h>
27
28 #include "errors.h"
29 #include "iobuf.h"
30 #include "memory.h"
31 #include "util.h"
32 #include "filter.h"
33 #include "packet.h"
34 #include "options.h"
35 #include "main.h"
36 #include "status.h"
37 #include "i18n.h"
38
39
40 #define CRCINIT 0xB704CE
41 #define CRCPOLY 0X864CFB
42 #define CRCUPDATE(a,c) do {                                                 \
43                         a = ((a) << 8) ^ crc_table[((a)&0xff >> 16) ^ (c)]; \
44                         a &= 0x00ffffff;                                    \
45                     } while(0)
46 static u32 crc_table[256];
47 static byte bintoasc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
48                          "abcdefghijklmnopqrstuvwxyz"
49                          "0123456789+/";
50 static byte asctobin[256]; /* runtime initialized */
51 static int is_initialized;
52
53
54 typedef enum {
55     fhdrHASArmor = 0,
56     fhdrNOArmor,
57     fhdrINIT,
58     fhdrINITCont,
59     fhdrINITSkip,
60     fhdrCHECKBegin,
61     fhdrWAITHeader,
62     fhdrWAITClearsig,
63     fhdrSKIPHeader,
64     fhdrCLEARSIG,
65     fhdrREADClearsig,
66     fhdrNullClearsig,
67     fhdrEMPTYClearsig,
68     fhdrCHECKClearsig,
69     fhdrCHECKClearsig2,
70     fhdrCHECKDashEscaped,
71     fhdrCHECKDashEscaped2,
72     fhdrCHECKDashEscaped3,
73     fhdrREADClearsigNext,
74     fhdrENDClearsig,
75     fhdrENDClearsigHelp,
76     fhdrTESTSpaces,
77     fhdrTEXT,
78     fhdrERROR,
79     fhdrERRORShow,
80     fhdrEOF
81 } fhdr_state_t;
82
83
84 /* if we encounter this armor string with this index, go
85  * into a mode which fakes packets and wait for the next armor */
86 #define BEGIN_SIGNED_MSG_IDX 3
87 static char *head_strings[] = {
88     "BEGIN PGP MESSAGE",
89     "BEGIN PGP PUBLIC KEY BLOCK",
90     "BEGIN PGP SIGNATURE",
91     "BEGIN PGP SIGNED MESSAGE",
92     "BEGIN PGP ARMORED FILE",       /* gnupg extension */
93     "BEGIN PGP PRIVATE KEY BLOCK",
94     "BEGIN PGP SECRET KEY BLOCK",   /* only used by pgp2 */
95     NULL
96 };
97 static char *tail_strings[] = {
98     "END PGP MESSAGE",
99     "END PGP PUBLIC KEY BLOCK",
100     "END PGP SIGNATURE",
101     "END dummy",
102     "END PGP ARMORED FILE",
103     "END PGP PRIVATE KEY BLOCK",
104     "END PGP SECRET KEY BLOCK",
105     NULL
106 };
107
108
109 static fhdr_state_t find_header( fhdr_state_t state,
110                                  byte *buf, size_t *r_buflen,
111                                  IOBUF a, size_t n,
112                                  unsigned *r_empty, int *r_hashes,
113                                  int only_keyblocks );
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( 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  * parse an ascii armor.
258  * Returns: the state,
259  *          the remaining bytes in BUF are returned in RBUFLEN.
260  *          r_empty return the # of empty lines before the buffer
261  */
262 static fhdr_state_t
263 find_header( fhdr_state_t state, byte *buf, size_t *r_buflen,
264              IOBUF a, size_t n, unsigned *r_empty, int *r_hashes,
265              int only_keyblocks )
266 {
267     int c=0, i;
268     const char *s;
269     byte *p;
270     size_t buflen;
271     int cont;
272     int clearsig=0;
273     int hdr_line=0;
274     unsigned empty = 0;
275
276     buflen = *r_buflen;
277     assert(buflen >= 100 );
278     buflen -= 4; /* reserved room for CR,LF, and two extra */
279
280     do {
281         switch( state ) {
282           case fhdrHASArmor:
283             /* read at least the first byte to check whether it is armored
284              * or not */
285             c = 0;
286             for(n=0; n < 28 && (c=iobuf_get(a)) != -1 && c != '\n'; )
287                 buf[n++] = c;
288             if( !n && c == '\n' )
289                 state = fhdrCHECKBegin;
290             else if( !n  || c == -1 )
291                 state = fhdrNOArmor; /* too short */
292             else if( !is_armored( buf ) ) {
293                 state = fhdrNOArmor;
294                 if( c == '\n' )
295                     buf[n++] = c;
296             }
297             else if( c == '\n' )
298                 state = fhdrCHECKBegin;
299             else
300                 state = fhdrINITCont;
301             break;
302
303           case fhdrINIT: /* read some stuff into buffer */
304             n = 0;
305           case fhdrINITCont: /* read more stuff into buffer */
306             c = 0;
307             for(; n < buflen && (c=iobuf_get(a)) != -1 && c != '\n'; )
308                 buf[n++] = c;
309             state = c == '\n' ? fhdrCHECKBegin :
310                      c == -1  ? fhdrEOF : fhdrINITSkip;
311             break;
312
313           case fhdrINITSkip:
314             if( c == '\n' )
315                 n = 0;
316             else {
317                 while( (c=iobuf_get(a)) != -1 && c != '\n' )
318                     ;
319             }
320             state =  c == -1? fhdrEOF : fhdrINIT;
321             break;
322
323           case fhdrSKIPHeader:
324             while( (c=iobuf_get(a)) != -1 && c != '\n' )
325                 ;
326             state =  c == -1? fhdrEOF : fhdrWAITHeader;
327             break;
328
329           case fhdrWAITHeader: /* wait for Header lines */
330             c = 0;
331             for(n=0; n < buflen && (c=iobuf_get(a)) != -1 && c != '\n'; )
332                 buf[n++] = c;
333             buf[n] = 0;
334             if( n < buflen || c == '\n' ) {
335                 if( n && buf[0] != '\r') { /* maybe a header */
336                     if( strchr( buf, ':') ) { /* yes */
337                         int hashes=0;
338                         if( buf[n-1] == '\r' )
339                             buf[--n] = 0;
340                         if( opt.verbose ) {
341                             log_info(_("armor header: "));
342                             print_string( stderr, buf, n, 0 );
343                             putc('\n', stderr);
344                         }
345                         if( clearsig && !(hashes=parse_hash_header( buf )) ) {
346                             log_error(_("invalid clearsig header\n"));
347                             state = fhdrERROR;
348                         }
349                         else {
350                             state = fhdrWAITHeader;
351                             if( r_hashes )
352                                 *r_hashes |= hashes;
353                         }
354                     }
355                     else if( clearsig && n > 15 && !memcmp(buf, "-----", 5 ) )
356                         state = fhdrNullClearsig;
357                     else
358                         state = fhdrCHECKDashEscaped3;
359                 }
360                 else if( !n || (buf[0] == '\r' && !buf[1]) ) { /* empty line */
361                     if( clearsig )
362                         state = fhdrWAITClearsig;
363                     else {
364                         /* this is not really correct: if we do not have
365                          * a clearsig and no armor lines we are not allowed
366                          * to have an empty line */
367                         n = 0;
368                         state = fhdrTEXT;
369                     }
370                 }
371                 else {
372                     log_error(_("invalid armor header: "));
373                     print_string( stderr, buf, n, 0 );
374                     putc('\n', stderr);
375                     state = fhdrERROR;
376                 }
377             }
378             else if( c != -1 ) {
379                 if( strchr( buf, ':') ) { /* buffer to short, but this is okay*/
380                     if( opt.verbose ) {
381                         log_info(_("armor header: "));
382                         print_string( stderr, buf, n, 0 );
383                         fputs("[...]\n", stderr);  /* indicate it is truncated */
384                     }
385                     state = fhdrSKIPHeader;  /* skip rest of line */
386                 }
387                 else /* line too long */
388                     state = fhdrERROR;
389             }
390             else
391                 state = fhdrEOF;
392             break;
393
394           case fhdrWAITClearsig: /* skip the empty line (for clearsig) */
395             c = 0;
396             for(n=0; n < buflen && (c=iobuf_get(a)) != -1 && c != '\n'; )
397                 buf[n++] = c;
398             if( n < buflen || c == '\n' ) {
399                 buf[n] = 0;
400                 if( n > 15 && !memcmp(buf, "-----", 5 ) )
401                     state = fhdrNullClearsig;
402                 else
403                     state = fhdrCHECKDashEscaped3;
404             }
405             else {
406                 /* fixme: we should check whether this line continues
407                  *   it is possible that we have only read ws until here
408                  *   and more stuff is to come */
409                 state = fhdrEOF;
410             }
411             break;
412
413           case fhdrNullClearsig: /* zero length cleartext */
414             state = fhdrENDClearsig;
415             break;
416
417           case fhdrENDClearsig:
418           case fhdrCHECKBegin:
419             state = state == fhdrCHECKBegin ? fhdrINITSkip : fhdrERRORShow;
420             if( n < 15 )
421                 break;  /* too short */
422             if( memcmp( buf, "-----", 5 ) )
423                 break;
424             buf[n] = 0;
425             p = strstr(buf+5, "-----");
426             if( !p )
427                 break;
428             *p = 0;
429             p += 5;
430             if( *p == '\r' )
431                 p++;
432             if( *p )
433                 break; /* garbage after dashes */
434             p = buf+5;
435             for(i=0; (s=head_strings[i]); i++ )
436                 if( !strcmp(s, p) )
437                     break;
438             if( !s )
439                 break; /* unknown begin line */
440             if( only_keyblocks && i != 1 && i != 5 && i != 6 )
441                 break; /* not a keyblock armor */
442
443             /* found the begin line */
444             hdr_line = i;
445             state = fhdrWAITHeader;
446             if( hdr_line == BEGIN_SIGNED_MSG_IDX )
447                 clearsig = 1;
448             if( opt.verbose > 1 )
449                 log_info(_("armor: %s\n"), head_strings[hdr_line]);
450             break;
451
452           case fhdrCLEARSIG:
453           case fhdrEMPTYClearsig:
454           case fhdrREADClearsig:
455             /* we are at the start of a line: read a clearsig into the buffer
456              * we have to look for a header line or dashed escaped text*/
457             n = 0;
458             c = 0;
459             while( n < buflen && (c=iobuf_get(a)) != -1 && c != '\n' )
460                 buf[n++] = c;
461             buf[n] = 0;
462             if( c == -1 )
463                 state = fhdrEOF;
464             else if( !n || ( buf[0]=='\r' && !buf[1] ) ) {
465                 state = fhdrEMPTYClearsig;
466                 empty++;
467             }
468             else if( c == '\n' )
469                 state = fhdrCHECKClearsig2;
470             else
471                 state = fhdrCHECKClearsig;
472             break;
473
474           case fhdrCHECKDashEscaped3:
475             if( !(n > 1 && buf[0] == '-' && buf[1] == ' ' ) ) {
476                 state = fhdrTEXT;
477                 break;
478             }
479             /* fall through */
480           case fhdrCHECKDashEscaped2:
481           case fhdrCHECKDashEscaped:
482             /* check dash escaped line */
483             if( buf[2] == '-' || ( n > 6 && !memcmp(buf+2, "From ", 5))) {
484                 for(i=2; i < n; i++ )
485                     buf[i-2] = buf[i];
486                 n -= 2;
487                 buf[n] = 0; /* not really needed */
488                 state = state == fhdrCHECKDashEscaped3 ? fhdrTEXT :
489                         state == fhdrCHECKDashEscaped2 ?
490                                  fhdrREADClearsig : fhdrTESTSpaces;
491             }
492             else {
493                 log_error(_("invalid dash escaped line: "));
494                 print_string( stderr, buf, n, 0 );
495                 putc('\n', stderr);
496                 state = fhdrERROR;
497             }
498             break;
499
500           case fhdrCHECKClearsig:
501             /* check the clearsig line */
502             if( n > 15 && !memcmp(buf, "-----", 5 ) )
503                 state = fhdrENDClearsig;
504             else if( buf[0] == '-' && buf[1] == ' ' )
505                 state = fhdrCHECKDashEscaped;
506             else {
507                 state = fhdrTESTSpaces;
508             }
509             break;
510
511           case fhdrCHECKClearsig2:
512             /* check the clearsig line */
513             if( n > 15 && !memcmp(buf, "-----", 5 ) )
514                 state = fhdrENDClearsig;
515             else if( buf[0] == '-' && buf[1] == ' ' )
516                 state = fhdrCHECKDashEscaped2;
517             else {
518                 state = fhdrREADClearsig;
519             }
520             break;
521
522           case fhdrREADClearsigNext:
523             /* Read to the end of the line, do not care about checking
524              * for dashed escaped text of headers */
525             c = 0;
526             n = 0;
527             while( n < buflen && (c=iobuf_get(a)) != -1 && c != '\n' )
528                 buf[n++] = c;
529             buf[n] = 0;
530             if( c == -1 )
531                 state = fhdrEOF;
532             else if( c == '\n' )
533                 state = fhdrREADClearsig;
534             else
535                 state = fhdrTESTSpaces;
536             break;
537
538           case fhdrTESTSpaces: {
539             /* but must check whether the rest of the line
540              * only contains white spaces; this is problematic
541              * since we may have to restore the stuff.  simply
542              * counting spaces is not enough, because it may be a
543              * mix of different white space characters */
544             IOBUF b = iobuf_temp();
545             while( (c=iobuf_get(a)) != -1 && c != '\n' ) {
546                 iobuf_put(b,c);
547                 if( c != ' ' && c != '\t' && c != '\r' )
548                     break;
549             }
550             if( c == '\n' ) {
551                 /* okay we can skip the rest of the line */
552                 iobuf_close(b);
553                 state = fhdrREADClearsig;
554             }
555             else {
556                 iobuf_unget_and_close_temp(a,b);
557                 state = fhdrREADClearsigNext;
558             }
559           } break;
560
561           case fhdrERRORShow:
562             log_error(_("invalid clear text header: "));
563             print_string( stderr, buf, n, 0 );
564             putc('\n', stderr);
565             state = fhdrERROR;
566             break;
567
568           default: BUG();
569         }
570         switch( state ) {
571           case fhdrINIT:
572           case fhdrINITCont:
573           case fhdrINITSkip:
574           case fhdrCHECKBegin:
575           case fhdrWAITHeader:
576           case fhdrWAITClearsig:
577           case fhdrSKIPHeader:
578           case fhdrEMPTYClearsig:
579           case fhdrCHECKClearsig:
580           case fhdrCHECKClearsig2:
581           case fhdrCHECKDashEscaped:
582           case fhdrCHECKDashEscaped2:
583           case fhdrCHECKDashEscaped3:
584           case fhdrTESTSpaces:
585           case fhdrERRORShow:
586             cont = 1;
587             break;
588           default: cont = 0;
589         }
590     } while( cont );
591
592     if( clearsig && state == fhdrTEXT )
593         state = fhdrCLEARSIG;
594
595     if( state == fhdrCLEARSIG || state == fhdrREADClearsig ) {
596         /* append CR,LF after removing trailing wspaces */
597         for(p=buf+n-1; n; n--, p-- ) {
598             assert( *p != '\n' );
599             if( *p != ' ' && *p != '\t' && *p != '\r' ) {
600                 p[1] = '\r';
601                 p[2] = '\n';
602                 n += 2;
603                 break;
604             }
605         }
606         if( !n ) {
607             buf[0] = '\r';
608             buf[1] = '\n';
609             n = 2;
610         }
611     }
612
613     *r_buflen = n;
614     *r_empty = empty;
615     return state;
616 }
617
618
619 /* figure out whether the data is armored or not */
620 static int
621 check_input( armor_filter_context_t *afx, IOBUF a )
622 {
623     int rc = 0;
624     size_t n;
625     fhdr_state_t state = afx->parse_state;
626     unsigned emplines;
627
628     if( state != fhdrENDClearsig )
629         state = fhdrHASArmor;
630
631     n = DIM(afx->helpbuf);
632     state = find_header( state, afx->helpbuf, &n, a,
633                                 afx->helplen, &emplines, &afx->hashes,
634                                 afx->only_keyblocks );
635     switch( state ) {
636       case fhdrNOArmor:
637         afx->inp_checked = 1;
638         afx->inp_bypass = 1;
639         afx->helplen = n;
640         break;
641
642       case fhdrERROR:
643         invalid_armor();
644         break;
645
646       case fhdrEOF:
647         rc = -1;
648         break;
649
650       case fhdrNullClearsig:
651       case fhdrCLEARSIG: /* start fake package mode (for clear signatures) */
652         afx->helplen = n;
653         afx->helpidx = 0;
654         afx->faked = 1;
655         break;
656
657       case fhdrTEXT:
658         afx->helplen = n;
659         afx->helpidx = 0;
660         afx->inp_checked = 1;
661         afx->crc = CRCINIT;
662         afx->idx = 0;
663         afx->radbuf[0] = 0;
664         break;
665
666       default: BUG();
667     }
668
669     afx->parse_state = state;
670     return rc;
671 }
672
673
674
675 /* fake a literal data packet and wait for an armor line */
676 static int
677 fake_packet( armor_filter_context_t *afx, IOBUF a,
678              size_t *retn, byte *buf, size_t size  )
679 {
680     int rc = 0;
681     size_t len = 0;
682     size_t n, nn;
683     fhdr_state_t state = afx->parse_state;
684     unsigned emplines = afx->empty;
685
686     len = 2;    /* reserve 2 bytes for the length header */
687     size -= 3;  /* and 1 for empline handling and 2 for the term header */
688     while( !rc && len < size ) {
689         if( emplines ) {
690             while( emplines && len < size ) {
691                 buf[len++] = '\r';
692                 buf[len++] = '\n';
693                 emplines--;
694             }
695             continue;
696         }
697         if( state == fhdrENDClearsigHelp ) {
698             state = fhdrENDClearsig;
699             afx->faked = 0;
700             rc = -1;
701             continue;
702         }
703         if( state != fhdrNullClearsig
704             && afx->helpidx < afx->helplen ) { /* flush the last buffer */
705             n = afx->helplen;
706             for(nn=afx->helpidx; len < size && nn < n ; nn++ )
707                 buf[len++] = afx->helpbuf[nn];
708             afx->helpidx = nn;
709             continue;
710         }
711         if( state == fhdrEOF ) {
712             rc = -1;
713             continue;
714         }
715         /* read a new one */
716         n = DIM(afx->helpbuf);
717         afx->helpidx = 0;
718         state = find_header( state, afx->helpbuf, &n, a,
719                               state == fhdrNullClearsig? afx->helplen:0,
720                                                 &emplines, &afx->hashes,
721                                                 afx->only_keyblocks );
722         switch( state) {
723           case fhdrERROR:
724             invalid_armor();
725             break;
726
727           case fhdrEOF:
728             rc = -1;
729             break;
730
731           case fhdrCLEARSIG:
732             BUG();
733
734           case fhdrREADClearsig:
735           case fhdrREADClearsigNext:
736             afx->helplen = n;
737             break;
738
739           case fhdrENDClearsig:
740             state = fhdrENDClearsigHelp;
741             afx->helplen = n;
742             break;
743
744           default: BUG();
745         }
746     }
747     buf[0] = (len-2) >> 8;
748     buf[1] = (len-2);
749     if( state == fhdrENDClearsig ) { /* write last (ending) length header */
750         if( buf[0] || buf[1] ) { /* write only if length of text is > 0 */
751             buf[len++] = 0;
752             buf[len++] = 0;
753         }
754         rc = 0;
755     }
756
757     afx->parse_state = state;
758     afx->empty = emplines;
759     *retn = len;
760     return rc;
761 }
762
763
764
765 static int
766 radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
767               byte *buf, size_t size )
768 {
769     byte val;
770     int c, c2;
771     int checkcrc=0;
772     int rc = 0;
773     size_t n = 0;
774     int  idx, i;
775     u32 crc;
776
777     crc = afx->crc;
778     idx = afx->idx;
779     val = afx->radbuf[0];
780     for( n=0; n < size; ) {
781         if( afx->helpidx < afx->helplen )
782             c = afx->helpbuf[afx->helpidx++];
783         else if( (c=iobuf_get(a)) == -1 )
784             break;
785         if( c == '\n' || c == ' ' || c == '\r' || c == '\t' )
786             continue;
787         else if( c == '=' ) { /* pad character: stop */
788             if( idx == 1 )
789                 buf[n++] = val;
790             checkcrc++;
791             break;
792         }
793         else if( (c = asctobin[(c2=c)]) == 255 ) {
794             log_error(_("invalid radix64 character %02x skipped\n"), c2);
795             continue;
796         }
797         switch(idx) {
798           case 0: val =  c << 2; break;
799           case 1: val |= (c>>4)&3; buf[n++]=val;val=(c<<4)&0xf0;break;
800           case 2: val |= (c>>2)&15; buf[n++]=val;val=(c<<6)&0xc0;break;
801           case 3: val |= c&0x3f; buf[n++] = val; break;
802         }
803         idx = (idx+1) % 4;
804     }
805     for(i=0; i < n; i++ )
806         crc = (crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ buf[i]];
807     crc &= 0x00ffffff;
808     afx->crc = crc;
809     afx->idx = idx;
810     afx->radbuf[0] = val;
811     if( checkcrc ) {
812         afx->any_data = 1;
813         afx->inp_checked=0;
814         afx->faked = 0;
815         afx->parse_state = 0;
816         for(;;) { /* skip lf and pad characters */
817             if( afx->helpidx < afx->helplen )
818                 c = afx->helpbuf[afx->helpidx++];
819             else if( (c=iobuf_get(a)) == -1 )
820                 break;
821             if( c == '\n' || c == ' ' || c == '\r'
822                 || c == '\t' || c == '=' )
823                 continue;
824             break;
825         }
826         if( c == -1 )
827             log_error(_("premature eof (no CRC)\n"));
828         else {
829             u32 mycrc = 0;
830             idx = 0;
831             do {
832                 if( (c = asctobin[c]) == 255 )
833                     break;
834                 switch(idx) {
835                   case 0: val =  c << 2; break;
836                   case 1: val |= (c>>4)&3; mycrc |= val << 16;val=(c<<4)&0xf0;break;
837                   case 2: val |= (c>>2)&15; mycrc |= val << 8;val=(c<<6)&0xc0;break;
838                   case 3: val |= c&0x3f; mycrc |= val; break;
839                 }
840                 if( afx->helpidx < afx->helplen )
841                     c = afx->helpbuf[afx->helpidx++];
842                 else if( (c=iobuf_get(a)) == -1 )
843                     break;
844             } while( ++idx < 4 );
845             if( c == -1 ) {
846                 log_error(_("premature eof (in CRC)\n"));
847                 rc = G10ERR_INVALID_ARMOR;
848             }
849             else if( idx != 4 ) {
850                 log_error(_("malformed CRC\n"));
851                 rc = G10ERR_INVALID_ARMOR;
852             }
853             else if( mycrc != afx->crc ) {
854                 log_error(_("CRC error; %06lx - %06lx\n"),
855                                     (ulong)afx->crc, (ulong)mycrc);
856                 rc = G10ERR_INVALID_ARMOR;
857             }
858             else {
859                 rc = 0;
860               #if 0
861                 for(rc=0;!rc;) {
862                     rc = 0 /*check_trailer( &fhdr, c )*/;
863                     if( !rc ) {
864                         if( afx->helpidx < afx->helplen )
865                             c = afx->helpbuf[afx->helpidx++];
866                         else if( (c=iobuf_get(a)) == -1 )
867                             rc = 2;
868                     }
869                 }
870                 if( rc == -1 )
871                     rc = 0;
872                 else if( rc == 2 ) {
873                     log_error(_("premature eof (in Trailer)\n"));
874                     rc = G10ERR_INVALID_ARMOR;
875                 }
876                 else {
877                     log_error(_("error in trailer line\n"));
878                     rc = G10ERR_INVALID_ARMOR;
879                 }
880               #endif
881             }
882         }
883     }
884
885     if( !n )
886         rc = -1;
887
888     *retn = n;
889     return rc;
890 }
891
892 /****************
893  * This filter is used to handle the armor stuff
894  */
895 int
896 armor_filter( void *opaque, int control,
897              IOBUF a, byte *buf, size_t *ret_len)
898 {
899     size_t size = *ret_len;
900     armor_filter_context_t *afx = opaque;
901     int rc=0, i, c;
902     byte radbuf[3];
903     int  idx, idx2;
904     size_t n=0;
905     u32 crc;
906   #if 0
907     static FILE *fp ;
908
909     if( !fp ) {
910         fp = fopen("armor.out", "w");
911         assert(fp);
912     }
913   #endif
914
915     if( DBG_FILTER )
916         log_debug("armor-filter: control: %d\n", control );
917     if( control == IOBUFCTRL_UNDERFLOW && afx->inp_bypass ) {
918         for( n=0; n < size; n++ ) {
919             if( (c=iobuf_get(a)) == -1 )
920                 break;
921             buf[n] = c & 0xff;
922         }
923         if( !n )
924             rc = -1;
925         *ret_len = n;
926     }
927     else if( control == IOBUFCTRL_UNDERFLOW ) {
928         if( size < 15+(4*15) )  /* need space for up to 4 onepass_sigs */
929             BUG(); /* supplied buffer too short */
930
931         if( afx->faked )
932             rc = fake_packet( afx, a, &n, buf, size );
933         else if( !afx->inp_checked ) {
934             rc = check_input( afx, a );
935             if( afx->inp_bypass ) {
936                 for( n=0; n < size && n < afx->helplen; n++ )
937                     buf[n] = afx->helpbuf[n];
938                 if( !n )
939                     rc = -1;
940                 assert( n == afx->helplen );
941                 afx->helplen = 0;
942             }
943             else if( afx->faked ) {
944                 unsigned hashes = afx->hashes;
945                 /* the buffer is at least 15+n*15 bytes long, so it
946                  * is easy to construct the packets */
947
948                 hashes &= 1|2|4|8;
949                 if( !hashes )
950                     hashes |= 4;  /* default to MD 5 */
951                 n=0;
952                 do {
953                     /* first some onepass signature packets */
954                     buf[n++] = 0x90; /* old format, type 4, 1 length byte */
955                     buf[n++] = 13;   /* length */
956                     buf[n++] = 3;    /* version */
957                     buf[n++] = 0x01; /* sigclass 0x01 (canonical text mode)*/
958                     if( hashes & 1 ) {
959                         hashes &= ~1;
960                         buf[n++] = DIGEST_ALGO_RMD160;
961                     }
962                     else if( hashes & 2 ) {
963                         hashes &= ~2;
964                         buf[n++] = DIGEST_ALGO_SHA1;
965                     }
966                     else if( hashes & 4 ) {
967                         hashes &= ~4;
968                         buf[n++] = DIGEST_ALGO_MD5;
969                     }
970                     else if( hashes & 8 ) {
971                         hashes &= ~8;
972                         buf[n++] = DIGEST_ALGO_TIGER;
973                     }
974                     else
975                         buf[n++] = 0;    /* (don't know) */
976
977                     buf[n++] = 0;    /* public key algo (don't know) */
978                     memset(buf+n, 0, 8); /* don't know the keyid */
979                     n += 8;
980                     buf[n++] = !hashes;   /* last one */
981                 } while( hashes );
982
983                 /* followed by a plaintext packet */
984                 buf[n++] = 0xaf; /* old packet format, type 11, var length */
985                 buf[n++] = 0;    /* set the length header */
986                 buf[n++] = 6;
987                 buf[n++] = 't';  /* canonical text mode */
988                 buf[n++] = 0;    /* namelength */
989                 memset(buf+n, 0, 4); /* timestamp */
990                 n += 4;
991             }
992             else if( !rc )
993                 rc = radix64_read( afx, a, &n, buf, size );
994         }
995         else
996             rc = radix64_read( afx, a, &n, buf, size );
997       #if 0
998         if( n )
999             if( fwrite(buf, n, 1, fp ) != 1 )
1000                 BUG();
1001       #endif
1002         *ret_len = n;
1003     }
1004     else if( control == IOBUFCTRL_FLUSH ) {
1005         if( !afx->status ) { /* write the header line */
1006             if( afx->what >= DIM(head_strings) )
1007                 log_bug("afx->what=%d", afx->what);
1008             iobuf_writestr(a, "-----");
1009             iobuf_writestr(a, head_strings[afx->what] );
1010             iobuf_writestr(a, "-----\n");
1011             iobuf_writestr(a, "Version: GNUPG v"  VERSION " ("
1012                                             PRINTABLE_OS_NAME ")\n");
1013
1014             if( opt.comment_string ) {
1015                 const char *s = opt.comment_string;
1016                 iobuf_writestr(a, "Comment: " );
1017                 for( ; *s; s++ ) {
1018                     if( *s == '\n' )
1019                         iobuf_writestr(a, "\\n" );
1020                     else if( *s == '\r' )
1021                         iobuf_writestr(a, "\\r" );
1022                     else if( *s == '\v' )
1023                         iobuf_writestr(a, "\\v" );
1024                     else
1025                         iobuf_put(a, *s );
1026                 }
1027                 iobuf_put(a, '\n' );
1028             }
1029             else
1030                 iobuf_writestr(a,
1031                     "Comment: For info finger gcrypt@ftp.guug.de\n");
1032             if( afx->hdrlines )
1033                 iobuf_writestr(a, afx->hdrlines);
1034             iobuf_put(a, '\n');
1035             afx->status++;
1036             afx->idx = 0;
1037             afx->idx2 = 0;
1038             afx->crc = CRCINIT;
1039         }
1040         crc = afx->crc;
1041         idx = afx->idx;
1042         idx2 = afx->idx2;
1043         for(i=0; i < idx; i++ )
1044             radbuf[i] = afx->radbuf[i];
1045
1046         for(i=0; i < size; i++ )
1047             crc = (crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ buf[i]];
1048         crc &= 0x00ffffff;
1049
1050         for( ; size; buf++, size-- ) {
1051             radbuf[idx++] = *buf;
1052             if( idx > 2 ) {
1053                 idx = 0;
1054                 c = bintoasc[(*radbuf >> 2) & 077];
1055                 iobuf_put(a, c);
1056                 c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
1057                 iobuf_put(a, c);
1058                 c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
1059                 iobuf_put(a, c);
1060                 c = bintoasc[radbuf[2]&077];
1061                 iobuf_put(a, c);
1062                 if( ++idx2 >= (64/4) ) { /* pgp doesn't like 72 here */
1063                     iobuf_put(a, '\n');
1064                     idx2=0;
1065                 }
1066             }
1067         }
1068         for(i=0; i < idx; i++ )
1069             afx->radbuf[i] = radbuf[i];
1070         afx->idx = idx;
1071         afx->idx2 = idx2;
1072         afx->crc  = crc;
1073     }
1074     else if( control == IOBUFCTRL_INIT ) {
1075         if( !is_initialized )
1076             initialize();
1077     }
1078     else if( control == IOBUFCTRL_FREE ) {
1079         if( afx->status ) { /* pad, write cecksum, and bottom line */
1080             crc = afx->crc;
1081             idx = afx->idx;
1082             idx2 = afx->idx2;
1083             for(i=0; i < idx; i++ )
1084                 radbuf[i] = afx->radbuf[i];
1085             if( idx ) {
1086                 c = bintoasc[(*radbuf>>2)&077];
1087                 iobuf_put(a, c);
1088                 if( idx == 1 ) {
1089                     c = bintoasc[((*radbuf << 4) & 060) & 077];
1090                     iobuf_put(a, c);
1091                     iobuf_put(a, '=');
1092                     iobuf_put(a, '=');
1093                 }
1094                 else { /* 2 */
1095                     c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1]>>4)&017))&077];
1096                     iobuf_put(a, c);
1097                     c = bintoasc[((radbuf[1] << 2) & 074) & 077];
1098                     iobuf_put(a, c);
1099                     iobuf_put(a, '=');
1100                 }
1101                 if( ++idx2 >= (64/4) ) { /* pgp doesn't like 72 here */
1102                     iobuf_put(a, '\n');
1103                     idx2=0;
1104                 }
1105             }
1106             /* may need a linefeed */
1107             if( idx2 )
1108                 iobuf_put(a, '\n');
1109             /* write the CRC */
1110             iobuf_put(a, '=');
1111             radbuf[0] = crc >>16;
1112             radbuf[1] = crc >> 8;
1113             radbuf[2] = crc;
1114             c = bintoasc[(*radbuf >> 2) & 077];
1115             iobuf_put(a, c);
1116             c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
1117             iobuf_put(a, c);
1118             c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
1119             iobuf_put(a, c);
1120             c = bintoasc[radbuf[2]&077];
1121             iobuf_put(a, c);
1122             iobuf_put(a, '\n');
1123             /* and the the trailer */
1124             if( afx->what >= DIM(tail_strings) )
1125                 log_bug("afx->what=%d", afx->what);
1126             iobuf_writestr(a, "-----");
1127             iobuf_writestr(a, tail_strings[afx->what] );
1128             iobuf_writestr(a, "-----\n");
1129         }
1130         else if( !afx->any_data && !afx->inp_bypass )
1131             log_error(_("no valid RFC1991 or OpenPGP data found.\n"));
1132     }
1133     else if( control == IOBUFCTRL_DESC )
1134         *(char**)buf = "armor_filter";
1135     return rc;
1136 }
1137
1138
1139