Coverage Report

Created: 2026-02-09 07:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gnupg/g10/armor.c
Line
Count
Source
1
/* armor.c - Armor filter
2
 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
3
 *               2007 Free Software Foundation, Inc.
4
 *
5
 * This file is part of GnuPG.
6
 *
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 3 of the License, or
10
 * (at your option) any later version.
11
 *
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.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, see <https://www.gnu.org/licenses/>.
19
 */
20
21
#include <config.h>
22
#include <stdio.h>
23
#include <stdlib.h>
24
#include <string.h>
25
#include <errno.h>
26
#include <ctype.h>
27
28
#include "gpg.h"
29
#include "../common/status.h"
30
#include "../common/iobuf.h"
31
#include "../common/util.h"
32
#include "filter.h"
33
#include "packet.h"
34
#include "options.h"
35
#include "main.h"
36
#include "../common/i18n.h"
37
38
1.06k
#define MAX_LINELEN 20000
39
40
static const byte bintoasc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
41
                               "abcdefghijklmnopqrstuvwxyz"
42
                               "0123456789+/";
43
static u32 asctobin[4][256]; /* runtime initialized */
44
static int is_initialized;
45
46
47
typedef enum {
48
    fhdrHASArmor = 0,
49
    fhdrNOArmor,
50
    fhdrINIT,
51
    fhdrINITCont,
52
    fhdrINITSkip,
53
    fhdrCHECKBegin,
54
    fhdrWAITHeader,
55
    fhdrWAITClearsig,
56
    fhdrSKIPHeader,
57
    fhdrCLEARSIG,
58
    fhdrREADClearsig,
59
    fhdrNullClearsig,
60
    fhdrEMPTYClearsig,
61
    fhdrCHECKClearsig,
62
    fhdrCHECKClearsig2,
63
    fhdrCHECKDashEscaped,
64
    fhdrCHECKDashEscaped2,
65
    fhdrCHECKDashEscaped3,
66
    fhdrREADClearsigNext,
67
    fhdrENDClearsig,
68
    fhdrENDClearsigHelp,
69
    fhdrTESTSpaces,
70
    fhdrCLEARSIGSimple,
71
    fhdrCLEARSIGSimpleNext,
72
    fhdrTEXT,
73
    fhdrTEXTSimple,
74
    fhdrERROR,
75
    fhdrERRORShow,
76
    fhdrEOF
77
} fhdr_state_t;
78
79
80
/* if we encounter this armor string with this index, go
81
 * into a mode which fakes packets and wait for the next armor */
82
0
#define BEGIN_SIGNATURE 2
83
39
#define BEGIN_SIGNED_MSG_IDX 3
84
static char *head_strings[] = {
85
    "BEGIN PGP MESSAGE",
86
    "BEGIN PGP PUBLIC KEY BLOCK",
87
    "BEGIN PGP SIGNATURE",
88
    "BEGIN PGP SIGNED MESSAGE",
89
    "BEGIN PGP ARMORED FILE",       /* gnupg extension */
90
    "BEGIN PGP PRIVATE KEY BLOCK",
91
    "BEGIN PGP SECRET KEY BLOCK",   /* only used by pgp2 */
92
    NULL
93
};
94
static char *tail_strings[] = {
95
    "END PGP MESSAGE",
96
    "END PGP PUBLIC KEY BLOCK",
97
    "END PGP SIGNATURE",
98
    "END dummy",
99
    "END PGP ARMORED FILE",
100
    "END PGP PRIVATE KEY BLOCK",
101
    "END PGP SECRET KEY BLOCK",
102
    NULL
103
};
104
105
106
static int armor_filter ( void *opaque, int control,
107
                          iobuf_t chain, byte *buf, size_t *ret_len);
108
109
110
111

112
/* Create a new context for armor filters.  */
113
armor_filter_context_t *
114
new_armor_context (void)
115
8
{
116
8
  armor_filter_context_t *afx;
117
8
  gpg_error_t err;
118
119
8
  afx = xcalloc (1, sizeof *afx);
120
8
  if (afx)
121
8
    {
122
8
      err = gcry_md_open (&afx->crc_md, GCRY_MD_CRC24_RFC2440, 0);
123
8
      if (err != 0)
124
0
  {
125
0
    log_error ("gcry_md_open failed for GCRY_MD_CRC24_RFC2440: %s",
126
0
        gpg_strerror (err));
127
0
    xfree (afx);
128
0
    return NULL;
129
0
  }
130
131
8
      afx->refcount = 1;
132
8
    }
133
134
8
  return afx;
135
8
}
136
137
/* Release an armor filter context.  Passing NULL is explicitly
138
   allowed and a no-op.  */
139
void
140
release_armor_context (armor_filter_context_t *afx)
141
19
{
142
19
  if (!afx)
143
3
    return;
144
19
  log_assert (afx->refcount);
145
16
  if ( --afx->refcount )
146
8
    return;
147
8
  gcry_md_close (afx->crc_md);
148
8
  xfree (afx);
149
8
}
150
151
/* Push the armor filter onto the iobuf stream IOBUF.  */
152
int
153
push_armor_filter (armor_filter_context_t *afx, iobuf_t iobuf)
154
8
{
155
8
  int rc;
156
157
8
  afx->refcount++;
158
8
  rc = iobuf_push_filter (iobuf, armor_filter, afx);
159
8
  if (rc)
160
0
    afx->refcount--;
161
8
  return rc;
162
8
}
163
164
165
/* This function returns true if the armor filter detected that the
166
 * input was indeed armored.  Gives a valid result only after the
167
 * first PGP packet has been read.  */
168
int
169
was_armored (armor_filter_context_t *afx)
170
0
{
171
0
  return (afx && !afx->inp_bypass);
172
0
}
173
174
175
176
static void
177
initialize(void)
178
1
{
179
1
    u32 i;
180
1
    const byte *s;
181
182
    /* Build the helptable for radix64 to bin conversion.  Value 0xffffffff is
183
       used to detect invalid characters.  */
184
1
    memset (asctobin, 0xff, sizeof(asctobin));
185
65
    for(s=bintoasc,i=0; *s; s++,i++ )
186
64
      {
187
64
  asctobin[0][*s] = i << (0 * 6);
188
64
  asctobin[1][*s] = i << (1 * 6);
189
64
  asctobin[2][*s] = i << (2 * 6);
190
64
  asctobin[3][*s] = i << (3 * 6);
191
64
      }
192
193
1
    is_initialized=1;
194
1
}
195
196
197
static inline u32
198
get_afx_crc (armor_filter_context_t *afx)
199
0
{
200
0
  const byte *crc_buf;
201
0
  u32 crc;
202
203
0
  crc_buf = gcry_md_read (afx->crc_md, GCRY_MD_CRC24_RFC2440);
204
205
0
  crc = crc_buf[0];
206
0
  crc <<= 8;
207
0
  crc |= crc_buf[1];
208
0
  crc <<= 8;
209
0
  crc |= crc_buf[2];
210
211
0
  return crc;
212
0
}
213
214
215
/*
216
 * Check whether this is an armored file.  See also
217
 * parse-packet.c for details on this code.
218
 *
219
 * Note that the buffer BUF needs to be at least 2 bytes long.  If in
220
 * doubt that the second byte to 0.
221
 *
222
 * Returns: True if it seems to be armored
223
 */
