2004-02-26 Marcus Brinkmann <marcus@g10code.de>
[gnupg.git] / g10 / armor.c
blob121ec3a0912929c625b1a57374924716bb3b3e35
1 /* armor.c - Armor flter
2 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
3 * Free Software Foundation, Inc.
5 * This file is part of GnuPG.
7 * GnuPG is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * GnuPG is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <assert.h>
28 #include <ctype.h>
30 #include "gpg.h"
31 #include "errors.h"
32 #include "iobuf.h"
33 #include "memory.h"
34 #include "util.h"
35 #include "filter.h"
36 #include "packet.h"
37 #include "options.h"
38 #include "main.h"
39 #include "status.h"
40 #include "i18n.h"
42 #ifdef HAVE_DOSISH_SYSTEM
43 #define LF "\r\n"
44 #else
45 #define LF "\n"
46 #endif
48 #define MAX_LINELEN 20000
50 #define CRCINIT 0xB704CE
51 #define CRCPOLY 0X864CFB
52 #define CRCUPDATE(a,c) do { \
53 a = ((a) << 8) ^ crc_table[((a)&0xff >> 16) ^ (c)]; \
54 a &= 0x00ffffff; \
55 } while(0)
56 static u32 crc_table[256];
57 static byte bintoasc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
58 "abcdefghijklmnopqrstuvwxyz"
59 "0123456789+/";
60 static byte asctobin[256]; /* runtime initialized */
61 static int is_initialized;
64 typedef enum {
65 fhdrHASArmor = 0,
66 fhdrNOArmor,
67 fhdrINIT,
68 fhdrINITCont,
69 fhdrINITSkip,
70 fhdrCHECKBegin,
71 fhdrWAITHeader,
72 fhdrWAITClearsig,
73 fhdrSKIPHeader,
74 fhdrCLEARSIG,
75 fhdrREADClearsig,
76 fhdrNullClearsig,
77 fhdrEMPTYClearsig,
78 fhdrCHECKClearsig,
79 fhdrCHECKClearsig2,
80 fhdrCHECKDashEscaped,
81 fhdrCHECKDashEscaped2,
82 fhdrCHECKDashEscaped3,
83 fhdrREADClearsigNext,
84 fhdrENDClearsig,
85 fhdrENDClearsigHelp,
86 fhdrTESTSpaces,
87 fhdrCLEARSIGSimple,
88 fhdrCLEARSIGSimpleNext,
89 fhdrTEXT,
90 fhdrTEXTSimple,
91 fhdrERROR,
92 fhdrERRORShow,
93 fhdrEOF
94 } fhdr_state_t;
97 /* if we encounter this armor string with this index, go
98 * into a mode which fakes packets and wait for the next armor */
99 #define BEGIN_SIGNATURE 2
100 #define BEGIN_SIGNED_MSG_IDX 3
101 static char *head_strings[] = {
102 "BEGIN PGP MESSAGE",
103 "BEGIN PGP PUBLIC KEY BLOCK",
104 "BEGIN PGP SIGNATURE",
105 "BEGIN PGP SIGNED MESSAGE",
106 "BEGIN PGP ARMORED FILE", /* gnupg extension */
107 "BEGIN PGP PRIVATE KEY BLOCK",
108 "BEGIN PGP SECRET KEY BLOCK", /* only used by pgp2 */
109 NULL
111 static char *tail_strings[] = {
112 "END PGP MESSAGE",
113 "END PGP PUBLIC KEY BLOCK",
114 "END PGP SIGNATURE",
115 "END dummy",
116 "END PGP ARMORED FILE",
117 "END PGP PRIVATE KEY BLOCK",
118 "END PGP SECRET KEY BLOCK",
119 NULL
124 static void
125 initialize(void)
127 int i, j;
128 u32 t;
129 byte *s;
131 /* init the crc lookup table */
132 crc_table[0] = 0;
133 for(i=j=0; j < 128; j++ ) {
134 t = crc_table[j];
135 if( t & 0x00800000 ) {
136 t <<= 1;
137 crc_table[i++] = t ^ CRCPOLY;
138 crc_table[i++] = t;
140 else {
141 t <<= 1;
142 crc_table[i++] = t;
143 crc_table[i++] = t ^ CRCPOLY;
146 /* build the helptable for radix64 to bin conversion */
147 for(i=0; i < 256; i++ )
148 asctobin[i] = 255; /* used to detect invalid characters */
149 for(s=bintoasc,i=0; *s; s++,i++ )
150 asctobin[*s] = i;
152 is_initialized=1;
155 /****************
156 * Check whether this is an armored file or not See also
157 * parse-packet.c for details on this code For unknown historic
158 * reasons we use a string here but only the first byte will be used.
159 * Returns: True if it seems to be armored
161 static int
162 is_armored( const byte *buf )
164 int ctb, pkttype;
166 ctb = *buf;
167 if( !(ctb & 0x80) )
168 return 1; /* invalid packet: assume it is armored */
169 pkttype = ctb & 0x40 ? (ctb & 0x3f) : ((ctb>>2)&0xf);
170 switch( pkttype ) {
171 case PKT_MARKER:
172 case PKT_SYMKEY_ENC:
173 case PKT_ONEPASS_SIG:
174 case PKT_PUBLIC_KEY:
175 case PKT_SECRET_KEY:
176 case PKT_PUBKEY_ENC:
177 case PKT_SIGNATURE:
178 case PKT_COMMENT:
179 case PKT_OLD_COMMENT:
180 case PKT_PLAINTEXT:
181 case PKT_COMPRESSED:
182 case PKT_ENCRYPTED:
183 return 0; /* seems to be a regular packet: not armored */
186 return 1;
190 /****************
191 * Try to check whether the iobuf is armored
192 * Returns true if this may be the case; the caller should use the
193 * filter to do further processing.
196 use_armor_filter( iobuf_t a )
198 byte buf[1];
199 int n;
201 /* fixme: there might be a problem with iobuf_peek */
202 n = iobuf_peek(a, buf, 1 );
203 if( n == -1 )
204 return 0; /* EOF, doesn't matter whether armored or not */
205 if( !n )
206 return 1; /* can't check it: try armored */
207 return is_armored(buf);
213 static void
214 invalid_armor(void)
216 write_status(STATUS_BADARMOR);
217 g10_exit(1); /* stop here */
221 /****************
222 * check whether the armor header is valid on a signed message.
223 * this is for security reasons: the header lines are not included in the
224 * hash and by using some creative formatting rules, Mallory could fake
225 * any text at the beginning of a document; assuming it is read with
226 * a simple viewer. We only allow the Hash Header.
228 static int
229 parse_hash_header( const char *line )
231 const char *s, *s2;
232 unsigned found = 0;
234 if( strlen(line) < 6 || strlen(line) > 60 )
235 return 0; /* too short or too long */
236 if( memcmp( line, "Hash:", 5 ) )
237 return 0; /* invalid header */
238 s = line+5;
239 for(s=line+5;;s=s2) {
240 for(; *s && (*s==' ' || *s == '\t'); s++ )
242 if( !*s )
243 break;
244 for(s2=s+1; *s2 && *s2!=' ' && *s2 != '\t' && *s2 != ','; s2++ )
246 if( !strncmp( s, "RIPEMD160", s2-s ) )
247 found |= 1;
248 else if( !strncmp( s, "SHA1", s2-s ) )
249 found |= 2;
250 else if( !strncmp( s, "MD5", s2-s ) )
251 found |= 4;
252 else if( !strncmp( s, "SHA256", s2-s ) )
253 found |= 8;
254 else if( !strncmp( s, "SHA384", s2-s ) )
255 found |= 16;
256 else if( !strncmp( s, "SHA512", s2-s ) )
257 found |= 32;
258 else
259 return 0;
260 for(; *s2 && (*s2==' ' || *s2 == '\t'); s2++ )
262 if( *s2 && *s2 != ',' )
263 return 0;
264 if( *s2 )
265 s2++;
267 return found;
272 /****************
273 * Check whether this is a armor line.
274 * returns: -1 if it is not a armor header or the index number of the
275 * armor header.
277 static int
278 is_armor_header( byte *line, unsigned len )
280 const char *s;
281 byte *save_p, *p;
282 int save_c;
283 int i;
285 if( len < 15 )
286 return -1; /* too short */
287 if( memcmp( line, "-----", 5 ) )
288 return -1; /* no */
289 p = strstr( line+5, "-----");
290 if( !p )
291 return -1;
292 save_p = p;
293 p += 5;
295 /* Some mail programs on Windows seem to add spaces to the end of
296 the line. This becomes strict if --openpgp is set. */
298 if(!RFC2440)
299 while(*p==' ')
300 p++;
302 if( *p == '\r' )
303 p++;
304 if( *p == '\n' )
305 p++;
306 if( *p )
307 return -1; /* garbage after dashes */
308 save_c = *save_p; *save_p = 0;
309 p = line+5;
310 for(i=0; (s=head_strings[i]); i++ )
311 if( !strcmp(s, p) )
312 break;
313 *save_p = save_c;
314 if( !s )
315 return -1; /* unknown armor line */
317 if( opt.verbose > 1 )
318 log_info(_("armor: %s\n"), head_strings[i]);
319 return i;
324 /****************
325 * Parse a header lines
326 * Return 0: Empty line (end of header lines)
327 * -1: invalid header line
328 * >0: Good header line
330 static int
331 parse_header_line( armor_filter_context_t *afx, byte *line, unsigned int len )
333 byte *p;
334 int hashes=0;
335 unsigned int len2;
337 len2 = length_sans_trailing_ws( line, len );
338 if( !len2 ) {
339 afx->buffer_pos = len2; /* (it is not the fine way to do it here) */
340 return 0; /* WS only: same as empty line */
342 len = len2;
343 line[len2] = 0;
345 p = strchr( line, ':');
346 if( !p || !p[1] ) {
347 log_error(_("invalid armor header: "));
348 print_string( stderr, line, len, 0 );
349 putc('\n', stderr);
350 return -1;
353 if( opt.verbose ) {
354 log_info(_("armor header: "));
355 print_string( stderr, line, len, 0 );
356 putc('\n', stderr);
359 if( afx->in_cleartext ) {
360 if( (hashes=parse_hash_header( line )) )
361 afx->hashes |= hashes;
362 else if( strlen(line) > 15 && !memcmp( line, "NotDashEscaped:", 15 ) )
363 afx->not_dash_escaped = 1;
364 else {
365 log_error(_("invalid clearsig header\n"));
366 return -1;
369 return 1;
374 /* figure out whether the data is armored or not */
375 static int
376 check_input( armor_filter_context_t *afx, iobuf_t a )
378 int rc = 0;
379 int i;
380 byte *line;
381 unsigned len;
382 unsigned maxlen;
383 int hdr_line = -1;
385 /* read the first line to see whether this is armored data */
386 maxlen = MAX_LINELEN;
387 len = afx->buffer_len = iobuf_read_line( a, &afx->buffer,
388 &afx->buffer_size, &maxlen );
389 line = afx->buffer;
390 if( !maxlen ) {
391 /* line has been truncated: assume not armored */
392 afx->inp_checked = 1;
393 afx->inp_bypass = 1;
394 return 0;
397 if( !len ) {
398 return -1; /* eof */
401 /* (the line is always a C string but maybe longer) */
402 if( *line == '\n' || ( len && (*line == '\r' && line[1]=='\n') ) )
404 else if( !is_armored( line ) ) {
405 afx->inp_checked = 1;
406 afx->inp_bypass = 1;
407 return 0;
410 /* find the armor header */
411 while(len) {
412 i = is_armor_header( line, len );
413 if( i >= 0 && !(afx->only_keyblocks && i != 1 && i != 5 && i != 6 )) {
414 hdr_line = i;
415 if( hdr_line == BEGIN_SIGNED_MSG_IDX ) {
416 if( afx->in_cleartext ) {
417 log_error(_("nested clear text signatures\n"));
418 rc = GPG_ERR_INV_ARMOR;
420 afx->in_cleartext = 1;
422 break;
424 /* read the next line (skip all truncated lines) */
425 do {
426 maxlen = MAX_LINELEN;
427 afx->buffer_len = iobuf_read_line( a, &afx->buffer,
428 &afx->buffer_size, &maxlen );
429 line = afx->buffer;
430 len = afx->buffer_len;
431 } while( !maxlen );
434 /* parse the header lines */
435 while(len) {
436 /* read the next line (skip all truncated lines) */
437 do {
438 maxlen = MAX_LINELEN;
439 afx->buffer_len = iobuf_read_line( a, &afx->buffer,
440 &afx->buffer_size, &maxlen );
441 line = afx->buffer;
442 len = afx->buffer_len;
443 } while( !maxlen );
445 i = parse_header_line( afx, line, len );
446 if( i <= 0 ) {
447 if( i )
448 rc = GPG_ERR_INV_ARMOR;
449 break;
454 if( rc )
455 invalid_armor();
456 else if( afx->in_cleartext )
457 afx->faked = 1;
458 else {
459 afx->inp_checked = 1;
460 afx->crc = CRCINIT;
461 afx->idx = 0;
462 afx->radbuf[0] = 0;
465 return rc;
470 /****************
471 * Fake a literal data packet and wait for the next armor line
472 * fixme: empty line handling and null length clear text signature are
473 * not implemented/checked.
475 static int
476 fake_packet( armor_filter_context_t *afx, iobuf_t a,
477 size_t *retn, byte *buf, size_t size )
479 int rc = 0;
480 size_t len = 0;
481 int lastline = 0;
482 unsigned maxlen, n;
483 byte *p;
485 len = 2; /* reserve 2 bytes for the length header */
486 size -= 2; /* and 2 for the terminating header */
487 while( !rc && len < size ) {
488 /* copy what we have in the line buffer */
489 if( afx->faked == 1 )
490 afx->faked++; /* skip the first (empty) line */
491 else {
492 while( len < size && afx->buffer_pos < afx->buffer_len )
493 buf[len++] = afx->buffer[afx->buffer_pos++];
494 if( len >= size )
495 continue;
498 /* read the next line */
499 maxlen = MAX_LINELEN;
500 afx->buffer_pos = 0;
501 afx->buffer_len = iobuf_read_line( a, &afx->buffer,
502 &afx->buffer_size, &maxlen );
503 if( !afx->buffer_len ) {
504 rc = -1; /* eof (should not happen) */
505 continue;
507 if( !maxlen )
508 afx->truncated++;
509 if( !afx->not_dash_escaped ) {
510 int crlf;
511 p = afx->buffer;
512 n = afx->buffer_len;
513 crlf = n > 1 && p[n-2] == '\r' && p[n-1]=='\n';
515 /* PGP2 does not treat a tab as white space character */
516 afx->buffer_len = trim_trailing_chars( p, n,
517 afx->pgp2mode ? " \r\n" : " \t\r\n");
518 /* the buffer is always allocated with enough space to append
519 * the removed [CR], LF and a Nul
520 * The reason for this complicated procedure is to keep at least
521 * the original type of lineending - handling of the removed
522 * trailing spaces seems to be impossible in our method
523 * of faking a packet; either we have to use a temporary file
524 * or calculate the hash here in this module and somehow find
525 * a way to send the hash down the processing line (well, a special
526 * faked packet could do the job).
528 if( crlf )
529 afx->buffer[afx->buffer_len++] = '\r';
530 afx->buffer[afx->buffer_len++] = '\n';
531 afx->buffer[afx->buffer_len] = 0;
533 p = afx->buffer;
534 n = afx->buffer_len;
536 if( n > 2 && *p == '-' ) {
537 /* check for dash escaped or armor header */
538 if( p[1] == ' ' && !afx->not_dash_escaped ) {
539 /* issue a warning if it is not regular encoded */
540 if( p[2] != '-' && !( n > 6 && !memcmp(p+2, "From ", 5))) {
541 log_info(_("invalid dash escaped line: "));
542 print_string( stderr, p, n, 0 );
543 putc('\n', stderr);
545 afx->buffer_pos = 2; /* skip */
547 else if( n >= 15 && p[1] == '-' && p[2] == '-' && p[3] == '-' ) {
548 int type = is_armor_header( p, n );
549 if( afx->not_dash_escaped && type != BEGIN_SIGNATURE )
550 ; /* this is okay */
551 else {
552 if( type != BEGIN_SIGNATURE ) {
553 log_info(_("unexpected armor:"));
554 print_string( stderr, p, n, 0 );
555 putc('\n', stderr);
557 lastline = 1;
558 rc = -1;
564 buf[0] = (len-2) >> 8;
565 buf[1] = (len-2);
566 if( lastline ) { /* write last (ending) length header */
567 if( buf[0] || buf[1] ) { /* only if we have some text */
568 buf[len++] = 0;
569 buf[len++] = 0;
571 rc = 0;
572 afx->faked = 0;
573 afx->in_cleartext = 0;
574 /* and now read the header lines */
575 afx->buffer_pos = 0;
576 for(;;) {
577 int i;
579 /* read the next line (skip all truncated lines) */
580 do {
581 maxlen = MAX_LINELEN;
582 afx->buffer_len = iobuf_read_line( a, &afx->buffer,
583 &afx->buffer_size, &maxlen );
584 } while( !maxlen );
585 p = afx->buffer;
586 n = afx->buffer_len;
587 if( !n ) {
588 rc = -1;
589 break; /* eof */
591 i = parse_header_line( afx, p , n );
592 if( i <= 0 ) {
593 if( i )
594 invalid_armor();
595 break;
598 afx->inp_checked = 1;
599 afx->crc = CRCINIT;
600 afx->idx = 0;
601 afx->radbuf[0] = 0;
604 *retn = len;
605 return rc;
609 static int
610 invalid_crc(void)
612 if ( opt.ignore_crc_error )
613 return 0;
614 log_inc_errorcount();
615 return GPG_ERR_INV_ARMOR;
619 static int
620 radix64_read( armor_filter_context_t *afx, iobuf_t a, size_t *retn,
621 byte *buf, size_t size )
623 byte val;
624 int c=0, c2; /*init c because gcc is not clever enough for the continue*/
625 int checkcrc=0;
626 int rc = 0;
627 size_t n = 0;
628 int idx, i;
629 u32 crc;
631 crc = afx->crc;
632 idx = afx->idx;
633 val = afx->radbuf[0];
634 for( n=0; n < size; ) {
636 if( afx->buffer_pos < afx->buffer_len )
637 c = afx->buffer[afx->buffer_pos++];
638 else { /* read the next line */
639 unsigned maxlen = MAX_LINELEN;
640 afx->buffer_pos = 0;
641 afx->buffer_len = iobuf_read_line( a, &afx->buffer,
642 &afx->buffer_size, &maxlen );
643 if( !maxlen )
644 afx->truncated++;
645 if( !afx->buffer_len )
646 break; /* eof */
647 continue;
650 again:
651 if( c == '\n' || c == ' ' || c == '\r' || c == '\t' )
652 continue;
653 else if( c == '=' ) { /* pad character: stop */
654 /* some mailers leave quoted-printable encoded characters
655 * so we try to workaround this */
656 if( afx->buffer_pos+2 < afx->buffer_len ) {
657 int cc1, cc2, cc3;
658 cc1 = afx->buffer[afx->buffer_pos];
659 cc2 = afx->buffer[afx->buffer_pos+1];
660 cc3 = afx->buffer[afx->buffer_pos+2];
661 if( isxdigit(cc1) && isxdigit(cc2)
662 && strchr( "=\n\r\t ", cc3 )) {
663 /* well it seems to be the case - adjust */
664 c = isdigit(cc1)? (cc1 - '0'): (ascii_toupper(cc1)-'A'+10);
665 c <<= 4;
666 c |= isdigit(cc2)? (cc2 - '0'): (ascii_toupper(cc2)-'A'+10);
667 afx->buffer_pos += 2;
668 afx->qp_detected = 1;
669 goto again;
673 if( idx == 1 )
674 buf[n++] = val;
675 checkcrc++;
676 break;
678 else if( (c = asctobin[(c2=c)]) == 255 ) {
679 log_error(_("invalid radix64 character %02x skipped\n"), c2);
680 continue;
682 switch(idx) {
683 case 0: val = c << 2; break;
684 case 1: val |= (c>>4)&3; buf[n++]=val;val=(c<<4)&0xf0;break;
685 case 2: val |= (c>>2)&15; buf[n++]=val;val=(c<<6)&0xc0;break;
686 case 3: val |= c&0x3f; buf[n++] = val; break;
688 idx = (idx+1) % 4;
691 for(i=0; i < n; i++ )
692 crc = (crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ buf[i]];
693 crc &= 0x00ffffff;
694 afx->crc = crc;
695 afx->idx = idx;
696 afx->radbuf[0] = val;
698 if( checkcrc ) {
699 afx->any_data = 1;
700 afx->inp_checked=0;
701 afx->faked = 0;
702 for(;;) { /* skip lf and pad characters */
703 if( afx->buffer_pos < afx->buffer_len )
704 c = afx->buffer[afx->buffer_pos++];
705 else { /* read the next line */
706 unsigned maxlen = MAX_LINELEN;
707 afx->buffer_pos = 0;
708 afx->buffer_len = iobuf_read_line( a, &afx->buffer,
709 &afx->buffer_size, &maxlen );
710 if( !maxlen )
711 afx->truncated++;
712 if( !afx->buffer_len )
713 break; /* eof */
714 continue;
716 if( c == '\n' || c == ' ' || c == '\r'
717 || c == '\t' || c == '=' )
718 continue;
719 break;
721 if( c == -1 )
722 log_error(_("premature eof (no CRC)\n"));
723 else {
724 u32 mycrc = 0;
725 idx = 0;
726 do {
727 if( (c = asctobin[c]) == 255 )
728 break;
729 switch(idx) {
730 case 0: val = c << 2; break;
731 case 1: val |= (c>>4)&3; mycrc |= val << 16;val=(c<<4)&0xf0;break;
732 case 2: val |= (c>>2)&15; mycrc |= val << 8;val=(c<<6)&0xc0;break;
733 case 3: val |= c&0x3f; mycrc |= val; break;
735 for(;;) {
736 if( afx->buffer_pos < afx->buffer_len )
737 c = afx->buffer[afx->buffer_pos++];
738 else { /* read the next line */
739 unsigned maxlen = MAX_LINELEN;
740 afx->buffer_pos = 0;
741 afx->buffer_len = iobuf_read_line( a, &afx->buffer,
742 &afx->buffer_size,
743 &maxlen );
744 if( !maxlen )
745 afx->truncated++;
746 if( !afx->buffer_len )
747 break; /* eof */
748 continue;
750 break;
752 if( !afx->buffer_len )
753 break; /* eof */
754 } while( ++idx < 4 );
755 if( c == -1 ) {
756 log_info(_("premature eof (in CRC)\n"));
757 rc = invalid_crc();
759 else if( idx != 4 ) {
760 log_info(_("malformed CRC\n"));
761 rc = invalid_crc();
763 else if( mycrc != afx->crc ) {
764 log_info (_("CRC error; %06lx - %06lx\n"),
765 (ulong)afx->crc, (ulong)mycrc);
766 rc = invalid_crc();
768 else {
769 rc = 0;
770 /* FIXME: Here we should emit another control packet,
771 * so that we know in mainproc that we are processing
772 * a clearsign message */
773 #if 0
774 for(rc=0;!rc;) {
775 rc = 0 /*check_trailer( &fhdr, c )*/;
776 if( !rc ) {
777 if( (c=iobuf_get(a)) == -1 )
778 rc = 2;
781 if( rc == -1 )
782 rc = 0;
783 else if( rc == 2 ) {
784 log_error(_("premature eof (in Trailer)\n"));
785 rc = GPG_ERR_INV_ARMOR;
787 else {
788 log_error(_("error in trailer line\n"));
789 rc = GPG_ERR_INV_ARMOR;
791 #endif
796 if( !n )
797 rc = -1;
799 *retn = n;
800 return rc;
803 /****************
804 * This filter is used to handle the armor stuff
807 armor_filter( void *opaque, int control,
808 iobuf_t a, byte *buf, size_t *ret_len)
810 size_t size = *ret_len;
811 armor_filter_context_t *afx = opaque;
812 int rc=0, i, c;
813 byte radbuf[3];
814 int idx, idx2;
815 size_t n=0;
816 u32 crc;
817 #if 0
818 static FILE *fp ;
820 if( !fp ) {
821 fp = fopen("armor.out", "w");
822 assert(fp);
824 #endif
826 if( DBG_FILTER )
827 log_debug("armor-filter: control: %d\n", control );
828 if( control == IOBUFCTRL_UNDERFLOW && afx->inp_bypass ) {
829 n = 0;
830 if( afx->buffer_len ) {
831 for(; n < size && afx->buffer_pos < afx->buffer_len; n++ )
832 buf[n++] = afx->buffer[afx->buffer_pos++];
833 if( afx->buffer_pos >= afx->buffer_len )
834 afx->buffer_len = 0;
836 for(; n < size; n++ ) {
837 if( (c=iobuf_get(a)) == -1 )
838 break;
839 buf[n] = c & 0xff;
841 if( !n )
842 rc = -1;
843 *ret_len = n;
845 else if( control == IOBUFCTRL_UNDERFLOW ) {
846 /* We need some space for the faked packet. The minmum required
847 * size is ~18 + length of the session marker */
848 if( size < 50 )
849 BUG(); /* supplied buffer too short */
851 if( afx->faked )
852 rc = fake_packet( afx, a, &n, buf, size );
853 else if( !afx->inp_checked ) {
854 rc = check_input( afx, a );
855 if( afx->inp_bypass ) {
856 for(n=0; n < size && afx->buffer_pos < afx->buffer_len; )
857 buf[n++] = afx->buffer[afx->buffer_pos++];
858 if( afx->buffer_pos >= afx->buffer_len )
859 afx->buffer_len = 0;
860 if( !n )
861 rc = -1;
863 else if( afx->faked ) {
864 unsigned int hashes = afx->hashes;
865 const byte *sesmark;
866 size_t sesmarklen;
868 sesmark = get_session_marker( &sesmarklen );
869 if ( sesmarklen > 20 )
870 BUG();
872 /* the buffer is at least 15+n*15 bytes long, so it
873 * is easy to construct the packets */
875 hashes &= 1|2|4|8|16|32|64;
876 if( !hashes ) {
877 hashes |= 4; /* default to MD 5 */
878 /* This is non-ideal since PGP 5-8 have the same
879 end-of-line bugs as PGP 2. However, we only
880 enable pgp2mode if there is no Hash: header. */
881 if( opt.pgp2_workarounds )
882 afx->pgp2mode = 1;
884 n=0;
885 /* first a gpg control packet */
886 buf[n++] = 0xff; /* new format, type 63, 1 length byte */
887 n++; /* see below */
888 memcpy(buf+n, sesmark, sesmarklen ); n+= sesmarklen;
889 buf[n++] = CTRLPKT_CLEARSIGN_START;
890 buf[n++] = afx->not_dash_escaped? 0:1; /* sigclass */
891 if( hashes & 1 )
892 buf[n++] = DIGEST_ALGO_RMD160;
893 if( hashes & 2 )
894 buf[n++] = DIGEST_ALGO_SHA1;
895 if( hashes & 4 )
896 buf[n++] = DIGEST_ALGO_MD5;
897 if( hashes & 8 )
898 buf[n++] = DIGEST_ALGO_SHA256;
899 if( hashes & 16 )
900 buf[n++] = DIGEST_ALGO_SHA384;
901 if( hashes & 32 )
902 buf[n++] = DIGEST_ALGO_SHA512;
903 buf[1] = n - 2;
905 /* followed by a plaintext packet */
906 buf[n++] = 0xaf; /* old packet format, type 11, var length */
907 buf[n++] = 0; /* set the length header */
908 buf[n++] = 6;
909 buf[n++] = 't'; /* canonical text mode */
910 buf[n++] = 0; /* namelength */
911 memset(buf+n, 0, 4); /* timestamp */
912 n += 4;
914 else if( !rc )
915 rc = radix64_read( afx, a, &n, buf, size );
917 else
918 rc = radix64_read( afx, a, &n, buf, size );
919 #if 0
920 if( n )
921 if( fwrite(buf, n, 1, fp ) != 1 )
922 BUG();
923 #endif
924 *ret_len = n;
926 else if( control == IOBUFCTRL_FLUSH && !afx->cancel ) {
927 if( !afx->status ) { /* write the header line */
928 const char *s;
929 STRLIST comment = opt.comments;
931 if( afx->what >= DIM(head_strings) )
932 log_bug("afx->what=%d", afx->what);
933 iobuf_writestr(a, "-----");
934 iobuf_writestr(a, head_strings[afx->what] );
935 iobuf_writestr(a, "-----" LF );
936 if( !opt.no_version )
937 iobuf_writestr(a, "Version: GnuPG v" VERSION " ("
938 PRINTABLE_OS_NAME ")" LF );
940 /* Write the comment string. */
941 for(s=comment? comment->d:NULL; comment;
942 comment=comment->next,s=comment->d)
944 iobuf_writestr(a, "Comment: " );
945 for ( ; *s; s++ )
947 if( *s == '\n' )
948 iobuf_writestr(a, "\\n" );
949 else if( *s == '\r' )
950 iobuf_writestr(a, "\\r" );
951 else if( *s == '\v' )
952 iobuf_writestr(a, "\\v" );
953 else
954 iobuf_put(a, *s );
956 iobuf_writestr(a, LF );
959 if ( afx->hdrlines ) {
960 for ( s = afx->hdrlines; *s; s++ ) {
961 #ifdef HAVE_DOSISH_SYSTEM
962 if ( *s == '\n' )
963 iobuf_put( a, '\r');
964 #endif
965 iobuf_put(a, *s );
968 iobuf_writestr(a, LF );
969 afx->status++;
970 afx->idx = 0;
971 afx->idx2 = 0;
972 afx->crc = CRCINIT;
975 crc = afx->crc;
976 idx = afx->idx;
977 idx2 = afx->idx2;
978 for(i=0; i < idx; i++ )
979 radbuf[i] = afx->radbuf[i];
981 for(i=0; i < size; i++ )
982 crc = (crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ buf[i]];
983 crc &= 0x00ffffff;
985 for( ; size; buf++, size-- ) {
986 radbuf[idx++] = *buf;
987 if( idx > 2 ) {
988 idx = 0;
989 c = bintoasc[(*radbuf >> 2) & 077];
990 iobuf_put(a, c);
991 c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
992 iobuf_put(a, c);
993 c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
994 iobuf_put(a, c);
995 c = bintoasc[radbuf[2]&077];
996 iobuf_put(a, c);
997 if( ++idx2 >= (64/4) ) { /* pgp doesn't like 72 here */
998 iobuf_writestr(a, LF );
999 idx2=0;
1003 for(i=0; i < idx; i++ )
1004 afx->radbuf[i] = radbuf[i];
1005 afx->idx = idx;
1006 afx->idx2 = idx2;
1007 afx->crc = crc;
1009 else if( control == IOBUFCTRL_INIT ) {
1010 if( !is_initialized )
1011 initialize();
1013 else if( control == IOBUFCTRL_CANCEL ) {
1014 afx->cancel = 1;
1016 else if( control == IOBUFCTRL_FREE ) {
1017 if( afx->cancel )
1019 else if( afx->status ) { /* pad, write cecksum, and bottom line */
1020 crc = afx->crc;
1021 idx = afx->idx;
1022 idx2 = afx->idx2;
1023 for(i=0; i < idx; i++ )
1024 radbuf[i] = afx->radbuf[i];
1025 if( idx ) {
1026 c = bintoasc[(*radbuf>>2)&077];
1027 iobuf_put(a, c);
1028 if( idx == 1 ) {
1029 c = bintoasc[((*radbuf << 4) & 060) & 077];
1030 iobuf_put(a, c);
1031 iobuf_put(a, '=');
1032 iobuf_put(a, '=');
1034 else { /* 2 */
1035 c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1]>>4)&017))&077];
1036 iobuf_put(a, c);
1037 c = bintoasc[((radbuf[1] << 2) & 074) & 077];
1038 iobuf_put(a, c);
1039 iobuf_put(a, '=');
1041 if( ++idx2 >= (64/4) ) { /* pgp doesn't like 72 here */
1042 iobuf_writestr(a, LF );
1043 idx2=0;
1046 /* may need a linefeed */
1047 if( idx2 )
1048 iobuf_writestr(a, LF );
1049 /* write the CRC */
1050 iobuf_put(a, '=');
1051 radbuf[0] = crc >>16;
1052 radbuf[1] = crc >> 8;
1053 radbuf[2] = crc;
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 iobuf_writestr(a, LF );
1063 /* and the the trailer */
1064 if( afx->what >= DIM(tail_strings) )
1065 log_bug("afx->what=%d", afx->what);
1066 iobuf_writestr(a, "-----");
1067 iobuf_writestr(a, tail_strings[afx->what] );
1068 iobuf_writestr(a, "-----" LF );
1070 else if( !afx->any_data && !afx->inp_bypass ) {
1071 log_error(_("no valid OpenPGP data found.\n"));
1072 afx->no_openpgp_data = 1;
1073 write_status_text( STATUS_NODATA, "1" );
1075 if( afx->truncated )
1076 log_info(_("invalid armor: line longer than %d characters\n"),
1077 MAX_LINELEN );
1078 /* issue an error to enforce dissemination of correct software */
1079 if( afx->qp_detected )
1080 log_error(_("quoted printable character in armor - "
1081 "probably a buggy MTA has been used\n") );
1082 xfree ( afx->buffer );
1083 afx->buffer = NULL;
1085 else if( control == IOBUFCTRL_DESC )
1086 *(char**)buf = "armor_filter";
1087 return rc;
1091 /****************
1092 * create a radix64 encoded string.
1094 char *
1095 make_radix64_string( const byte *data, size_t len )
1097 char *buffer, *p;
1099 buffer = p = xmalloc ( (len+2)/3*4 + 1 );
1100 for( ; len >= 3 ; len -= 3, data += 3 ) {
1101 *p++ = bintoasc[(data[0] >> 2) & 077];
1102 *p++ = bintoasc[(((data[0] <<4)&060)|((data[1] >> 4)&017))&077];
1103 *p++ = bintoasc[(((data[1]<<2)&074)|((data[2]>>6)&03))&077];
1104 *p++ = bintoasc[data[2]&077];
1106 if( len == 2 ) {
1107 *p++ = bintoasc[(data[0] >> 2) & 077];
1108 *p++ = bintoasc[(((data[0] <<4)&060)|((data[1] >> 4)&017))&077];
1109 *p++ = bintoasc[((data[1]<<2)&074)];
1111 else if( len == 1 ) {
1112 *p++ = bintoasc[(data[0] >> 2) & 077];
1113 *p++ = bintoasc[(data[0] <<4)&060];
1115 *p = 0;
1116 return buffer;
1120 /***********************************************
1121 * For the pipemode command we can't use the armor filter for various
1122 * reasons, so we use this new unarmor_pump stuff to remove the armor
1125 enum unarmor_state_e {
1126 STA_init = 0,
1127 STA_bypass,
1128 STA_wait_newline,
1129 STA_wait_dash,
1130 STA_first_dash,
1131 STA_compare_header,
1132 STA_found_header_wait_newline,
1133 STA_skip_header_lines,
1134 STA_skip_header_lines_non_ws,
1135 STA_read_data,
1136 STA_wait_crc,
1137 STA_read_crc,
1138 STA_ready
1141 struct unarmor_pump_s {
1142 enum unarmor_state_e state;
1143 byte val;
1144 int checkcrc;
1145 int pos; /* counts from 0..3 */
1146 u32 crc;
1147 u32 mycrc; /* the one store in the data */
1152 UnarmorPump
1153 unarmor_pump_new (void)
1155 UnarmorPump x;
1157 if( !is_initialized )
1158 initialize();
1159 x = xcalloc (1,sizeof *x);
1160 return x;
1163 void
1164 unarmor_pump_release (UnarmorPump x)
1166 xfree (x);
1170 * Get the next character from the ascii armor taken from the IOBUF
1171 * created earlier by unarmor_pump_new().
1172 * Return: c = Character
1173 * 256 = ignore this value
1174 * -1 = End of current armor
1175 * -2 = Premature EOF (not used)
1176 * -3 = Invalid armor
1179 unarmor_pump (UnarmorPump x, int c)
1181 int rval = 256; /* default is to ignore the return value */
1183 switch (x->state) {
1184 case STA_init:
1186 byte tmp[1];
1187 tmp[0] = c;
1188 if ( is_armored (tmp) )
1189 x->state = c == '-'? STA_first_dash : STA_wait_newline;
1190 else {
1191 x->state = STA_bypass;
1192 return c;
1195 break;
1196 case STA_bypass:
1197 return c; /* return here to avoid crc calculation */
1198 case STA_wait_newline:
1199 if (c == '\n')
1200 x->state = STA_wait_dash;
1201 break;
1202 case STA_wait_dash:
1203 x->state = c == '-'? STA_first_dash : STA_wait_newline;
1204 break;
1205 case STA_first_dash: /* just need for initalization */
1206 x->pos = 0;
1207 x->state = STA_compare_header;
1208 case STA_compare_header:
1209 if ( "-----BEGIN PGP SIGNATURE-----"[++x->pos] == c ) {
1210 if ( x->pos == 28 )
1211 x->state = STA_found_header_wait_newline;
1213 else
1214 x->state = c == '\n'? STA_wait_dash : STA_wait_newline;
1215 break;
1216 case STA_found_header_wait_newline:
1217 /* to make CR,LF issues easier we simply allow for white space
1218 behind the 5 dashes */
1219 if ( c == '\n' )
1220 x->state = STA_skip_header_lines;
1221 else if ( c != '\r' && c != ' ' && c != '\t' )
1222 x->state = STA_wait_dash; /* garbage after the header line */
1223 break;
1224 case STA_skip_header_lines:
1225 /* i.e. wait for one empty line */
1226 if ( c == '\n' ) {
1227 x->state = STA_read_data;
1228 x->crc = CRCINIT;
1229 x->val = 0;
1230 x->pos = 0;
1232 else if ( c != '\r' && c != ' ' && c != '\t' )
1233 x->state = STA_skip_header_lines_non_ws;
1234 break;
1235 case STA_skip_header_lines_non_ws:
1236 /* like above but we already encountered non white space */
1237 if ( c == '\n' )
1238 x->state = STA_skip_header_lines;
1239 break;
1240 case STA_read_data:
1241 /* fixme: we don't check for the trailing dash lines but rely
1242 * on the armor stop characters */
1243 if( c == '\n' || c == ' ' || c == '\r' || c == '\t' )
1244 break; /* skip all kind of white space */
1246 if( c == '=' ) { /* pad character: stop */
1247 if( x->pos == 1 ) /* in this case val has some value */
1248 rval = x->val;
1249 x->state = STA_wait_crc;
1250 break;
1254 int c2;
1255 if( (c = asctobin[(c2=c)]) == 255 ) {
1256 log_error(_("invalid radix64 character %02x skipped\n"), c2);
1257 break;
1261 switch(x->pos) {
1262 case 0:
1263 x->val = c << 2;
1264 break;
1265 case 1:
1266 x->val |= (c>>4)&3;
1267 rval = x->val;
1268 x->val = (c<<4)&0xf0;
1269 break;
1270 case 2:
1271 x->val |= (c>>2)&15;
1272 rval = x->val;
1273 x->val = (c<<6)&0xc0;
1274 break;
1275 case 3:
1276 x->val |= c&0x3f;
1277 rval = x->val;
1278 break;
1280 x->pos = (x->pos+1) % 4;
1281 break;
1282 case STA_wait_crc:
1283 if( c == '\n' || c == ' ' || c == '\r' || c == '\t' || c == '=' )
1284 break; /* skip ws and pad characters */
1285 /* assume that we are at the next line */
1286 x->state = STA_read_crc;
1287 x->pos = 0;
1288 x->mycrc = 0;
1289 case STA_read_crc:
1290 if( (c = asctobin[c]) == 255 ) {
1291 rval = -1; /* ready */
1292 if( x->crc != x->mycrc ) {
1293 log_info (_("CRC error; %06lx - %06lx\n"),
1294 (ulong)x->crc, (ulong)x->mycrc);
1295 if ( invalid_crc() )
1296 rval = -3;
1298 x->state = STA_ready; /* not sure whether this is correct */
1299 break;
1302 switch(x->pos) {
1303 case 0:
1304 x->val = c << 2;
1305 break;
1306 case 1:
1307 x->val |= (c>>4)&3;
1308 x->mycrc |= x->val << 16;
1309 x->val = (c<<4)&0xf0;
1310 break;
1311 case 2:
1312 x->val |= (c>>2)&15;
1313 x->mycrc |= x->val << 8;
1314 x->val = (c<<6)&0xc0;
1315 break;
1316 case 3:
1317 x->val |= c&0x3f;
1318 x->mycrc |= x->val;
1319 break;
1321 x->pos = (x->pos+1) % 4;
1322 break;
1323 case STA_ready:
1324 rval = -1;
1325 break;
1328 if ( !(rval & ~255) ) { /* compute the CRC */
1329 x->crc = (x->crc << 8) ^ crc_table[((x->crc >> 16)&0xff) ^ rval];
1330 x->crc &= 0x00ffffff;
1333 return rval;