Coverage Report

Created: 2026-09-03 07:09

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
66.4k
#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
10.4k
#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
6.94k
{
116
6.94k
  armor_filter_context_t *afx;
117
6.94k
  gpg_error_t err;
118
119
6.94k
  afx = xcalloc (1, sizeof *afx);
120
6.94k
  if (afx)
121
6.94k
    {
122
6.94k
      err = gcry_md_open (&afx->crc_md, GCRY_MD_CRC24_RFC2440, 0);
123
6.94k
      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
6.94k
      afx->refcount = 1;
132
6.94k
    }
133
134
6.94k
  return afx;
135
6.94k
}
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
13.8k
{
142
13.8k
  if (!afx)
143
0
    return;
144
13.8k
  log_assert (afx->refcount);
145
13.8k
  if ( --afx->refcount )
146
6.94k
    return;
147
6.94k
  gcry_md_close (afx->crc_md);
148
6.94k
  xfree (afx);
149
6.94k
}
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
6.94k
{
155
6.94k
  int rc;
156
157
6.94k
  afx->refcount++;
158
6.94k
  rc = iobuf_push_filter (iobuf, armor_filter, afx);
159
6.94k
  if (rc)
160
0
    afx->refcount--;
161
6.94k
  return rc;
162
6.94k
}
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
444
{
200
444
  const byte *crc_buf;
201
444
  u32 crc;
202
203
444
  crc_buf = gcry_md_read (afx->crc_md, GCRY_MD_CRC24_RFC2440);
204
205
444
  crc = crc_buf[0];
206
444
  crc <<= 8;
207
444
  crc |= crc_buf[1];
208
444
  crc <<= 8;
209
444
  crc |= crc_buf[2];
210
211
444
  return crc;
212
444
}
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
15.6k
{
227
15.6k
  int ctb, pkttype;
228
15.6k
  int indeterminate_length_allowed;
229
230
15.6k
    ctb = *buf;
231
15.6k
    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
9.38k
      return 1;
236
237
6.21k
    pkttype =  ctb & 0x40 ? (ctb & 0x3f) : ((ctb>>2)&0xf);
238
6.21k
    switch( pkttype ) {
239
154
      case PKT_PUBKEY_ENC:
240
1.15k
      case PKT_SIGNATURE:
241
1.31k
      case PKT_SYMKEY_ENC:
242
1.38k
      case PKT_ONEPASS_SIG:
243
1.91k
      case PKT_SECRET_KEY:
244
3.51k
      case PKT_PUBLIC_KEY:
245
3.79k
      case PKT_SECRET_SUBKEY:
246
3.89k
      case PKT_MARKER:
247
4.16k
      case PKT_RING_TRUST:
248
4.36k
      case PKT_USER_ID:
249
4.38k
      case PKT_PUBLIC_SUBKEY:
250
4.66k
      case PKT_ATTRIBUTE:
251
4.72k
      case PKT_MDC:
252
4.72k
  indeterminate_length_allowed = 0;
253
4.72k
        break;
254
255
35
      case PKT_COMPRESSED:
256
255
      case PKT_ENCRYPTED:
257
426
      case PKT_ENCRYPTED_MDC:
258
529
      case PKT_ENCRYPTED_AEAD:
259
748
      case PKT_PLAINTEXT:
260
788
      case PKT_OLD_COMMENT:
261
858
      case PKT_COMMENT:
262
980
      case PKT_GPG_CONTROL:
263
980
  indeterminate_length_allowed = 1;
264
980
        break;
265
266
511
      default:
267
        /* Invalid packet type.  */
268
511
        return 1;
269
6.21k
    }
270
271
5.70k
    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
4.72k
      {
277
4.72k
        int new_format;
278
4.72k
        int indeterminate_length;
279
280
4.72k
        new_format = !! (ctb & (1 << 6));
281
4.72k
        if (new_format)
282
2.27k
          indeterminate_length = (buf[1] >= 224 && buf[1] < 255);
283
2.45k
        else
284
2.45k
          indeterminate_length = (ctb & 3) == 3;
285
286
4.72k
        if (indeterminate_length)
287
88
          return 1;
288
4.72k
      }
289
290
    /* The first CTB seems legit.  It is probably not armored
291
       data.  */
292
5.61k
    return 0;
293
5.70k
}
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
0
{
304
0
    byte buf[2];
305
0
    int n;
306
307
    /* fixme: there might be a problem with iobuf_peek */
308
0
    n = iobuf_peek (a, buf, 2);
309
0
    if( n == -1 )
310
0
  return 0; /* EOF, doesn't matter whether armored or not */
311
0
    if( !n )
312
0
  return 1; /* can't check it: try armored */
313
0
    if (n != 2)
314
0
  return 0; /* short buffer */
315
0
    return is_armored(buf);
316
0
}
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
4.00k
{
382
4.00k
  if(strncmp(line,"Version",7)==0
383
3.42k
     || strncmp(line,"Comment",7)==0
384
3.05k
     || strncmp(line,"MessageID",9)==0
385
2.12k
     || strncmp(line,"Hash",4)==0
386
1.35k
     || strncmp(line,"Charset",7)==0)
387
3.00k
    return 1;
388
389
1.00k
  return 0;
390
4.00k
}
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
25.1k
{
400
25.1k
    const char *s;
401
25.1k
    byte *save_p, *p;
402
25.1k
    int save_c;
403
25.1k
    int i;
404
405
25.1k
    if( len < 15 )
406
10.1k
  return -1; /* too short */
407
14.9k
    if( memcmp( line, "-----", 5 ) )
408
1.55k
  return -1; /* no */
409
13.4k
    p = strstr( line+5, "-----");
410
13.4k
    if( !p )
411
841
  return -1;
412
12.5k
    save_p = p;
413
12.5k
    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
12.5k
    if(RFC2440)
424
0
      {
425
0
  if( *p == '\r' )
426
0
    p++;
427
0
  if( *p == '\n' )
428
0
    p++;
429
0
      }
430
12.5k
    else
431
24.8k
      while(*p==' ' || *p=='\r' || *p=='\n' || *p=='\t')
432
12.2k
  p++;
433
434
12.5k
    if( *p )
435
675
  return -1; /* garbage after dashes */
436
11.9k
    save_c = *save_p; *save_p = 0;
437
11.9k
    p = line+5;
438
39.9k
    for(i=0; (s=head_strings[i]); i++ )
439
38.6k
  if( !strcmp(s, p) )
440
10.6k
      break;
441
11.9k
    *save_p = save_c;
442
11.9k
    if (!s)
443
1.25k
      {
444
1.25k
        if (!strncmp (p, "BEGIN ", 6))
445
751
          return 42;
446
499
  return -1; /* unknown armor line */
447
1.25k
      }
448
449
10.6k
    if( opt.verbose > 1 )
450
10.6k
  log_info(_("armor: %s\n"), head_strings[i]);
451
10.6k
    return i;
452
11.9k
}
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
14.4k
{
465
14.4k
    byte *p;
466
14.4k
    int hashes=0;
467
14.4k
    unsigned int len2;
468
469
14.4k
    len2 = length_sans_trailing_ws ( line, len );
470
14.4k
    if( !len2 ) {
471
5.27k
        afx->buffer_pos = len2;  /* (it is not the fine way to do it here) */
472
5.27k
  return 0; /* WS only: same as empty line */
473
5.27k
    }
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
9.19k
    p = strchr( line, ':');
486
9.19k
    if (!p && afx->dearmor_state)
487
0
      return 0; /* Special treatment in --dearmor mode.  */
488
9.19k
    if( !p || (RFC2440 && p[1]!=' ')
489
4.60k
  || (!RFC2440 && p[1]!=' ' && p[1]!='\n' && p[1]!='\r'))
490
5.18k
      {
491
5.18k
  log_error (_("invalid armor header: "));
492
5.18k
  es_write_sanitized (log_get_stream (), line, len, NULL, NULL);
493
5.18k
  log_printf ("\n");
494
5.18k
  return -1;
495
5.18k
      }
496
497
    /* Chop off the whitespace we detected before */
498
4.00k
    len=len2;
499
4.00k
    line[len2]='\0';
500
501
4.00k
    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
4.00k
    if (afx->dearmor_mode)
508
0
      ;
509
4.00k
    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
4.00k
    else if(!is_armor_tag(line))
524
1.00k
      {
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
1.00k
  log_info(_("unknown armor header: "));
533
1.00k
  es_write_sanitized (log_get_stream (), line, len, NULL, NULL);
534
1.00k
  log_printf ("\n");
535
1.00k
      }
536
537
4.00k
    return 1;
538
4.00k
}
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
16.5k
{
546
16.5k
    int rc = 0;
547
16.5k
    int i;
548
16.5k
    byte *line;
549
16.5k
    unsigned len;
550
16.5k
    unsigned maxlen;
551
16.5k
    int hdr_line = -1;
552
553
    /* read the first line to see whether this is armored data */
554
16.5k
    maxlen = MAX_LINELEN;
555
16.5k
    len = afx->buffer_len = iobuf_read_line( a, &afx->buffer,
556
16.5k
               &afx->buffer_size, &maxlen );
557
16.5k
    line = afx->buffer;
558
16.5k
    if( !maxlen ) {
559
  /* line has been truncated: assume not armored */
560
0
  afx->inp_checked = 1;
561
0
  afx->inp_bypass = 1;
562
0
  return 0;
563
0
    }
564
565
16.5k
    if( !len ) {
566
80
  return -1; /* eof */
567
80
    }
568
569
    /* (the line is always a C string but maybe longer) */
570
16.5k
    if( *line == '\n' || ( len && (*line == '\r' && line[1]=='\n') ) )
571
883
  ;
572
15.6k
    else if (len >= 2 && !is_armored (line)) {
573
5.61k
  afx->inp_checked = 1;
574
5.61k
  afx->inp_bypass = 1;
575
5.61k
  return 0;
576
5.61k
    }
577
578
    /* find the armor header */
579
25.5k
    while(len) {
580
25.1k
  i = is_armor_header( line, len );
581
25.1k
        if ( i == 42 ) {
582
751
            if (afx->dearmor_mode) {
583
0
                afx->dearmor_state = 1;
584
0
                break;
585
0
            }
586
751
        }
587
24.3k
        else if (i >= 0
588
10.6k
                 && !(afx->only_keyblocks && i != 1 && i != 5 && i != 6 )) {
589
10.4k
      hdr_line = i;
590
10.4k
      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
10.4k
      break;
598
10.4k
  }
599
600
  /* read the next line (skip all truncated lines) */
601
14.6k
  do {
602
14.6k
      maxlen = MAX_LINELEN;
603
14.6k
      afx->buffer_len = iobuf_read_line( a, &afx->buffer,
604
14.6k
                 &afx->buffer_size, &maxlen );
605
14.6k
      line = afx->buffer;
606
14.6k
      len = afx->buffer_len;
607
14.6k
  } while( !maxlen );
608
14.6k
    }
609
610
    /* Parse the header lines.  */
611
14.9k
    while(len) {
612
  /* Read the next line (skip all truncated lines). */
613
14.4k
  do {
614
14.4k
      maxlen = MAX_LINELEN;
615
14.4k
      afx->buffer_len = iobuf_read_line( a, &afx->buffer,
616
14.4k
                 &afx->buffer_size, &maxlen );
617
14.4k
      line = afx->buffer;
618
14.4k
      len = afx->buffer_len;
619
14.4k
  } while( !maxlen );
620
621
14.4k
  i = parse_header_line( afx, line, len );
622
14.4k
  if( i <= 0 ) {
623
10.4k
      if (i && RFC2440)
624
0
    rc = GPG_ERR_INV_ARMOR;
625
10.4k
      break;
626
10.4k
  }
627
14.4k
    }
628
629
630
10.9k
    if( rc )
631
0
  invalid_armor();
632
10.9k
    else if( afx->in_cleartext )
633
0
  afx->faked = 1;
634
10.9k
    else {
635
10.9k
  afx->inp_checked = 1;
636
10.9k
  gcry_md_reset (afx->crc_md);
637
10.9k
  afx->idx = 0;
638
10.9k
  afx->radbuf[0] = 0;
639
10.9k
    }
640
641
10.9k
    return rc;
642
16.5k
}
643
644
16.8k
#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
127
{
841
127
  if ( opt.ignore_crc_error )
842
0
    return 0;
843
127
  log_inc_errorcount();
844
127
  return gpg_error (GPG_ERR_INV_ARMOR);
845
127
}
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
11.1k
{
852
11.1k
    byte val;
853
11.1k
    int c;
854
11.1k
    u32 binc;
855
11.1k
    int checkcrc=0;
856
11.1k
    int rc = 0;
857
11.1k
    size_t n = 0;
858
11.1k
    int idx, onlypad=0;
859
11.1k
    int skip_fast = 0;
860
861
11.1k
    idx = afx->idx;
862
11.1k
    val = afx->radbuf[0];
863
231k
    for( n=0; n < size; ) {
864
865
231k
  if( afx->buffer_pos < afx->buffer_len )
866
211k
      c = afx->buffer[afx->buffer_pos++];
867
19.4k
  else { /* read the next line */
868
19.4k
      unsigned maxlen = MAX_LINELEN;
869
19.4k
      afx->buffer_pos = 0;
870
19.4k
      afx->buffer_len = iobuf_read_line( a, &afx->buffer,
871
19.4k
                 &afx->buffer_size, &maxlen );
872
19.4k
      if( !maxlen )
873
0
    afx->truncated++;
874
19.4k
      if( !afx->buffer_len )
875
1.21k
    break; /* eof */
876
18.2k
      continue;
877
19.4k
  }
878
879
212k
      again:
880
212k
  binc = asctobin[0][c];
881
882
212k
  if( binc != 0xffffffffUL )
883
110k
    {
884
110k
      if( idx == 0 && skip_fast == 0
885
48.4k
    && afx->buffer_pos + (16 - 1) < afx->buffer_len
886
32.8k
    && n + 12 < size)
887
32.7k
        {
888
    /* Fast path for radix64 to binary conversion.  */
889
32.7k
    u32 b0,b1,b2,b3;
890
891
    /* Speculatively load 15 more input bytes.  */
892
32.7k
    b0 = binc << (3 * 6);
893
32.7k
    b0 |= asctobin[2][afx->buffer[afx->buffer_pos + 0]];
894
32.7k
    b0 |= asctobin[1][afx->buffer[afx->buffer_pos + 1]];
895
32.7k
    b0 |= asctobin[0][afx->buffer[afx->buffer_pos + 2]];
896
32.7k
    b1  = asctobin[3][afx->buffer[afx->buffer_pos + 3]];
897
32.7k
    b1 |= asctobin[2][afx->buffer[afx->buffer_pos + 4]];
898
32.7k
    b1 |= asctobin[1][afx->buffer[afx->buffer_pos + 5]];
899
32.7k
    b1 |= asctobin[0][afx->buffer[afx->buffer_pos + 6]];
900
32.7k
    b2  = asctobin[3][afx->buffer[afx->buffer_pos + 7]];
901
32.7k
    b2 |= asctobin[2][afx->buffer[afx->buffer_pos + 8]];
902
32.7k
    b2 |= asctobin[1][afx->buffer[afx->buffer_pos + 9]];
903
32.7k
    b2 |= asctobin[0][afx->buffer[afx->buffer_pos + 10]];
904
32.7k
    b3  = asctobin[3][afx->buffer[afx->buffer_pos + 11]];
905
32.7k
    b3 |= asctobin[2][afx->buffer[afx->buffer_pos + 12]];
906
32.7k
    b3 |= asctobin[1][afx->buffer[afx->buffer_pos + 13]];
907
32.7k
    b3 |= asctobin[0][afx->buffer[afx->buffer_pos + 14]];
908
909
    /* Check if any of the input bytes were invalid. */
910
32.7k
    if( (b0 | b1 | b2 | b3) != 0xffffffffUL )
911
20.3k
      {
912
        /* All 16 bytes are valid. */
913
20.3k
        buf[n + 0] = b0 >> (2 * 8);
914
20.3k
        buf[n + 1] = b0 >> (1 * 8);
915
20.3k
        buf[n + 2] = b0 >> (0 * 8);
916
20.3k
        buf[n + 3] = b1 >> (2 * 8);
917
20.3k
        buf[n + 4] = b1 >> (1 * 8);
918
20.3k
        buf[n + 5] = b1 >> (0 * 8);
919
20.3k
        buf[n + 6] = b2 >> (2 * 8);
920
20.3k
        buf[n + 7] = b2 >> (1 * 8);
921
20.3k
        buf[n + 8] = b2 >> (0 * 8);
922
20.3k
        buf[n + 9] = b3 >> (2 * 8);
923
20.3k
        buf[n + 10] = b3 >> (1 * 8);
924
20.3k
        buf[n + 11] = b3 >> (0 * 8);
925
20.3k
        afx->buffer_pos += 16 - 1;
926
20.3k
        n += 12;
927
20.3k
        continue;
928
20.3k
      }
929
12.4k
    else if( b0 == 0xffffffffUL )
930
4.01k
      {
931
        /* byte[1..3] have invalid character(s).  Switch to slow
932
           path.  */
933
4.01k
        skip_fast = 1;
934
4.01k
      }
935
8.39k
    else if( b1 == 0xffffffffUL )
936
3.76k
      {
937
        /* byte[4..7] have invalid character(s), first 4 bytes are
938
           valid.  */
939
3.76k
        buf[n + 0] = b0 >> (2 * 8);
940
3.76k
        buf[n + 1] = b0 >> (1 * 8);
941
3.76k
        buf[n + 2] = b0 >> (0 * 8);
942
3.76k
        afx->buffer_pos += 4 - 1;
943
3.76k
        n += 3;
944
3.76k
        skip_fast = 1;
945
3.76k
        continue;
946
3.76k
      }
947
4.62k
    else if( b2 == 0xffffffffUL )
948
3.07k
      {
949
        /* byte[8..11] have invalid character(s), first 8 bytes are
950
           valid.  */
951
3.07k
        buf[n + 0] = b0 >> (2 * 8);
952
3.07k
        buf[n + 1] = b0 >> (1 * 8);
953
3.07k
        buf[n + 2] = b0 >> (0 * 8);
954
3.07k
        buf[n + 3] = b1 >> (2 * 8);
955
3.07k
        buf[n + 4] = b1 >> (1 * 8);
956
3.07k
        buf[n + 5] = b1 >> (0 * 8);
957
3.07k
        afx->buffer_pos += 8 - 1;
958
3.07k
        n += 6;
959
3.07k
        skip_fast = 1;
960
3.07k
        continue;
961
3.07k
      }
962
1.55k
    else /*if( b3 == 0xffffffffUL )*/
963
1.55k
      {
964
        /* byte[12..15] have invalid character(s), first 12 bytes
965
           are valid.  */
966
1.55k
        buf[n + 0] = b0 >> (2 * 8);
967
1.55k
        buf[n + 1] = b0 >> (1 * 8);
968
1.55k
        buf[n + 2] = b0 >> (0 * 8);
969
1.55k
        buf[n + 3] = b1 >> (2 * 8);
970
1.55k
        buf[n + 4] = b1 >> (1 * 8);
971
1.55k
        buf[n + 5] = b1 >> (0 * 8);
972
1.55k
        buf[n + 6] = b2 >> (2 * 8);
973
1.55k
        buf[n + 7] = b2 >> (1 * 8);
974
1.55k
        buf[n + 8] = b2 >> (0 * 8);
975
1.55k
        afx->buffer_pos += 12 - 1;
976
1.55k
        n += 9;
977
1.55k
        skip_fast = 1;
978
1.55k
        continue;
979
1.55k
      }
980
32.7k
        }
981
982
81.6k
      switch(idx)
983
81.6k
        {
984
24.2k
    case 0: val =  binc << 2; break;
985
20.6k
    case 1: val |= (binc>>4)&3; buf[n++]=val;val=(binc<<4)&0xf0;break;
986
19.3k
    case 2: val |= (binc>>2)&15; buf[n++]=val;val=(binc<<6)&0xc0;break;
987
17.4k
    case 3: val |= binc&0x3f; buf[n++] = val; break;
988
81.6k
        }
989
81.6k
      idx = (idx+1) % 4;
990
991
81.6k
      continue;
992
81.6k
    }
993
994
101k
  skip_fast = 0;
995
996
101k
  if( c == '\n' || c == ' ' || c == '\r' || c == '\t' )
997
23.7k
      continue;
998
78.0k
  else if( c == '=' ) { /* pad character: stop */
999
      /* some mailers leave quoted-printable encoded characters
1000
       * so we try to workaround this */
1001
10.5k
      if( afx->buffer_pos+2 < afx->buffer_len ) {
1002
6.84k
    int cc1, cc2, cc3;
1003
6.84k
    cc1 = afx->buffer[afx->buffer_pos];
1004
6.84k
    cc2 = afx->buffer[afx->buffer_pos+1];
1005
6.84k
    cc3 = afx->buffer[afx->buffer_pos+2];
1006
6.84k
    if( isxdigit(cc1) && isxdigit(cc2)
1007
961
          && strchr( "=\n\r\t ", cc3 )) {
1008
        /* well it seems to be the case - adjust */
1009
680
        c = isdigit(cc1)? (cc1 - '0'): (ascii_toupper(cc1)-'A'+10);
1010
680
        c <<= 4;
1011
680
        c |= isdigit(cc2)? (cc2 - '0'): (ascii_toupper(cc2)-'A'+10);
1012
680
        afx->buffer_pos += 2;
1013
680
        afx->qp_detected = 1;
1014
680
        goto again;
1015
680
    }
1016
6.84k
      }
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
9.87k
            if (afx->buffer_pos + 6 < afx->buffer_len
1024
1.95k
                && afx->buffer[afx->buffer_pos + 0] == '3'
1025
15
                && afx->buffer[afx->buffer_pos + 1] == 'D'
1026
12
                && asctobin[0][afx->buffer[afx->buffer_pos + 2]] != 0xffffffffUL
1027
11
                && asctobin[0][afx->buffer[afx->buffer_pos + 3]] != 0xffffffffUL
1028
10
                && asctobin[0][afx->buffer[afx->buffer_pos + 4]] != 0xffffffffUL
1029
8
                && asctobin[0][afx->buffer[afx->buffer_pos + 5]] != 0xffffffffUL
1030
7
                && 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
9.87k
      if (!n)
1037
5.26k
        onlypad = 1;
1038
1039
9.87k
      if( idx == 1 )
1040
3.45k
    buf[n++] = val;
1041
9.87k
      checkcrc++;
1042
9.87k
      break;
1043
10.5k
  }
1044
67.4k
        else if (afx->buffer_pos == 1 && c == '-'
1045
1.08k
                 && afx->buffer_len > 9
1046
745
                 && !strncmp (afx->buffer, "-----END ", 9)) {
1047
            /* End in --dearmor mode.  */
1048
9
            if (n)
1049
                /* No CRC found, and the end of the armor is detected.
1050
                   Let return with the result of N-byte now, and come
1051
                   again to process the end of the armor with N=0.  */
1052
4
                afx->buffer_pos--;
1053
9
            break;
1054
9
        }
1055
67.4k
  else {
1056
67.4k
      log_error(_("invalid radix64 character %02X skipped\n"), c);
1057
67.4k
      continue;
1058
67.4k
  }
1059
101k
    }
1060
1061
11.1k
    afx->idx = idx;
1062
11.1k
    afx->radbuf[0] = val;
1063
1064
11.1k
    if( n )
1065
7.89k
      {
1066
7.89k
        gcry_md_write (afx->crc_md, buf, n);
1067
7.89k
        afx->any_data = 1;
1068
7.89k
      }
1069
1070
11.1k
    if( checkcrc ) {
1071
9.87k
  gcry_md_final (afx->crc_md);
1072
9.87k
  afx->inp_checked=0;
1073
9.87k
  afx->faked = 0;
1074
21.2k
  for(;;) { /* skip lf and pad characters */
1075
21.2k
      if( afx->buffer_pos < afx->buffer_len )
1076
20.0k
    c = afx->buffer[afx->buffer_pos++];
1077
1.24k
      else { /* read the next line */
1078
1.24k
    unsigned maxlen = MAX_LINELEN;
1079
1.24k
    afx->buffer_pos = 0;
1080
1.24k
    afx->buffer_len = iobuf_read_line( a, &afx->buffer,
1081
1.24k
               &afx->buffer_size, &maxlen );
1082
1.24k
    if( !maxlen )
1083
0
        afx->truncated++;
1084
1.24k
    if( !afx->buffer_len )
1085
85
        break; /* eof */
1086
1.15k
    continue;
1087
1.24k
      }
1088
20.0k
      if( c == '\n' || c == ' ' || c == '\r'
1089
15.8k
    || c == '\t' || c == '=' )
1090
10.2k
    continue;
1091
9.79k
      break;
1092
20.0k
  }
1093
9.87k
  if( !afx->buffer_len )
1094
9.87k
      log_error(_("premature eof (no CRC)\n"));
1095
9.79k
  else {
1096
9.79k
      u32 mycrc = 0;
1097
9.79k
      idx = 0;
1098
10.9k
      do {
1099
10.9k
    if( (binc = asctobin[0][c]) == 0xffffffffUL )
1100
9.41k
        break;
1101
1.52k
    switch(idx) {
1102
403
      case 0: val =  binc << 2; break;
1103
383
      case 1: val |= (binc>>4)&3; mycrc |= val << 16;val=(binc<<4)&0xf0;break;
1104
373
      case 2: val |= (binc>>2)&15; mycrc |= val << 8;val=(binc<<6)&0xc0;break;
1105
362
      case 3: val |= binc&0x3f; mycrc |= val; break;
1106
1.52k
    }
1107
1.52k
    for(;;) {
1108
1.52k
        if( afx->buffer_pos < afx->buffer_len )
1109
1.50k
      c = afx->buffer[afx->buffer_pos++];
1110
21
        else { /* read the next line */
1111
21
      unsigned maxlen = MAX_LINELEN;
1112
21
      afx->buffer_pos = 0;
1113
21
      afx->buffer_len = iobuf_read_line( a, &afx->buffer,
1114
21
                 &afx->buffer_size,
1115
21
                &maxlen );
1116
21
      if( !maxlen )
1117
0
          afx->truncated++;
1118
21
      if( !afx->buffer_len )
1119
21
          break; /* eof */
1120
0
      continue;
1121
21
        }
1122
1.50k
        break;
1123
1.52k
    }
1124
1.52k
    if( !afx->buffer_len )
1125
21
        break; /* eof */
1126
1.52k
      } while( ++idx < 4 );
1127
9.79k
      if( !afx->buffer_len ) {
1128
21
    log_info(_("premature eof (in CRC)\n"));
1129
21
    rc = invalid_crc();
1130
21
      }
1131
9.77k
      else if( idx == 0 ) {
1132
          /* No CRC at all is legal ("MAY") */
1133
9.38k
          rc=0;
1134
9.38k
      }
1135
382
      else if( idx != 4 ) {
1136
22
    log_info(_("malformed CRC\n"));
1137
22
    rc = invalid_crc();
1138
22
      }
1139
360
      else if( mycrc != get_afx_crc (afx) ) {
1140
84
    log_info (_("CRC error; %06lX - %06lX\n"),
1141
84
            (ulong)get_afx_crc (afx), (ulong)mycrc);
1142
84
    rc = invalid_crc();
1143
84
      }
1144
276
      else {
1145
276
    rc = 0;
1146
                /* FIXME: Here we should emit another control packet,
1147
                 * so that we know in mainproc that we are processing
1148
                 * a clearsign message */
1149
#if 0
1150
    for(rc=0;!rc;) {
1151
        rc = 0 /*check_trailer( &fhdr, c )*/;
1152
        if( !rc ) {
1153
      if( (c=iobuf_get(a)) == -1 )
1154
          rc = 2;
1155
        }
1156
    }
1157
    if( rc == -1 )
1158
        rc = 0;
1159
    else if( rc == 2 ) {
1160
        log_error(_("premature eof (in trailer)\n"));
1161
        rc = GPG_ERR_INV_ARMOR;
1162
    }
1163
    else {
1164
        log_error(_("error in trailer line\n"));
1165
        rc = GPG_ERR_INV_ARMOR;
1166
    }
1167
#endif
1168
276
      }
1169
9.79k
  }
1170
9.87k
    }
1171
1172
11.1k
    if( !n && !onlypad )
1173
873
  rc = -1;
1174
1175
11.1k
    *retn = n;
1176
11.1k
    return rc;
1177
11.1k
}
1178
1179
static void
1180
armor_output_buf_as_radix64 (armor_filter_context_t *afx, IOBUF a,
1181
           byte *buf, size_t size)
1182
0
{
1183
0
  byte radbuf[sizeof (afx->radbuf)];
1184
0
  byte outbuf[64 + sizeof (afx->eol)];
1185
0
  unsigned int eollen = strlen (afx->eol);
1186
0
  u32 in, in2;
1187
0
  int idx, idx2;
1188
0
  int i;
1189
1190
0
  idx = afx->idx;
1191
0
  idx2 = afx->idx2;
1192
0
  memcpy (radbuf, afx->radbuf, sizeof (afx->radbuf));
1193
1194
0
  if (size && (idx || idx2))
1195
0
    {
1196
      /* preload eol to outbuf buffer */
1197
0
      memcpy (outbuf + 4, afx->eol, sizeof (afx->eol));
1198
1199
0
      for (; size && (idx || idx2); buf++, size--)
1200
0
  {
1201
0
    radbuf[idx++] = *buf;
1202
0
    if (idx > 2)
1203
0
      {
1204
0
        idx = 0;
1205
0
        in = (u32)radbuf[0] << (2 * 8);
1206
0
        in |= (u32)radbuf[1] << (1 * 8);
1207
0
        in |= (u32)radbuf[2] << (0 * 8);
1208
0
        outbuf[0] = bintoasc[(in >> 18) & 077];
1209
0
        outbuf[1] = bintoasc[(in >> 12) & 077];
1210
0
        outbuf[2] = bintoasc[(in >> 6) & 077];
1211
0
        outbuf[3] = bintoasc[(in >> 0) & 077];
1212
0
        if (++idx2 >= (64/4))
1213
0
    { /* pgp doesn't like 72 here */
1214
0
      idx2=0;
1215
0
      iobuf_write (a, outbuf, 4 + eollen);
1216
0
    }
1217
0
        else
1218
0
    {
1219
0
      iobuf_write (a, outbuf, 4);
1220
0
    }
1221
0
      }
1222
0
  }
1223
0
    }
1224
1225
0
  if (size >= (64/4)*3)
1226
0
    {
1227
      /* preload eol to outbuf buffer */
1228
0
      memcpy (outbuf + 64, afx->eol, sizeof(afx->eol));
1229
1230
0
      do
1231
0
  {
1232
    /* idx and idx2 == 0 */
1233
1234
0
    for (i = 0; i < (64/8); i++)
1235
0
      {
1236
0
        in = (u32)buf[0] << (2 * 8);
1237
0
        in |= (u32)buf[1] << (1 * 8);
1238
0
        in |= (u32)buf[2] << (0 * 8);
1239
0
        in2 = (u32)buf[3] << (2 * 8);
1240
0
        in2 |= (u32)buf[4] << (1 * 8);
1241
0
        in2 |= (u32)buf[5] << (0 * 8);
1242
0
        outbuf[i*8+0] = bintoasc[(in >> 18) & 077];
1243
0
        outbuf[i*8+1] = bintoasc[(in >> 12) & 077];
1244
0
        outbuf[i*8+2] = bintoasc[(in >> 6) & 077];
1245
0
        outbuf[i*8+3] = bintoasc[(in >> 0) & 077];
1246
0
        outbuf[i*8+4] = bintoasc[(in2 >> 18) & 077];
1247
0
        outbuf[i*8+5] = bintoasc[(in2 >> 12) & 077];
1248
0
        outbuf[i*8+6] = bintoasc[(in2 >> 6) & 077];
1249
0
        outbuf[i*8+7] = bintoasc[(in2 >> 0) & 077];
1250
0
        buf+=6;
1251
0
        size-=6;
1252
0
      }
1253
1254
    /* pgp doesn't like 72 here */
1255
0
    iobuf_write (a, outbuf, 64 + eollen);
1256
0
  }
1257
0
      while (size >= (64/4)*3);
1258
1259
      /* restore eol for tail handling */
1260
0
      if (size)
1261
0
  memcpy (outbuf + 4, afx->eol, sizeof (afx->eol));
1262
0
    }
1263
1264
0
  for (; size; buf++, size--)
1265
0
    {
1266
0
      radbuf[idx++] = *buf;
1267
0
      if (idx > 2)
1268
0
  {
1269
0
    idx = 0;
1270
0
    in = (u32)radbuf[0] << (2 * 8);
1271
0
    in |= (u32)radbuf[1] << (1 * 8);
1272
0
    in |= (u32)radbuf[2] << (0 * 8);
1273
0
    outbuf[0] = bintoasc[(in >> 18) & 077];
1274
0
    outbuf[1] = bintoasc[(in >> 12) & 077];
1275
0
    outbuf[2] = bintoasc[(in >> 6) & 077];
1276
0
    outbuf[3] = bintoasc[(in >> 0) & 077];
1277
0
    if (++idx2 >= (64/4))
1278
0
      { /* pgp doesn't like 72 here */
1279
0
        idx2=0;
1280
0
        iobuf_write (a, outbuf, 4 + eollen);
1281
0
      }
1282
0
    else
1283
0
      {
1284
0
        iobuf_write (a, outbuf, 4);
1285
0
      }
1286
0
  }
1287
0
    }
1288
1289
0
  memcpy (afx->radbuf, radbuf, sizeof (afx->radbuf));
1290
0
  afx->idx = idx;
1291
0
  afx->idx2 = idx2;
1292
0
}
1293
1294
/****************
1295
 * This filter is used to handle the armor stuff
1296
 */
1297
static int
1298
armor_filter( void *opaque, int control,
1299
       IOBUF a, byte *buf, size_t *ret_len)
1300
36.9k
{
1301
36.9k
    size_t size = *ret_len;
1302
36.9k
    armor_filter_context_t *afx = opaque;
1303
36.9k
    int rc=0, c;
1304
36.9k
    byte radbuf[3];
1305
36.9k
    int  idx, idx2;
1306
36.9k
    size_t n=0;
1307
36.9k
    u32 crc;
1308
#if 0
1309
    static FILE *fp ;
1310
1311
    if( !fp ) {
1312
  fp = fopen("armor.out", "w");
1313
  log_assert(fp);
1314
    }
1315
#endif
1316
1317
36.9k
    if( DBG_FILTER )
1318
36.9k
  log_debug("armor-filter: control: %d\n", control );
1319
36.9k
    if( control == IOBUFCTRL_UNDERFLOW && afx->inp_bypass ) {
1320
6.20k
  n = 0;
1321
6.20k
  if( afx->buffer_len ) {
1322
            /* Copy the data from AFX->BUFFER to BUF.  */
1323
41.0k
            for(; n < size && afx->buffer_pos < afx->buffer_len;)
1324
40.9k
                buf[n++] = afx->buffer[afx->buffer_pos++];
1325
47
      if( afx->buffer_pos >= afx->buffer_len )
1326
31
    afx->buffer_len = 0;
1327
47
  }
1328
        /* If there is still space in BUF, read directly into it.  */
1329
1.61M
  for(; n < size; n++ ) {
1330
1.61M
      if( (c=iobuf_get(a)) == -1 )
1331
6.14k
    break;
1332
1.61M
      buf[n] = c & 0xff;
1333
1.61M
  }
1334
6.20k
  if( !n )
1335
            /* We didn't get any data.  EOF.  */
1336
4.76k
      rc = -1;
1337
6.20k
  *ret_len = n;
1338
6.20k
    }
1339
30.7k
    else if( control == IOBUFCTRL_UNDERFLOW ) {
1340
        /* We need some space for the faked packet.  The minimum
1341
         * required size is the PARTIAL_CHUNK size plus a byte for the
1342
         * length itself */
1343
16.8k
  if( size < PARTIAL_CHUNK+1 )
1344
0
      BUG(); /* supplied buffer too short */
1345
1346
16.8k
  if( afx->faked )
1347
0
      rc = fake_packet( afx, a, &n, buf, size );
1348
16.8k
  else if( !afx->inp_checked ) {
1349
16.5k
      rc = check_input( afx, a );
1350
16.5k
      if( afx->inp_bypass ) {
1351
1.35M
    for(n=0; n < size && afx->buffer_pos < afx->buffer_len; )
1352
1.34M
        buf[n++] = afx->buffer[afx->buffer_pos++];
1353
5.61k
    if( afx->buffer_pos >= afx->buffer_len )
1354
5.58k
        afx->buffer_len = 0;
1355
5.61k
    if( !n )
1356
68
        rc = -1;
1357
5.61k
      }
1358
10.9k
      else if( afx->faked ) {
1359
0
          unsigned int hashes = afx->hashes;
1360
0
                const byte *sesmark;
1361
0
                size_t sesmarklen;
1362
1363
0
                sesmark = get_session_marker( &sesmarklen );
1364
0
                if ( sesmarklen > 20 )
1365
0
                    BUG();
1366
1367
    /* the buffer is at least 15+n*15 bytes long, so it
1368
     * is easy to construct the packets */
1369
1370
0
    hashes &= 1|2|8|16|32|64;
1371
0
    if( !hashes ) {
1372
0
        hashes |= 2;  /* Default to SHA-1. */
1373
0
    }
1374
0
    n=0;
1375
                /* First a gpg control packet... */
1376
0
                buf[n++] = 0xff; /* new format, type 63, 1 length byte */
1377
0
                n++;   /* see below */
1378
0
                memcpy(buf+n, sesmark, sesmarklen ); n+= sesmarklen;
1379
0
                buf[n++] = CTRLPKT_CLEARSIGN_START;
1380
0
                buf[n++] = afx->not_dash_escaped? 0:1; /* sigclass */
1381
0
                if( hashes & 1 )
1382
0
                    buf[n++] = DIGEST_ALGO_RMD160;
1383
0
                if( hashes & 2 )
1384
0
                    buf[n++] = DIGEST_ALGO_SHA1;
1385
0
                if( hashes & 8 )
1386
0
                    buf[n++] = DIGEST_ALGO_SHA224;
1387
0
                if( hashes & 16 )
1388
0
                    buf[n++] = DIGEST_ALGO_SHA256;
1389
0
                if( hashes & 32 )
1390
0
                    buf[n++] = DIGEST_ALGO_SHA384;
1391
0
                if( hashes & 64 )
1392
0
                    buf[n++] = DIGEST_ALGO_SHA512;
1393
0
                buf[1] = n - 2;
1394
1395
    /* ...followed by an invented plaintext packet.
1396
       Amusingly enough, this packet is not compliant with
1397
       2440 as the initial partial length is less than 512
1398
       bytes.  Of course, we'll accept it anyway ;) */
1399
1400
0
    buf[n++] = 0xCB; /* new packet format, type 11 */
1401
0
    buf[n++] = 0xE1; /* 2^1 == 2 bytes */
1402
0
    buf[n++] = 't';  /* canonical text mode */
1403
0
    buf[n++] = 0;  /* namelength */
1404
0
    buf[n++] = 0xE2; /* 2^2 == 4 more bytes */
1405
0
    memset(buf+n, 0, 4); /* timestamp */
1406
0
    n += 4;
1407
0
      }
1408
10.9k
      else if( !rc )
1409
10.9k
    rc = radix64_read( afx, a, &n, buf, size );
1410
16.5k
  }
1411
224
  else
1412
224
      rc = radix64_read( afx, a, &n, buf, size );
1413
#if 0
1414
  if( n )
1415
      if( fwrite(buf, n, 1, fp ) != 1 )
1416
    BUG();
1417
#endif
1418
16.8k
  *ret_len = n;
1419
16.8k
    }
1420
13.8k
    else if( control == IOBUFCTRL_FLUSH && !afx->cancel ) {
1421
0
  if( !afx->status ) { /* write the header line */
1422
0
      const char *s;
1423
0
      strlist_t comment=opt.comments;
1424
1425
0
      if( afx->what >= DIM(head_strings) )
1426
0
    log_bug("afx->what=%d", afx->what);
1427
0
      iobuf_writestr(a, "-----");
1428
0
      iobuf_writestr(a, head_strings[afx->what] );
1429
0
      iobuf_writestr(a, "-----" );
1430
0
      iobuf_writestr(a,afx->eol);
1431
0
      if (opt.emit_version)
1432
0
        {
1433
0
    iobuf_writestr (a, "Version: "GNUPG_NAME" v");
1434
0
                for (s=VERSION; *s && *s != '.'; s++)
1435
0
                  iobuf_writebyte (a, *s);
1436
0
                if (opt.emit_version > 1 && *s)
1437
0
                  {
1438
0
                    iobuf_writebyte (a, *s++);
1439
0
                    for (; *s && *s != '.'; s++)
1440
0
                      iobuf_writebyte (a, *s);
1441
0
                    if (opt.emit_version > 2)
1442
0
                      {
1443
0
                        for (; *s && *s != '-' && !spacep (s); s++)
1444
0
                          iobuf_writebyte (a, *s);
1445
0
                        if (opt.emit_version > 3)
1446
0
                          iobuf_writestr (a, " (" PRINTABLE_OS_NAME ")");
1447
0
                      }
1448
0
                  }
1449
0
    iobuf_writestr(a,afx->eol);
1450
0
        }
1451
1452
      /* write the comment strings */
1453
0
      for(;comment;comment=comment->next)
1454
0
        {
1455
0
    iobuf_writestr(a, "Comment: " );
1456
0
    for( s=comment->d; *s; s++ )
1457
0
      {
1458
0
        if( *s == '\n' )
1459
0
          iobuf_writestr(a, "\\n" );
1460
0
        else if( *s == '\r' )
1461
0
          iobuf_writestr(a, "\\r" );
1462
0
        else if( *s == '\v' )
1463
0
          iobuf_writestr(a, "\\v" );
1464
0
        else
1465
0
          iobuf_put(a, *s );
1466
0
      }
1467
1468
0
    iobuf_writestr(a,afx->eol);
1469
0
        }
1470
1471
0
      if ( afx->hdrlines ) {
1472
0
                for ( s = afx->hdrlines; *s; s++ ) {
1473
#ifdef HAVE_DOSISH_SYSTEM
1474
                    if ( *s == '\n' )
1475
                        iobuf_put( a, '\r');
1476
#endif
1477
0
                    iobuf_put(a, *s );
1478
0
                }
1479
0
            }
1480
1481
0
      iobuf_writestr(a,afx->eol);
1482
0
      afx->status++;
1483
0
      afx->idx = 0;
1484
0
      afx->idx2 = 0;
1485
0
      gcry_md_reset (afx->crc_md);
1486
0
  }
1487
1488
0
  if( size ) {
1489
0
      gcry_md_write (afx->crc_md, buf, size);
1490
0
      armor_output_buf_as_radix64 (afx, a, buf, size);
1491
0
        }
1492
0
    }
1493
13.8k
    else if( control == IOBUFCTRL_INIT )
1494
6.94k
      {
1495
6.94k
  if( !is_initialized )
1496
1
    initialize();
1497
1498
  /* Figure out what we're using for line endings if the caller
1499
     didn't specify. */
1500
6.94k
  if(afx->eol[0]==0)
1501
6.94k
    {
1502
#ifdef HAVE_DOSISH_SYSTEM
1503
      afx->eol[0]='\r';
1504
      afx->eol[1]='\n';
1505
#else
1506
6.94k
      afx->eol[0]='\n';
1507
6.94k
#endif
1508
6.94k
    }
1509
6.94k
      }
1510
6.94k
    else if( control == IOBUFCTRL_CANCEL ) {
1511
0
  afx->cancel = 1;
1512
0
    }
1513
6.94k
    else if( control == IOBUFCTRL_FREE ) {
1514
6.94k
  if( afx->cancel )
1515
0
      ;
1516
6.94k
  else if( afx->status ) { /* pad, write checksum, and bottom line */
1517
0
      gcry_md_final (afx->crc_md);
1518
0
      crc = get_afx_crc (afx);
1519
0
      idx = afx->idx;
1520
0
      idx2 = afx->idx2;
1521
0
      if( idx ) {
1522
0
    c = bintoasc[(afx->radbuf[0]>>2)&077];
1523
0
    iobuf_put(a, c);
1524
0
    if( idx == 1 ) {
1525
0
        c = bintoasc[((afx->radbuf[0] << 4) & 060) & 077];
1526
0
        iobuf_put(a, c);
1527
0
        iobuf_put(a, '=');
1528
0
        iobuf_put(a, '=');
1529
0
    }
1530
0
    else { /* 2 */
1531
0
        c = bintoasc[(((afx->radbuf[0]<<4)&060)
1532
0
                                  |((afx->radbuf[1]>>4)&017))&077];
1533
0
        iobuf_put(a, c);
1534
0
        c = bintoasc[((afx->radbuf[1] << 2) & 074) & 077];
1535
0
        iobuf_put(a, c);
1536
0
        iobuf_put(a, '=');
1537
0
    }
1538
0
    if( ++idx2 >= (64/4) )
1539
0
      { /* pgp doesn't like 72 here */
1540
0
        iobuf_writestr(a,afx->eol);
1541
0
        idx2=0;
1542
0
      }
1543
0
      }
1544
      /* may need a linefeed */
1545
0
      if( idx2 )
1546
0
        iobuf_writestr(a,afx->eol);
1547
      /* write the CRC */
1548
0
      iobuf_put(a, '=');
1549
0
      radbuf[0] = crc >>16;
1550
0
      radbuf[1] = crc >> 8;
1551
0
      radbuf[2] = crc;
1552
0
      c = bintoasc[(*radbuf >> 2) & 077];
1553
0
      iobuf_put(a, c);
1554
0
      c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
1555
0
      iobuf_put(a, c);
1556
0
      c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
1557
0
      iobuf_put(a, c);
1558
0
      c = bintoasc[radbuf[2]&077];
1559
0
      iobuf_put(a, c);
1560
0
      iobuf_writestr(a,afx->eol);
1561
      /* and the trailer */
1562
0
      if( afx->what >= DIM(tail_strings) )
1563
0
    log_bug("afx->what=%d", afx->what);
1564
0
      iobuf_writestr(a, "-----");
1565
0
      iobuf_writestr(a, tail_strings[afx->what] );
1566
0
      iobuf_writestr(a, "-----" );
1567
0
      iobuf_writestr(a,afx->eol);
1568
0
  }
1569
6.94k
  else if( !afx->any_data && !afx->inp_bypass ) {
1570
556
      log_error(_("no valid OpenPGP data found.\n"));
1571
556
      afx->no_openpgp_data = 1;
1572
556
      write_status_text( STATUS_NODATA, "1" );
1573
556
  }
1574
        /* Note that in a cleartext signature truncated lines in the
1575
         * plaintext are detected and propagated to the signature
1576
         * checking code by inserting a \f into the plaintext.  We do
1577
         * not use log_info here because some of the truncated lines
1578
         * are harmless.  */
1579
6.94k
  if( afx->truncated )
1580
6.94k
      log_info(_("invalid armor: line longer than %d characters\n"),
1581
0
          MAX_LINELEN );
1582
  /* issue an error to enforce dissemination of correct software */
1583
6.94k
  if( afx->qp_detected )
1584
6.94k
      log_error(_("quoted printable character in armor - "
1585
35
      "probably a buggy MTA has been used\n") );
1586
6.94k
  xfree( afx->buffer );
1587
6.94k
  afx->buffer = NULL;
1588
6.94k
        release_armor_context (afx);
1589
6.94k
    }
1590
0
    else if( control == IOBUFCTRL_DESC )
1591
0
        mem2str (buf, "armor_filter", *ret_len);
1592
36.9k
    return rc;
1593
36.9k
}
1594
1595
1596
/****************
1597
 * create a radix64 encoded string.
1598
 */
1599
char *
1600
make_radix64_string( const byte *data, size_t len )
1601
0
{
1602
0
    char *buffer, *p;
1603
1604
0
    buffer = p = xmalloc( (len+2)/3*4 + 1 );
1605
0
    for( ; len >= 3 ; len -= 3, data += 3 ) {
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)|((data[2]>>6)&03))&077];
1609
0
  *p++ = bintoasc[data[2]&077];
1610
0
    }
1611
0
    if( len == 2 ) {
1612
0
  *p++ = bintoasc[(data[0] >> 2) & 077];
1613
0
  *p++ = bintoasc[(((data[0] <<4)&060)|((data[1] >> 4)&017))&077];
1614
0
  *p++ = bintoasc[((data[1]<<2)&074)];
1615
0
    }
1616
0
    else if( len == 1 ) {
1617
0
  *p++ = bintoasc[(data[0] >> 2) & 077];
1618
0
  *p++ = bintoasc[(data[0] <<4)&060];
1619
0
    }
1620
0
    *p = 0;
1621
0
    return buffer;
1622
0
}