224
static int
225
is_armored (const byte *buf)
226
33
{
227
33
  int ctb, pkttype;
228
33
  int indeterminate_length_allowed;
229
230
33
    ctb = *buf;
231
33
    if( !(ctb & 0x80) )
232
      /* The most significant bit of the CTB must be set.  Since it is
233
         cleared, this is not a binary OpenPGP message.  Assume it is
234
         armored.  */
235
25
      return 1;
236
237
8
    pkttype =  ctb & 0x40 ? (ctb & 0x3f) : ((ctb>>2)&0xf);
238
8
    switch( pkttype ) {
239
0
      case PKT_PUBKEY_ENC:
240
0
      case PKT_SIGNATURE:
241
0
      case PKT_SYMKEY_ENC:
242
0
      case PKT_ONEPASS_SIG:
243
0
      case PKT_SECRET_KEY:
244
0
      case PKT_PUBLIC_KEY:
245
0
      case PKT_SECRET_SUBKEY:
246
0
      case PKT_MARKER:
247
0
      case PKT_RING_TRUST:
248
0
      case PKT_USER_ID:
249
0
      case PKT_PUBLIC_SUBKEY:
250
0
      case PKT_ATTRIBUTE:
251
0
      case PKT_MDC:
252
0
  indeterminate_length_allowed = 0;
253
0
        break;
254
255
0
      case PKT_COMPRESSED:
256
2
      case PKT_ENCRYPTED:
257
2
      case PKT_ENCRYPTED_MDC:
258
2
      case PKT_ENCRYPTED_AEAD:
259
2
      case PKT_PLAINTEXT:
260
2
      case PKT_OLD_COMMENT:
261
2
      case PKT_COMMENT:
262
6
      case PKT_GPG_CONTROL:
263
6
  indeterminate_length_allowed = 1;
264
6
        break;
265
266
2
      default:
267
        /* Invalid packet type.  */
268
2
        return 1;
269
8
    }
270
271
6
    if (! indeterminate_length_allowed)
272
      /* It is only legal to use an indeterminate length with a few
273
         packet types.  If a packet uses an indeterminate length, but
274
         that is not allowed, then the data is not valid binary
275
         OpenPGP data.  */
276
0
      {
277
0
        int new_format;
278
0
        int indeterminate_length;
279
280
0
        new_format = !! (ctb & (1 << 6));
281
0
        if (new_format)
282
0
          indeterminate_length = (buf[1] >= 224 && buf[1] < 255);
283
0
        else
284
0
          indeterminate_length = (ctb & 3) == 3;
285
286
0
        if (indeterminate_length)
287
0
          return 1;
288
0
      }
289
290
    /* The first CTB seems legit.  It is probably not armored
291
       data.  */
292
6
    return 0;
293
6
}
294
295
296
/****************
297
 * Try to check whether the iobuf is armored
298
 * Returns true if this may be the case; the caller should use the
299
 *     filter to do further processing.
300
 */
301
int
302
use_armor_filter( IOBUF a )
303
14
{
304
14
    byte buf[2];
305
14
    int n;
306
307
    /* fixme: there might be a problem with iobuf_peek */
308
14
    n = iobuf_peek (a, buf, 2);
309
14
    if( n == -1 )
310
0
  return 0; /* EOF, doesn't matter whether armored or not */
311
14
    if( !n )
312
0
  return 1; /* can't check it: try armored */
313
14
    if (n != 2)
314
0
  return 0; /* short buffer */
315
14
    return is_armored(buf);
316
14
}
317
318
319
320
321
static void
322
invalid_armor(void)
323
0
{
324
0
    write_status(STATUS_BADARMOR);
325
0
    g10_exit(1); /* stop here */
326
0
}
327
328
329
/****************
330
 * check whether the armor header is valid on a signed message.
331
 * this is for security reasons: the header lines are not included in the
332
 * hash and by using some creative formatting rules, Mallory could fake
333
 * any text at the beginning of a document; assuming it is read with
334
 * a simple viewer. We only allow the Hash Header.
335
 */
336
static int
337
parse_hash_header( const char *line )
338
0
{
339
0
    const char *s, *s2;
340
0
    unsigned found = 0;
341
342
0
    if( strlen(line) < 6  || strlen(line) > 60 )
343
0
  return 0; /* too short or too long */
344
0
    if( memcmp( line, "Hash:", 5 ) )
345
0
  return 0; /* invalid header */
346
347
0
    for(s=line+5;;s=s2) {
348
0
  for(; *s && (*s==' ' || *s == '\t'); s++ )
349
0
      ;
350
0
  if( !*s )
351
0
      break;
352
0
  for(s2=s+1; *s2 && *s2!=' ' && *s2 != '\t' && *s2 != ','; s2++ )
353
0
      ;
354
0
  if( !strncmp( s, "RIPEMD160", s2-s ) )
355
0
      found |= 1;
356
0
  else if( !strncmp( s, "SHA1", s2-s ) )
357
0
      found |= 2;
358
0
  else if( !strncmp( s, "SHA224", s2-s ) )
359
0
      found |= 8;
360
0
  else if( !strncmp( s, "SHA256", s2-s ) )
361
0
      found |= 16;
362
0
  else if( !strncmp( s, "SHA384", s2-s ) )
363
0
      found |= 32;
364
0
  else if( !strncmp( s, "SHA512", s2-s ) )
365
0
      found |= 64;
366
0
  else
367
0
      return 0;
368
0
  for(; *s2 && (*s2==' ' || *s2 == '\t'); s2++ )
369
0
      ;
370
0
  if( *s2 && *s2 != ',' )
371
0
      return 0;
372
0
  if( *s2 )
373
0
      s2++;
374
0
    }
375
0
    return found;
376
0
}
377
378
/* Returns true if this is a valid armor tag as per RFC-2440bis-21. */
379
static int
380
is_armor_tag(const char *line)
381
19
{
382
19
  if(strncmp(line,"Version",7)==0
383
9
     || strncmp(line,"Comment",7)==0
384
9
     || strncmp(line,"MessageID",9)==0
385
9
     || strncmp(line,"Hash",4)==0
386
9
     || strncmp(line,"Charset",7)==0)
387
10
    return 1;
388
389
9
  return 0;
390
19
}
391
392
/****************
393
 * Check whether this is a armor line.  Returns: -1 if it is not a
394
 * armor header, 42 if it is a generic header, or the index number of
395
 * the armor header.
396
 */
397
static int
398
is_armor_header( byte *line, unsigned len )
399
582
{
400
582
    const char *s;
401
582
    byte *save_p, *p;
402
582
    int save_c;
403
582
    int i;
404
405
582
    if( len < 15 )
406
255
  return -1; /* too short */
407
327
    if( memcmp( line, "-----", 5 ) )
408
259
  return -1; /* no */
409
68
    p = strstr( line+5, "-----");
410
68
    if( !p )
411
29
  return -1;
412
39
    save_p = p;
413
39
    p += 5;
414
415
    /* Some Windows environments seem to add whitespace to the end of
416
       the line, so we strip it here.  This becomes strict if
417
       --rfc2440 is set since 2440 reads "The header lines, therefore,
418
       MUST start at the beginning of a line, and MUST NOT have text
419
       following them on the same line."  It is unclear whether "text"
420
       refers to all text or just non-whitespace text.  4880 clarified
421
       this was only non-whitespace text. */
422
423
39
    if(RFC2440)
424
0
      {
425
0
  if( *p == '\r' )
426
0
    p++;
427
0
  if( *p == '\n' )
428
0
    p++;
429
0
      }
430
39
    else
431
78
      while(*p==' ' || *p=='\r' || *p=='\n' || *p=='\t')
432
39
  p++;
433
434
39
    if( *p )
435
0
  return -1; /* garbage after dashes */
436
39
    save_c = *save_p; *save_p = 0;
437
39
    p = line+5;
438
78
    for(i=0; (s=head_strings[i]); i++ )
439
78
  if( !strcmp(s, p) )
440
39
      break;
441
39
    *save_p = save_c;
442
39
    if (!s)
443
0
      {
444
0
        if (!strncmp (p, "BEGIN ", 6))
445
0
          return 42;
446
0
  return -1; /* unknown armor line */
447
0
      }
448
449
39
    if( opt.verbose > 1 )
450
39
  log_info(_("armor: %s\n"), head_strings[i]);
451
39
    return i;
452
39
}
453
454
455
456
/****************
457
 * Parse a header lines
458
 * Return 0: Empty line (end of header lines)
459
 *   -1: invalid header line
460
 *   >0: Good header line
461
 */
462
static int
463
parse_header_line( armor_filter_context_t *afx, byte *line, unsigned int len )
464
58
{
465
58
    byte *p;
466
58
    int hashes=0;
467
58
    unsigned int len2;
468
469
58
    len2 = length_sans_trailing_ws ( line, len );
470
58
    if( !len2 ) {
471
39
        afx->buffer_pos = len2;  /* (it is not the fine way to do it here) */
472
39
  return 0; /* WS only: same as empty line */
473
39
    }
474
475
    /*
476
      This is fussy.  The spec says that a header line is delimited
477
      with a colon-space pair.  This means that a line such as
478
      "Comment: " (with nothing else) is actually legal as an empty
479
      string comment.  However, email and cut-and-paste being what it
480
      is, that trailing space may go away.  Therefore, we accept empty
481
      headers delimited with only a colon.  --rfc2440, as always,
482
      makes this strict and enforces the colon-space pair. -dms
483
    */
484
485
19
    p = strchr( line, ':');
486
19
    if (!p && afx->dearmor_state)
487
0
      return 0; /* Special treatment in --dearmor mode.  */
488
19
    if( !p || (RFC2440 && p[1]!=' ')
489
19
  || (!RFC2440 && p[1]!=' ' && p[1]!='\n' && p[1]!='\r'))
490
0
      {
491
0
  log_error (_("invalid armor header: "));
492
0
  es_write_sanitized (log_get_stream (), line, len, NULL, NULL);
493
0
  log_printf ("\n");
494
0
  return -1;
495
0
      }
496
497
    /* Chop off the whitespace we detected before */
498
19
    len=len2;
499
19
    line[len2]='\0';
500
501
19
    if( opt.verbose ) {
502
0
  log_info(_("armor header: "));
503
0
  es_write_sanitized (log_get_stream (), line, len, NULL, NULL);
504
0
  log_printf ("\n");
505
0
    }
506
507
19
    if (afx->dearmor_mode)
508
0
      ;
509
19
    else if (afx->in_cleartext)
510
0
      {
511
0
  if( (hashes=parse_hash_header( line )) )
512
0
    afx->hashes |= hashes;
513
0
  else if ((opt.compat_flags & COMPAT_ALLOW_NOT_DASH_ESCAPED)
514
0
                 && strlen (line) > 15
515
0
                 && !memcmp( line, "NotDashEscaped:", 15 ) )
516
0
    afx->not_dash_escaped = 1;
517
0
  else
518
0
    {
519
0
      log_error(_("invalid clearsig header\n"));
520
0
      return -1;
521
0
    }
522
0
      }
523
19
    else if(!is_armor_tag(line))
524
9
      {
525
  /* Section 6.2: "Unknown keys should be reported to the user,
526
     but OpenPGP should continue to process the message."  Note
527
     that in a clearsigned message this applies to the signature
528
     part (i.e. "BEGIN PGP SIGNATURE") and not the signed data
529
     ("BEGIN PGP SIGNED MESSAGE").  The only key allowed in the
530
     signed data section is "Hash". */
531
532
9
  log_info(_("unknown armor header: "));
533
9
  es_write_sanitized (log_get_stream (), line, len, NULL, NULL);
534
9
  log_printf ("\n");
535
9
      }
536
537
19
    return 1;
538
19
}
539
540
541
542
/* figure out whether the data is armored or not */
543
static int
544
check_input( armor_filter_context_t *afx, IOBUF a )
545
46
{
546
46
    int rc = 0;
547
46
    int i;
548
46
    byte *line;
549
46
    unsigned len;
550
46
    unsigned maxlen;
551
46
    int hdr_line = -1;
552
553
    /* read the first line to see whether this is armored data */
554
46
    maxlen = MAX_LINELEN;
555
46
    len = afx->buffer_len = iobuf_read_line( a, &afx->buffer,
556
46
               &afx->buffer_size, &maxlen );
557
46
    line = afx->buffer;
558
46
    if( !maxlen ) {
559
  /* line has been truncated: assume not armored */
560
6
  afx->inp_checked = 1;
561
6
  afx->inp_bypass = 1;
562
6
  return 0;
563
6
    }
564
565
40
    if( !len ) {
566
0
  return -1; /* eof */
567
0
    }
568
569
    /* (the line is always a C string but maybe longer) */
570
40
    if( *line == '\n' || ( len && (*line == '\r' && line[1]=='\n') ) )
571
21
  ;
572
19
    else if (len >= 2 && !is_armored (line)) {
573
0
  afx->inp_checked = 1;
574
0
  afx->inp_bypass = 1;
575
0
  return 0;
576
0
    }
577
578
    /* find the armor header */
579
583
    while(len) {
580
582
  i = is_armor_header( line, len );
581
582
        if ( i == 42 ) {
582
0
            if (afx->dearmor_mode) {
583
0
                afx->dearmor_state = 1;
584
0
                break;
585
0
            }
586
0
        }
587
582
        else if (i >= 0
588
39
                 && !(afx->only_keyblocks && i != 1 && i != 5 && i != 6 )) {
589
39
      hdr_line = i;
590
39
      if( hdr_line == BEGIN_SIGNED_MSG_IDX ) {
591
0
          if( afx->in_cleartext ) {
592
0
        log_error(_("nested clear text signatures\n"));
593
0
        rc = gpg_error (GPG_ERR_INV_ARMOR);
594
0
                }
595
0
    afx->in_cleartext = 1;
596
0
      }
597
39
      break;
598
39
  }
599
600
  /* read the next line (skip all truncated lines) */
601
545
  do {
602
545
      maxlen = MAX_LINELEN;
603
545
      afx->buffer_len = iobuf_read_line( a, &afx->buffer,
604
545
                 &afx->buffer_size, &maxlen );
605
545
      line = afx->buffer;
606
545
      len = afx->buffer_len;
607
545
  } while( !maxlen );
608
543
    }
609
610
    /* Parse the header lines.  */
611
59
    while(len) {
612
  /* Read the next line (skip all truncated lines). */
613
58
  do {
614
58
      maxlen = MAX_LINELEN;
615
58
      afx->buffer_len = iobuf_read_line( a, &afx->buffer,
616
58
                 &afx->buffer_size, &maxlen );
617
58
      line = afx->buffer;
618
58
      len = afx->buffer_len;
619
58
  } while( !maxlen );
620
621
58
  i = parse_header_line( afx, line, len );
622
58
  if( i <= 0 ) {
623
39
      if (i && RFC2440)
624
0
    rc = GPG_ERR_INV_ARMOR;
625
39
      break;
626
39
  }
627
58
    }
628
629
630
40
    if( rc )
631
0
  invalid_armor();
632
40
    else if( afx->in_cleartext )
633
0
  afx->faked = 1;
634
40
    else {
635
40
  afx->inp_checked = 1;
636
40
  gcry_md_reset (afx->crc_md);
637
40
  afx->idx = 0;
638
40
  afx->radbuf[0] = 0;
639
40
    }
640
641
40
    return rc;
642
40
}
643
644
46
#define PARTIAL_CHUNK 512
645
0
#define PARTIAL_POW   9
646
647
/****************
648
 * Fake a literal data packet and wait for the next armor line
649
 * fixme: empty line handling and null length clear text signature are
650
 *    not implemented/checked.
651
 */
652
static int
653
fake_packet( armor_filter_context_t *afx, IOBUF a,
654
       size_t *retn, byte *buf, size_t size  )
655
0
{
656
0
    int rc = 0;
657
0
    size_t len = 0;
658
0
    int lastline = 0;
659
0
    unsigned maxlen, n;
660
0
    byte *p;
661
0
    byte tempbuf[PARTIAL_CHUNK];
662
0
    size_t tempbuf_len=0;
663
0
    int this_truncated;
664
665
0
    while( !rc && size-len>=(PARTIAL_CHUNK+1)) {
666
  /* copy what we have in the line buffer */
667
0
  if( afx->faked == 1 )
668
0
      afx->faked++; /* skip the first (empty) line */
669
0
  else
670
0
    {
671
      /* It's full, so write this partial chunk */
672
0
      if(tempbuf_len==PARTIAL_CHUNK)
673
0
        {
674
0
    buf[len++]=0xE0+PARTIAL_POW;
675
0
    memcpy(&buf[len],tempbuf,PARTIAL_CHUNK);
676
0
    len+=PARTIAL_CHUNK;
677
0
    tempbuf_len=0;
678
0
    continue;
679
0
        }
680
681
0
      while( tempbuf_len < PARTIAL_CHUNK
682
0
       && afx->buffer_pos < afx->buffer_len )
683
0
        tempbuf[tempbuf_len++] = afx->buffer[afx->buffer_pos++];
684
0
      if( tempbuf_len==PARTIAL_CHUNK )
685
0
        continue;
686
0
    }
687
688
  /* read the next line */
689
0
  maxlen = MAX_LINELEN;
690
0
  afx->buffer_pos = 0;
691
0
  afx->buffer_len = iobuf_read_line( a, &afx->buffer,
692
0
             &afx->buffer_size, &maxlen );
693
0
  if( !afx->buffer_len ) {
694
0
      rc = -1; /* eof (should not happen) */
695
0
      continue;
696
0
  }
697
0
  if( !maxlen )
698
0
          {
699
0
      afx->truncated++;
700
0
            this_truncated = 1;
701
0
          }
702
0
        else
703
0
          this_truncated = 0;
704
705
706
0
  p = afx->buffer;
707
0
  n = afx->buffer_len;
708
709
  /* Armor header or dash-escaped line? */
710
0
  if(p[0]=='-')
711
0
    {
712
      /* 2440bis-10: When reversing dash-escaping, an
713
         implementation MUST strip the string "- " if it occurs
714
         at the beginning of a line, and SHOULD warn on "-" and
715
         any character other than a space at the beginning of a
716
         line.  */
717
718
0
      if(p[1]==' ' && !afx->not_dash_escaped)
719
0
        {
720
    /* It's a dash-escaped line, so skip over the
721
       escape. */
722
0
    afx->buffer_pos = 2;
723
0
        }
724
0
      else if(p[1]=='-' && p[2]=='-' && p[3]=='-' && p[4]=='-')
725
0
        {
726
    /* Five dashes in a row mean it's probably armor
727
       header. */
728
0
    int type = is_armor_header( p, n );
729
0
                if (type == 42)
730
0
                  type = -1;  /* Only OpenPGP armors are expected.  */
731
0
    if( afx->not_dash_escaped && type != BEGIN_SIGNATURE )
732
0
      ; /* this is okay */
733
0
    else
734
0
      {
735
0
        if( type != BEGIN_SIGNATURE )
736
0
          {
737
0
      log_info(_("unexpected armor: "));
738
0
      es_write_sanitized (log_get_stream (), p, n,
739
0
                                            NULL, NULL);
740
0
      log_printf ("\n");
741
0
          }
742
743
0
        lastline = 1;
744
0
        rc = -1;
745
0
      }
746
0
        }
747
0
      else if(!afx->not_dash_escaped)
748
0
        {
749
    /* Bad dash-escaping. */
750
0
    log_info (_("invalid dash escaped line: "));
751
0
    es_write_sanitized (log_get_stream (), p, n, NULL, NULL);
752
0
    log_printf ("\n");
753
0
        }
754
0
    }
755
756
  /* Now handle the end-of-line canonicalization */
757
0
  if( !afx->not_dash_escaped || this_truncated)
758
0
    {
759
0
      int crlf = n > 1 && p[n-2] == '\r' && p[n-1]=='\n';
760
761
0
      afx->buffer_len=
762
0
        trim_trailing_chars( &p[afx->buffer_pos], n-afx->buffer_pos,
763
0
           " \t\r\n");
764
0
      afx->buffer_len+=afx->buffer_pos;
765
      /* the buffer is always allocated with enough space to append
766
       * the removed [CR], LF and a Nul
767
       * The reason for this complicated procedure is to keep at least
768
       * the original type of lineending - handling of the removed
769
       * trailing spaces seems to be impossible in our method
770
       * of faking a packet; either we have to use a temporary file
771
       * or calculate the hash here in this module and somehow find
772
       * a way to send the hash down the processing line (well, a special
773
       * faked packet could do the job).
774
             *
775
             * To make sure that a truncated line triggers a bad
776
             * signature error we replace a removed LF by a FF or
777
             * append a FF.  Right, this is a hack but better than a
778
             * global variable and way easier than to introduce a new
779
             * control packet or insert a line like "[truncated]\n"
780
             * into the filter output.
781
       */
782
0
      if( crlf )
783
0
        afx->buffer[afx->buffer_len++] = '\r';
784
0
      afx->buffer[afx->buffer_len++] = this_truncated? '\f':'\n';
785
0
      afx->buffer[afx->buffer_len] = '\0';
786
0
    }
787
0
    }
788
789
0
    if( lastline ) { /* write last (ending) length header */
790
0
        if(tempbuf_len<192)
791
0
    buf[len++]=tempbuf_len;
792
0
  else
793
0
    {
794
0
      buf[len++]=((tempbuf_len-192)/256) + 192;
795
0
      buf[len++]=(tempbuf_len-192) % 256;
796
0
    }
797
0
  memcpy(&buf[len],tempbuf,tempbuf_len);
798
0
  len+=tempbuf_len;
799
800
0
  rc = 0;
801
0
  afx->faked = 0;
802
0
  afx->in_cleartext = 0;
803
  /* and now read the header lines */
804
0
  afx->buffer_pos = 0;
805
0
  for(;;) {
806
0
      int i;
807
808
      /* read the next line (skip all truncated lines) */
809
0
      do {
810
0
    maxlen = MAX_LINELEN;
811
0
    afx->buffer_len = iobuf_read_line( a, &afx->buffer,
812
0
             &afx->buffer_size, &maxlen );
813
0
      } while( !maxlen );
814
0
      p = afx->buffer;
815
0
      n = afx->buffer_len;
816
0
      if( !n ) {
817
0
    rc = -1;
818
0
    break; /* eof */
819
0
      }
820
0
      i = parse_header_line( afx, p , n );
821
0
      if( i <= 0 ) {
822
0
    if( i )
823
0
        invalid_armor();
824
0
    break;
825
0
      }
826
0
  }
827
0
  afx->inp_checked = 1;
828
0
  gcry_md_reset (afx->crc_md);
829
0
  afx->idx = 0;
830
0
  afx->radbuf[0] = 0;
831
0
    }
832
833
0
    *retn = len;
834
0
    return rc;
835
0
}
836
837
838
static int
839
invalid_crc(void)
840
0
{
841
0
  if ( opt.ignore_crc_error )
842
0
    return 0;
843
0
  log_inc_errorcount();
844
0
  return gpg_error (GPG_ERR_INV_ARMOR);
845
0
}
846
847
848
static int
849
radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
850
        byte *buf, size_t size )
851
40
{
852
40
    byte val;
853
40
    int c;
854
40
    u32 binc;
855
40
    int checkcrc=0;
856
40
    int rc = 0;
857
40
    size_t n = 0;
858
40
    int idx, onlypad=0;
859
40
    int skip_fast = 0;
860
861
40
    idx = afx->idx;
862
40
    val = afx->radbuf[0];
863
12.8k
    for( n=0; n < size; ) {
864
865
12.8k
  if( afx->buffer_pos < afx->buffer_len )
866
12.4k
      c = afx->buffer[afx->buffer_pos++];
867
394
  else { /* read the next line */
868
394
      unsigned maxlen = MAX_LINELEN;
869
394
      afx->buffer_pos = 0;
870
394
      afx->buffer_len = iobuf_read_line( a, &afx->buffer,
871
394
                 &afx->buffer_size, &maxlen );
872
394
      if( !maxlen )
873
0
    afx->truncated++;
874
394
      if( !afx->buffer_len )
875
1
    break; /* eof */
876
393
      continue;
877
394
  }
878
879
12.4k
      again:
880
12.4k
  binc = asctobin[0][c];
881
882
12.4k
  if( binc != 0xffffffffUL )
883
5.58k
    {
884
5.58k
      if( idx == 0 && skip_fast == 0
885
2.17k
    && afx->buffer_pos + (16 - 1) < afx->buffer_len
886
1.68k
    && n + 12 < size)
887
1.68k
        {
888
    /* Fast path for radix64 to binary conversion.  */
889
1.68k
    u32 b0,b1,b2,b3;
890
891
    /* Speculatively load 15 more input bytes.  */
892
1.68k
    b0 = binc << (3 * 6);
893
1.68k
    b0 |= asctobin[2][afx->buffer[afx->buffer_pos + 0]];
894
1.68k
    b0 |= asctobin[1][afx->buffer[afx->buffer_pos + 1]];
895
1.68k
    b0 |= asctobin[0][afx->buffer[afx->buffer_pos + 2]];
896
1.68k
    b1  = asctobin[3][afx->buffer[afx->buffer_pos + 3]];
897
1.68k
    b1 |= asctobin[2][afx->buffer[afx->buffer_pos + 4]];
898
1.68k
    b1 |= asctobin[1][afx->buffer[afx->buffer_pos + 5]];
899
1.68k
    b1 |= asctobin[0][afx->buffer[afx->buffer_pos + 6]];
900
1.68k
    b2  = asctobin[3][afx->buffer[afx->buffer_pos + 7]];
901
1.68k
    b2 |= asctobin[2][afx->buffer[afx->buffer_pos + 8]];
902
1.68k
    b2 |= asctobin[1][afx->buffer[afx->buffer_pos + 9]];
903
1.68k
    b2 |= asctobin[0][afx->buffer[afx->buffer_pos + 10]];
904
1.68k
    b3  = asctobin[3][afx->buffer[afx->buffer_pos + 11]];
905
1.68k
    b3 |= asctobin[2][afx->buffer[afx->buffer_pos + 12]];
906
1.68k
    b3 |= asctobin[1][afx->buffer[afx->buffer_pos + 13]];
907
1.68k
    b3 |= asctobin[0][afx->buffer[afx->buffer_pos + 14]];
908
909
    /* Check if any of the input bytes were invalid. */
910
1.68k
    if( (b0 | b1 | b2 | b3) != 0xffffffffUL )
911
917
      {
912
        /* All 16 bytes are valid. */
913
917
        buf[n + 0] = b0 >> (2 * 8);
914
917
        buf[n + 1] = b0 >> (1 * 8);
915
917
        buf[n + 2] = b0 >> (0 * 8);
916
917
        buf[n + 3] = b1 >> (2 * 8);
917
917
        buf[n + 4] = b1 >> (1 * 8);
918
917
        buf[n + 5] = b1 >> (0 * 8);
919
917
        buf[n + 6] = b2 >> (2 * 8);
920
917
        buf[n + 7] = b2 >> (1 * 8);
921
917
        buf[n + 8] = b2 >> (0 * 8);
922
917
        buf[n + 9] = b3 >> (2 * 8);
923
917
        buf[n + 10] = b3 >> (1 * 8);
924
917
        buf[n + 11] = b3 >> (0 * 8);
925
917
        afx->buffer_pos += 16 - 1;
926
917
        n += 12;
927
917
        continue;
928
917
      }
929
769
    else if( b0 == 0xffffffffUL )
930
402
      {
931
        /* byte[1..3] have invalid character(s).  Switch to slow
932
           path.  */
933
402
        skip_fast = 1;
934
402
      }
935
367
    else if( b1 == 0xffffffffUL )
936
195
      {
937
        /* byte[4..7] have invalid character(s), first 4 bytes are
938
           valid.  */
939
195
        buf[n + 0] = b0 >> (2 * 8);
940
195
        buf[n + 1] = b0 >> (1 * 8);
941
195
        buf[n + 2] = b0 >> (0 * 8);
942
195
        afx->buffer_pos += 4 - 1;
943
195
        n += 3;
944
195
        skip_fast = 1;
945
195
        continue;
946
195
      }
947
172
    else if( b2 == 0xffffffffUL )
948
120
      {
949
        /* byte[8..11] have invalid character(s), first 8 bytes are
950
           valid.  */
951
120
        buf[n + 0] = b0 >> (2 * 8);
952
120
        buf[n + 1] = b0 >> (1 * 8);
953
120
        buf[n + 2] = b0 >> (0 * 8);
954
120
        buf[n + 3] = b1 >> (2 * 8);
955
120
        buf[n + 4] = b1 >> (1 * 8);
956
120
        buf[n + 5] = b1 >> (0 * 8);
957
120
        afx->buffer_pos += 8 - 1;
958
120
        n += 6;
959
120
        skip_fast = 1;
960
120
        continue;
961
120
      }
962
52
    else /*if( b3 == 0xffffffffUL )*/
963
52
      {
964
        /* byte[12..15] have invalid character(s), first 12 bytes
965
           are valid.  */
966
52
        buf[n + 0] = b0 >> (2 * 8);
967
52
        buf[n + 1] = b0 >> (1 * 8);
968
52
        buf[n + 2] = b0 >> (0 * 8);
969
52
        buf[n + 3] = b1 >> (2 * 8);
970
52
        buf[n + 4] = b1 >> (1 * 8);
971
52
        buf[n + 5] = b1 >> (0 * 8);
972
52
        buf[n + 6] = b2 >> (2 * 8);
973
52
        buf[n + 7] = b2 >> (1 * 8);
974
52
        buf[n + 8] = b2 >> (0 * 8);
975
52
        afx->buffer_pos += 12 - 1;
976
52
        n += 9;
977
52
        skip_fast = 1;
978
52
        continue;
979
52
      }
980
1.68k
        }
981
982
4.30k
      switch(idx)
983
4.30k
        {
984
1.08k
    case 0: val =  binc << 2; break;
985
1.08k
    case 1: val |= (binc>>4)&3; buf[n++]=val;val=(binc<<4)&0xf0;break;
986
1.08k
    case 2: val |= (binc>>2)&15; buf[n++]=val;val=(binc<<6)&0xc0;break;
987
1.06k
    case 3: val |= binc&0x3f; buf[n++] = val; break;
988
4.30k
        }
989
4.30k
      idx = (idx+1) % 4;
990
991
4.30k
      continue;
992
4.30k
    }
993
994
6.91k
  skip_fast = 0;
995
996
6.91k
  if( c == '\n' || c == ' ' || c == '\r' || c == '\t' )
997
778
      continue;
998
6.13k
  else if( c == '=' ) { /* pad character: stop */
999
      /* some mailers leave quoted-printable encoded characters
1000
       * so we try to workaround this */
1001
39
      if( afx->buffer_pos+2 < afx->buffer_len ) {
1002
18
    int cc1, cc2, cc3;
1003
18
    cc1 = afx->buffer[afx->buffer_pos];
1004
18
    cc2 = afx->buffer[afx->buffer_pos+1];
1005
18
    cc3 = afx->buffer[afx->buffer_pos+2];
1006
18
    if( isxdigit(cc1) && isxdigit(cc2)
1007
0
          && strchr( "=\n\r\t ", cc3 )) {
1008
        /* well it seems to be the case - adjust */
1009
0
        c = isdigit(cc1)? (cc1 - '0'): (ascii_toupper(cc1)-'A'+10);
1010
0
        c <<= 4;
1011
0
        c |= isdigit(cc2)? (cc2 - '0'): (ascii_toupper(cc2)-'A'+10);
1012
0
        afx->buffer_pos += 2;
1013
0
        afx->qp_detected = 1;
1014
0
        goto again;
1015
0
    }
1016
18
      }
1017
1018
            /* Occasionally a bug MTA will leave the = escaped as
1019
               =3D.  If the 4 characters following that are valid
1020
               Radix64 characters and they are following by a new
1021
               line, assume that this is the case and skip the
1022
               3D.  */
1023
39
            if (afx->buffer_pos + 6 < afx->buffer_len
1024
3
                && afx->buffer[afx->buffer_pos + 0] == '3'
1025
0
                && afx->buffer[afx->buffer_pos + 1] == 'D'
1026
0
                && asctobin[0][afx->buffer[afx->buffer_pos + 2]] != 0xffffffffUL
1027
0
                && asctobin[0][afx->buffer[afx->buffer_pos + 3]] != 0xffffffffUL
1028
0
                && asctobin[0][afx->buffer[afx->buffer_pos + 4]] != 0xffffffffUL
1029
0
                && asctobin[0][afx->buffer[afx->buffer_pos + 5]] != 0xffffffffUL
1030
0
                && afx->buffer[afx->buffer_pos + 6] == '\n')
1031
0
              {
1032
0
                afx->buffer_pos += 2;
1033
0
                afx->qp_detected = 1;
1034
0
              }
1035
1036
39
      if (!n)
1037
0
        onlypad = 1;
1038
1039
39
      if( idx == 1 )
1040
0
    buf[n++] = val;
1041
39
      checkcrc++;
1042
39
      break;
1043
39
  }
1044
6.09k
        else if (afx->buffer_pos == 1 && c == '-'
1045
0
                 && afx->buffer_len > 9
1046
0
                 && !strncmp (afx->buffer, "-----END ", 9)) {
1047
0
            break; /* End in --dearmor mode or No CRC.  */
1048
0
        }
1049
6.09k
  else {
1050
6.09k
      log_error(_("invalid radix64 character %02X skipped\n"), c);
1051
6.09k
      continue;
1052
6.09k
  }
1053
6.91k
    }
1054
1055
40
    afx->idx = idx;
1056
40
    afx->radbuf[0] = val;
1057
1058
40
    if( n )
1059
39
      {
1060
39
        gcry_md_write (afx->crc_md, buf, n);
1061
39
        afx->any_data = 1;
1062
39
      }
1063
1064
40
    if( checkcrc ) {
1065
39
  gcry_md_final (afx->crc_md);
1066
39
  afx->inp_checked=0;
1067
39
  afx->faked = 0;
1068
96
  for(;;) { /* skip lf and pad characters */
1069
96
      if( afx->buffer_pos < afx->buffer_len )
1070
75
    c = afx->buffer[afx->buffer_pos++];
1071
21
      else { /* read the next line */
1072
21
    unsigned maxlen = MAX_LINELEN;
1073
21
    afx->buffer_pos = 0;
1074
21
    afx->buffer_len = iobuf_read_line( a, &afx->buffer,
1075
21
               &afx->buffer_size, &maxlen );
1076
21
    if( !maxlen )
1077
0
        afx->truncated++;
1078
21
    if( !afx->buffer_len )
1079
0
        break; /* eof */
1080
21
    continue;
1081
21
      }
1082
75
      if( c == '\n' || c == ' ' || c == '\r'
1083
54
    || c == '\t' || c == '=' )
1084
36
    continue;
1085
39
      break;
1086
75
  }
1087
39
  if( !afx->buffer_len )
1088
39
      log_error(_("premature eof (no CRC)\n"));
1089
39
  else {
1090
39
      u32 mycrc = 0;
1091
39
      idx = 0;
1092
39
      do {
1093
39
    if( (binc = asctobin[0][c]) == 0xffffffffUL )
1094
39
        break;
1095
0
    switch(idx) {
1096
0
      case 0: val =  binc << 2; break;
1097
0
      case 1: val |= (binc>>4)&3; mycrc |= val << 16;val=(binc<<4)&0xf0;break;
1098
0
      case 2: val |= (binc>>2)&15; mycrc |= val << 8;val=(binc<<6)&0xc0;break;
1099
0
      case 3: val |= binc&0x3f; mycrc |= val; break;
1100
0
    }
1101
0
    for(;;) {
1102
0
        if( afx->buffer_pos < afx->buffer_len )
1103
0
      c = afx->buffer[afx->buffer_pos++];
1104
0
        else { /* read the next line */
1105
0
      unsigned maxlen = MAX_LINELEN;
1106
0
      afx->buffer_pos = 0;
1107
0
      afx->buffer_len = iobuf_read_line( a, &afx->buffer,
1108
0
                 &afx->buffer_size,
1109
0
                &maxlen );
1110
0
      if( !maxlen )
1111
0
          afx->truncated++;
1112
0
      if( !afx->buffer_len )
1113
0
          break; /* eof */
1114
0
      continue;
1115
0
        }
1116
0
        break;
1117
0
    }
1118
0
    if( !afx->buffer_len )
1119
0
        break; /* eof */
1120
0
      } while( ++idx < 4 );
1121
39
      if( !afx->buffer_len ) {
1122
0
    log_info(_("premature eof (in CRC)\n"));
1123
0
    rc = invalid_crc();
1124
0
      }
1125
39
      else if( idx == 0 ) {
1126
          /* No CRC at all is legal ("MAY") */
1127
39
          rc=0;
1128
39
      }
1129
0
      else if( idx != 4 ) {
1130
0
    log_info(_("malformed CRC\n"));
1131
0
    rc = invalid_crc();
1132
0
      }
1133
0
      else if( mycrc != get_afx_crc (afx) ) {
1134
0
    log_info (_("CRC error; %06lX - %06lX\n"),
1135
0
            (ulong)get_afx_crc (afx), (ulong)mycrc);
1136
0
    rc = invalid_crc();
1137
0
      }
1138
0
      else {
1139
0
    rc = 0;
1140
                /* FIXME: Here we should emit another control packet,
1141
                 * so that we know in mainproc that we are processing
1142
                 * a clearsign message */
1143
#if 0
1144
    for(rc=0;!rc;) {
1145
        rc = 0 /*check_trailer( &fhdr, c )*/;
1146
        if( !rc ) {
1147
      if( (c=iobuf_get(a)) == -1 )
1148
          rc = 2;
1149
        }
1150
    }
1151
    if( rc == -1 )
1152
        rc = 0;
1153
    else if( rc == 2 ) {
1154
        log_error(_("premature eof (in trailer)\n"));
1155
        rc = GPG_ERR_INV_ARMOR;
1156
    }
1157
    else {
1158
        log_error(_("error in trailer line\n"));
1159
        rc = GPG_ERR_INV_ARMOR;
1160
    }
1161
#endif
1162
0
      }
1163
39
  }
1164
39
    }
1165
1166
40
    if( !n && !onlypad )
1167
1
  rc = -1;
1168
1169
40
    *retn = n;
1170
40
    return rc;
1171
40
}
1172
1173
static void
1174
armor_output_buf_as_radix64 (armor_filter_context_t *afx, IOBUF a,
1175
           byte *buf, size_t size)
1176
0
{
1177
0
  byte radbuf[sizeof (afx->radbuf)];
1178
0
  byte outbuf[64 + sizeof (afx->eol)];
1179
0
  unsigned int eollen = strlen (afx->eol);
1180
0
  u32 in, in2;
1181
0
  int idx, idx2;
1182
0
  int i;
1183
1184
0
  idx = afx->idx;
1185
0
  idx2 = afx->idx2;
1186
0
  memcpy (radbuf, afx->radbuf, sizeof (afx->radbuf));
1187
1188
0
  if (size && (idx || idx2))
1189
0
    {
1190
      /* preload eol to outbuf buffer */
1191
0
      memcpy (outbuf + 4, afx->eol, sizeof (afx->eol));
1192
1193
0
      for (; size && (idx || idx2); buf++, size--)
1194
0
  {
1195
0
    radbuf[idx++] = *buf;
1196
0
    if (idx > 2)
1197
0
      {
1198
0
        idx = 0;
1199
0
        in = (u32)radbuf[0] << (2 * 8);
1200
0
        in |= (u32)radbuf[1] << (1 * 8);
1201
0
        in |= (u32)radbuf[2] << (0 * 8);
1202
0
        outbuf[0] = bintoasc[(in >> 18) & 077];
1203
0
        outbuf[1] = bintoasc[(in >> 12) & 077];
1204
0
        outbuf[2] = bintoasc[(in >> 6) & 077];
1205
0
        outbuf[3] = bintoasc[(in >> 0) & 077];
1206
0
        if (++idx2 >= (64/4))
1207
0
    { /* pgp doesn't like 72 here */
1208
0
      idx2=0;
1209
0
      iobuf_write (a, outbuf, 4 + eollen);
1210
0
    }
1211
0
        else
1212
0
    {
1213
0
      iobuf_write (a, outbuf, 4);
1214
0
    }
1215
0
      }
1216
0
  }
1217
0
    }
1218
1219
0
  if (size >= (64/4)*3)
1220
0
    {
1221
      /* preload eol to outbuf buffer */
1222
0
      memcpy (outbuf + 64, afx->eol, sizeof(afx->eol));
1223
1224
0
      do
1225
0
  {
1226
    /* idx and idx2 == 0 */
1227
1228
0
    for (i = 0; i < (64/8); i++)
1229
0
      {
1230
0
        in = (u32)buf[0] << (2 * 8);
1231
0
        in |= (u32)buf[1] << (1 * 8);
1232
0
        in |= (u32)buf[2] << (0 * 8);
1233
0
        in2 = (u32)buf[3] << (2 * 8);
1234
0
        in2 |= (u32)buf[4] << (1 * 8);
1235
0
        in2 |= (u32)buf[5] << (0 * 8);
1236
0
        outbuf[i*8+0] = bintoasc[(in >> 18) & 077];
1237
0
        outbuf[i*8+1] = bintoasc[(in >> 12) & 077];
1238
0
        outbuf[i*8+2] = bintoasc[(in >> 6) & 077];
1239
0
        outbuf[i*8+3] = bintoasc[(in >> 0) & 077];
1240
0
        outbuf[i*8+4] = bintoasc[(in2 >> 18) & 077];
1241
0
        outbuf[i*8+5] = bintoasc[(in2 >> 12) & 077];
1242
0
        outbuf[i*8+6] = bintoasc[(in2 >> 6) & 077];
1243
0
        outbuf[i*8+7] = bintoasc[(in2 >> 0) & 077];
1244
0
        buf+=6;
1245
0
        size-=6;
1246
0
      }
1247
1248
    /* pgp doesn't like 72 here */
1249
0
    iobuf_write (a, outbuf, 64 + eollen);
1250
0
  }
1251
0
      while (size >= (64/4)*3);
1252
1253
      /* restore eol for tail handling */
1254
0
      if (size)
1255
0
  memcpy (outbuf + 4, afx->eol, sizeof (afx->eol));
1256
0
    }
1257
1258
0
  for (; size; buf++, size--)
1259
0
    {
1260
0
      radbuf[idx++] = *buf;
1261
0
      if (idx > 2)
1262
0
  {
1263
0
    idx = 0;
1264
0
    in = (u32)radbuf[0] << (2 * 8);
1265
0
    in |= (u32)radbuf[1] << (1 * 8);
1266
0
    in |= (u32)radbuf[2] << (0 * 8);
1267
0
    outbuf[0] = bintoasc[(in >> 18) & 077];
1268
0
    outbuf[1] = bintoasc[(in >> 12) & 077];
1269
0
    outbuf[2] = bintoasc[(in >> 6) & 077];
1270
0
    outbuf[3] = bintoasc[(in >> 0) & 077];
1271
0
    if (++idx2 >= (64/4))
1272
0
      { /* pgp doesn't like 72 here */
1273
0
        idx2=0;
1274
0
        iobuf_write (a, outbuf, 4 + eollen);
1275
0
      }
1276
0
    else
1277
0
      {
1278
0
        iobuf_write (a, outbuf, 4);
1279
0
      }
1280
0
  }
1281
0
    }
1282
1283
0
  memcpy (afx->radbuf, radbuf, sizeof (afx->radbuf));
1284
0
  afx->idx = idx;
1285
0
  afx->idx2 = idx2;
1286
0
}
1287
1288
/****************
1289
 * This filter is used to handle the armor stuff
1290
 */
1291
static int
1292
armor_filter( void *opaque, int control,
1293
       IOBUF a, byte *buf, size_t *ret_len)
1294
64
{
1295
64
    size_t size = *ret_len;
1296
64
    armor_filter_context_t *afx = opaque;
1297
64
    int rc=0, c;
1298
64
    byte radbuf[3];
1299
64
    int  idx, idx2;
1300
64
    size_t n=0;
1301
64
    u32 crc;
1302
#if 0
1303
    static FILE *fp ;
1304
1305
    if( !fp ) {
1306
  fp = fopen("armor.out", "w");
1307
  log_assert(fp);
1308
    }
1309
#endif
1310
1311
64
    if( DBG_FILTER )
1312
64
  log_debug("armor-filter: control: %d\n", control );
1313
64
    if( control == IOBUFCTRL_UNDERFLOW && afx->inp_bypass ) {
1314
2
  n = 0;
1315
2
  if( afx->buffer_len ) {
1316
            /* Copy the data from AFX->BUFFER to BUF.  */
1317
0
            for(; n < size && afx->buffer_pos < afx->buffer_len;)
1318
0
                buf[n++] = afx->buffer[afx->buffer_pos++];
1319
0
      if( afx->buffer_pos >= afx->buffer_len )
1320
0
    afx->buffer_len = 0;
1321
0
  }
1322
        /* If there is still space in BUF, read directly into it.  */
1323
2
  for(; n < size; n++ ) {
1324
2
      if( (c=iobuf_get(a)) == -1 )
1325
2
    break;
1326
0
      buf[n] = c & 0xff;
1327
0
  }
1328
2
  if( !n )
1329
            /* We didn't get any data.  EOF.  */
1330
2
      rc = -1;
1331
2
  *ret_len = n;
1332
2
    }
1333
62
    else if( control == IOBUFCTRL_UNDERFLOW ) {
1334
        /* We need some space for the faked packet.  The minimum
1335
         * required size is the PARTIAL_CHUNK size plus a byte for the
1336
         * length itself */
1337
46
  if( size < PARTIAL_CHUNK+1 )
1338
0
      BUG(); /* supplied buffer too short */
1339
1340
46
  if( afx->faked )
1341
0
      rc = fake_packet( afx, a, &n, buf, size );
1342
46
  else if( !afx->inp_checked ) {
1343
46
      rc = check_input( afx, a );
1344
46
      if( afx->inp_bypass ) {
1345
120k
    for(n=0; n < size && afx->buffer_pos < afx->buffer_len; )
1346
119k
        buf[n++] = afx->buffer[afx->buffer_pos++];
1347
6
    if( afx->buffer_pos >= afx->buffer_len )
1348
6
        afx->buffer_len = 0;
1349
6
    if( !n )
1350
0
        rc = -1;
1351
6
      }
1352
40
      else if( afx->faked ) {
1353
0
          unsigned int hashes = afx->hashes;
1354
0
                const byte *sesmark;
1355
0
                size_t sesmarklen;
1356
1357
0
                sesmark = get_session_marker( &sesmarklen );
1358
0
                if ( sesmarklen > 20 )
1359
0
                    BUG();
1360
1361
    /* the buffer is at least 15+n*15 bytes long, so it
1362
     * is easy to construct the packets */
1363
1364
0
    hashes &= 1|2|8|16|32|64;
1365
0
    if( !hashes ) {
1366
0
        hashes |= 2;  /* Default to SHA-1. */
1367
0
    }
1368
0
    n=0;
1369
                /* First a gpg control packet... */
1370
0
                buf[n++] = 0xff; /* new format, type 63, 1 length byte */
1371
0
                n++;   /* see below */
1372
0
                memcpy(buf+n, sesmark, sesmarklen ); n+= sesmarklen;
1373
0
                buf[n++] = CTRLPKT_CLEARSIGN_START;
1374
0
                buf[n++] = afx->not_dash_escaped? 0:1; /* sigclass */
1375
0
                if( hashes & 1 )
1376
0
                    buf[n++] = DIGEST_ALGO_RMD160;
1377
0
                if( hashes & 2 )
1378
0
                    buf[n++] = DIGEST_ALGO_SHA1;
1379
0
                if( hashes & 8 )
1380
0
                    buf[n++] = DIGEST_ALGO_SHA224;
1381
0
                if( hashes & 16 )
1382
0
                    buf[n++] = DIGEST_ALGO_SHA256;
1383
0
                if( hashes & 32 )
1384
0
                    buf[n++] = DIGEST_ALGO_SHA384;
1385
0
                if( hashes & 64 )
1386
0
                    buf[n++] = DIGEST_ALGO_SHA512;
1387
0
                buf[1] = n - 2;
1388
1389
    /* ...followed by an invented plaintext packet.
1390
       Amusingly enough, this packet is not compliant with
1391
       2440 as the initial partial length is less than 512
1392
       bytes.  Of course, we'll accept it anyway ;) */
1393
1394
0
    buf[n++] = 0xCB; /* new packet format, type 11 */
1395
0
    buf[n++] = 0xE1; /* 2^1 == 2 bytes */
1396
0
    buf[n++] = 't';  /* canonical text mode */
1397
0
    buf[n++] = 0;  /* namelength */
1398
0
    buf[n++] = 0xE2; /* 2^2 == 4 more bytes */
1399
0
    memset(buf+n, 0, 4); /* timestamp */
1400
0
    n += 4;
1401
0
      }
1402
40
      else if( !rc )
1403
40
    rc = radix64_read( afx, a, &n, buf, size );
1404
46
  }
1405
0
  else
1406
0
      rc = radix64_read( afx, a, &n, buf, size );
1407
#if 0
1408
  if( n )
1409
      if( fwrite(buf, n, 1, fp ) != 1 )
1410
    BUG();
1411
#endif
1412
46
  *ret_len = n;
1413
46
    }
1414
16
    else if( control == IOBUFCTRL_FLUSH && !afx->cancel ) {
1415
0
  if( !afx->status ) { /* write the header line */
1416
0
      const char *s;
1417
0
      strlist_t comment=opt.comments;
1418
1419
0
      if( afx->what >= DIM(head_strings) )
1420
0
    log_bug("afx->what=%d", afx->what);
1421
0
      iobuf_writestr(a, "-----");
1422
0
      iobuf_writestr(a, head_strings[afx->what] );
1423
0
      iobuf_writestr(a, "-----" );
1424
0
      iobuf_writestr(a,afx->eol);
1425
0
      if (opt.emit_version)
1426
0
        {
1427
0
    iobuf_writestr (a, "Version: "GNUPG_NAME" v");
1428
0
                for (s=VERSION; *s && *s != '.'; s++)
1429
0
                  iobuf_writebyte (a, *s);
1430
0
                if (opt.emit_version > 1 && *s)
1431
0
                  {
1432
0
                    iobuf_writebyte (a, *s++);
1433
0
                    for (; *s && *s != '.'; s++)
1434
0
                      iobuf_writebyte (a, *s);
1435
0
                    if (opt.emit_version > 2)
1436
0
                      {
1437
0
                        for (; *s && *s != '-' && !spacep (s); s++)
1438
0
                          iobuf_writebyte (a, *s);
1439
0
                        if (opt.emit_version > 3)
1440
0
                          iobuf_writestr (a, " (" PRINTABLE_OS_NAME ")");
1441
0
                      }
1442
0
                  }
1443
0
    iobuf_writestr(a,afx->eol);
1444
0
        }
1445
1446
      /* write the comment strings */
1447
0
      for(;comment;comment=comment->next)
1448
0
        {
1449
0
    iobuf_writestr(a, "Comment: " );
1450
0
    for( s=comment->d; *s; s++ )
1451
0
      {
1452
0
        if( *s == '\n' )
1453
0
          iobuf_writestr(a, "\\n" );
1454
0
        else if( *s == '\r' )
1455
0
          iobuf_writestr(a, "\\r" );
1456
0
        else if( *s == '\v' )
1457
0
          iobuf_writestr(a, "\\v" );
1458
0
        else
1459
0
          iobuf_put(a, *s );
1460
0
      }
1461
1462
0
    iobuf_writestr(a,afx->eol);
1463
0
        }
1464
1465
0
      if ( afx->hdrlines ) {
1466
0
                for ( s = afx->hdrlines; *s; s++ ) {
1467
#ifdef HAVE_DOSISH_SYSTEM
1468
                    if ( *s == '\n' )
1469
                        iobuf_put( a, '\r');
1470
#endif
1471
0
                    iobuf_put(a, *s );
1472
0
                }
1473
0
            }
1474
1475
0
      iobuf_writestr(a,afx->eol);
1476
0
      afx->status++;
1477
0
      afx->idx = 0;
1478
0
      afx->idx2 = 0;
1479
0
      gcry_md_reset (afx->crc_md);
1480
0
  }
1481
1482
0
  if( size ) {
1483
0
      gcry_md_write (afx->crc_md, buf, size);
1484
0
      armor_output_buf_as_radix64 (afx, a, buf, size);
1485
0
        }
1486
0
    }
1487
16
    else if( control == IOBUFCTRL_INIT )
1488
8
      {
1489
8
  if( !is_initialized )
1490
1
    initialize();
1491
1492
  /* Figure out what we're using for line endings if the caller
1493
     didn't specify. */
1494
8
  if(afx->eol[0]==0)
1495
8
    {
1496
#ifdef HAVE_DOSISH_SYSTEM
1497
      afx->eol[0]='\r';
1498
      afx->eol[1]='\n';
1499
#else
1500
8
      afx->eol[0]='\n';
1501
8
#endif
1502
8
    }
1503
8
      }
1504
8
    else if( control == IOBUFCTRL_CANCEL ) {
1505
0
  afx->cancel = 1;
1506
0
    }
1507
8
    else if( control == IOBUFCTRL_FREE ) {
1508
8
  if( afx->cancel )
1509
0
      ;
1510
8
  else if( afx->status ) { /* pad, write checksum, and bottom line */
1511
0
      gcry_md_final (afx->crc_md);
1512
0
      crc = get_afx_crc (afx);
1513
0
      idx = afx->idx;
1514
0
      idx2 = afx->idx2;
1515
0
      if( idx ) {
1516
0
    c = bintoasc[(afx->radbuf[0]>>2)&077];
1517
0
    iobuf_put(a, c);
1518
0
    if( idx == 1 ) {
1519
0
        c = bintoasc[((afx->radbuf[0] << 4) & 060) & 077];
1520
0
        iobuf_put(a, c);
1521
0
        iobuf_put(a, '=');
1522
0
        iobuf_put(a, '=');
1523
0
    }
1524
0
    else { /* 2 */
1525
0
        c = bintoasc[(((afx->radbuf[0]<<4)&060)
1526
0
                                  |((afx->radbuf[1]>>4)&017))&077];
1527
0
        iobuf_put(a, c);
1528
0
        c = bintoasc[((afx->radbuf[1] << 2) & 074) & 077];
1529
0
        iobuf_put(a, c);
1530
0
        iobuf_put(a, '=');
1531
0
    }
1532
0
    if( ++idx2 >= (64/4) )
1533
0
      { /* pgp doesn't like 72 here */
1534
0
        iobuf_writestr(a,afx->eol);
1535
0
        idx2=0;
1536
0
      }
1537
0
      }
1538
      /* may need a linefeed */
1539
0
      if( idx2 )
1540
0
        iobuf_writestr(a,afx->eol);
1541
      /* write the CRC */
1542
0
      iobuf_put(a, '=');
1543
0
      radbuf[0] = crc >>16;
1544
0
      radbuf[1] = crc >> 8;
1545
0
      radbuf[2] = crc;
1546
0
      c = bintoasc[(*radbuf >> 2) & 077];
1547
0
      iobuf_put(a, c);
1548
0
      c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
1549
0
      iobuf_put(a, c);
1550
0
      c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
1551
0
      iobuf_put(a, c);
1552
0
      c = bintoasc[radbuf[2]&077];
1553
0
      iobuf_put(a, c);
1554
0
      iobuf_writestr(a,afx->eol);
1555
      /* and the trailer */
1556
0
      if( afx->what >= DIM(tail_strings) )
1557
0
    log_bug("afx->what=%d", afx->what);
1558
0
      iobuf_writestr(a, "-----");
1559
0
      iobuf_writestr(a, tail_strings[afx->what] );
1560
0
      iobuf_writestr(a, "-----" );
1561
0
      iobuf_writestr(a,afx->eol);
1562
0
  }
1563
8
  else if( !afx->any_data && !afx->inp_bypass ) {
1564
0
      log_error(_("no valid OpenPGP data found.\n"));
1565
0
      afx->no_openpgp_data = 1;
1566
0
      write_status_text( STATUS_NODATA, "1" );
1567
0
  }
1568
        /* Note that in a cleartext signature truncated lines in the
1569
         * plaintext are detected and propagated to the signature
1570
         * checking code by inserting a \f into the plaintext.  We do
1571
         * not use log_info here because some of the truncated lines
1572
         * are harmless.  */
1573
8
  if( afx->truncated )
1574
8
      log_info(_("invalid armor: line longer than %d characters\n"),
1575
0
          MAX_LINELEN );
1576
  /* issue an error to enforce dissemination of correct software */
1577
8
  if( afx->qp_detected )
1578
8
      log_error(_("quoted printable character in armor - "
1579
0
      "probably a buggy MTA has been used\n") );
1580
8
  xfree( afx->buffer );
1581
8
  afx->buffer = NULL;
1582
8
        release_armor_context (afx);
1583
8
    }
1584
0
    else if( control == IOBUFCTRL_DESC )
1585
0
        mem2str (buf, "armor_filter", *ret_len);
1586
64
    return rc;
1587
64
}
1588
1589
1590
/****************
1591
 * create a radix64 encoded string.
1592
 */
1593
char *
1594
make_radix64_string( const byte *data, size_t len )
1595
0
{
1596
0
    char *buffer, *p;
1597
1598
0
    buffer = p = xmalloc( (len+2)/3*4 + 1 );
1599
0
    for( ; len >= 3 ; len -= 3, data += 3 ) {
1600
0
  *p++ = bintoasc[(data[0] >> 2) & 077];
1601
0
  *p++ = bintoasc[(((data[0] <<4)&060)|((data[1] >> 4)&017))&077];
1602
0
  *p++ = bintoasc[(((data[1]<<2)&074)|((data[2]>>6)&03))&077];
1603
0
  *p++ = bintoasc[data[2]&077];
1604
0
    }
1605
0
    if( len == 2 ) {
1606
0
  *p++ = bintoasc[(data[0] >> 2) & 077];
1607
0
  *p++ = bintoasc[(((data[0] <<4)&060)|((data[1] >> 4)&017))&077];
1608
0
  *p++ = bintoasc[((data[1]<<2)&074)];
1609
0
    }
1610
0
    else if( len == 1 ) {
1611
0
  *p++ = bintoasc[(data[0] >> 2) & 077];
1612
0
  *p++ = bintoasc[(data[0] <<4)&060];
1613
0
    }
1614
0
    *p = 0;
1615
0
    return buffer;
1616
0
}