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
48.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
7.41k
#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
5.56k
{
116
5.56k
  armor_filter_context_t *afx;
117
5.56k
  gpg_error_t err;
118
119
5.56k
  afx = xcalloc (1, sizeof *afx);
120
5.56k
  if (afx)
121
5.56k
    {
122
5.56k
      err = gcry_md_open (&afx->crc_md, GCRY_MD_CRC24_RFC2440, 0);
123
5.56k
      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
5.56k
      afx->refcount = 1;
132
5.56k
    }
133
134
5.56k
  return afx;
135
5.56k
}
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
11.1k
{
142
11.1k
  if (!afx)
143
0
    return;
144
11.1k
  log_assert (afx->refcount);
145
11.1k
  if ( --afx->refcount )
146
5.56k
    return;
147
5.56k
  gcry_md_close (afx->crc_md);
148
5.56k
  xfree (afx);
149
5.56k
}
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
5.56k
{
155
5.56k
  int rc;
156
157
5.56k
  afx->refcount++;
158
5.56k
  rc = iobuf_push_filter (iobuf, armor_filter, afx);
159
5.56k
  if (rc)
160
0
    afx->refcount--;
161
5.56k
  return rc;
162
5.56k
}
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
377
{
200
377
  const byte *crc_buf;
201
377
  u32 crc;
202
203
377
  crc_buf = gcry_md_read (afx->crc_md, GCRY_MD_CRC24_RFC2440);
204
205
377
  crc = crc_buf[0];
206
377
  crc <<= 8;
207
377
  crc |= crc_buf[1];
208
377
  crc <<= 8;
209
377
  crc |= crc_buf[2];
210
211
377
  return crc;
212
377
}
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
11.7k
{
227
11.7k
  int ctb, pkttype;
228
11.7k
  int indeterminate_length_allowed;
229
230
11.7k
    ctb = *buf;
231
11.7k
    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
6.52k
      return 1;
236
237
5.24k
    pkttype =  ctb & 0x40 ? (ctb & 0x3f) : ((ctb>>2)&0xf);
238
5.24k
    switch( pkttype ) {
239
116
      case PKT_PUBKEY_ENC:
240
867
      case PKT_SIGNATURE:
241
1.02k
      case PKT_SYMKEY_ENC:
242
1.08k
      case PKT_ONEPASS_SIG:
243
1.49k
      case PKT_SECRET_KEY:
244
2.81k
      case PKT_PUBLIC_KEY:
245
3.19k
      case PKT_SECRET_SUBKEY:
246
3.25k
      case PKT_MARKER:
247
3.48k
      case PKT_RING_TRUST:
248
3.64k
      case PKT_USER_ID:
249
3.67k
      case PKT_PUBLIC_SUBKEY:
250
4.12k
      case PKT_ATTRIBUTE:
251
4.18k
      case PKT_MDC:
252
4.18k
  indeterminate_length_allowed = 0;
253
4.18k
        break;
254
255
44
      case PKT_COMPRESSED:
256
172
      case PKT_ENCRYPTED:
257
308
      case PKT_ENCRYPTED_MDC:
258
379
      case PKT_ENCRYPTED_AEAD:
259
520
      case PKT_PLAINTEXT:
260
553
      case PKT_OLD_COMMENT:
261
606
      case PKT_COMMENT:
262
702
      case PKT_GPG_CONTROL:
263
702
  indeterminate_length_allowed = 1;
264
702
        break;
265
266
363
      default:
267
        /* Invalid packet type.  */
268
363
        return 1;
269
5.24k
    }
270
271
4.88k
    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.18k
      {
277
4.18k
        int new_format;
278
4.18k
        int indeterminate_length;
279
280
4.18k
        new_format = !! (ctb & (1 << 6));
281
4.18k
        if (new_format)
282
2.11k
          indeterminate_length = (buf[1] >= 224 && buf[1] < 255);
283
2.07k
        else
284
2.07k
          indeterminate_length = (ctb & 3) == 3;
285
286
4.18k
        if (indeterminate_length)
287
458
          return 1;
288
4.18k
      }
289
290
    /* The first CTB seems legit.  It is probably not armored
291
       data.  */
292
4.42k
    return 0;
293
4.88k
}
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
2.49k
{
382
2.49k
  if(strncmp(line,"Version",7)==0
383
2.14k
     || strncmp(line,"Comment",7)==0
384
1.86k
     || strncmp(line,"MessageID",9)==0
385
1.63k
     || strncmp(line,"Hash",4)==0
386
1.51k
     || strncmp(line,"Charset",7)==0)
387
1.51k
    return 1;
388
389
984
  return 0;
390
2.49k
}
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
18.0k
{
400
18.0k
    const char *s;
401
18.0k
    byte *save_p, *p;
402
18.0k
    int save_c;
403
18.0k
    int i;
404
405
18.0k
    if( len < 15 )
406
7.14k
  return -1; /* too short */
407
10.8k
    if( memcmp( line, "-----", 5 ) )
408
1.37k
  return -1; /* no */
409
9.49k
    p = strstr( line+5, "-----");
410
9.49k
    if( !p )
411
544
  return -1;
412
8.94k
    save_p = p;
413
8.94k
    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
8.94k
    if(RFC2440)
424
0
      {
425
0
  if( *p == '\r' )
426
0
    p++;
427
0
  if( *p == '\n' )
428
0
    p++;
429
0
      }
430
8.94k
    else
431
17.9k
      while(*p==' ' || *p=='\r' || *p=='\n' || *p=='\t')
432
8.95k
  p++;
433
434
8.94k
    if( *p )
435
280
  return -1; /* garbage after dashes */
436
8.66k
    save_c = *save_p; *save_p = 0;
437
8.66k
    p = line+5;
438
29.3k
    for(i=0; (s=head_strings[i]); i++ )
439
28.2k
  if( !strcmp(s, p) )
440
7.61k
      break;
441
8.66k
    *save_p = save_c;
442
8.66k
    if (!s)
443
1.05k
      {
444
1.05k
        if (!strncmp (p, "BEGIN ", 6))
445
503
          return 42;
446
549
  return -1; /* unknown armor line */
447
1.05k
      }
448
449
7.61k
    if( opt.verbose > 1 )
450
7.61k
  log_info(_("armor: %s\n"), head_strings[i]);
451
7.61k
    return i;
452
8.66k
}
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
9.90k
{
465
9.90k
    byte *p;
466
9.90k
    int hashes=0;
467
9.90k
    unsigned int len2;
468
469
9.90k
    len2 = length_sans_trailing_ws ( line, len );
470
9.90k
    if( !len2 ) {
471
4.36k
        afx->buffer_pos = len2;  /* (it is not the fine way to do it here) */
472
4.36k
  return 0; /* WS only: same as empty line */
473
4.36k
    }
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
5.54k
    p = strchr( line, ':');
486
5.54k
    if (!p && afx->dearmor_state)
487
0
      return 0; /* Special treatment in --dearmor mode.  */
488
5.54k
    if( !p || (RFC2440 && p[1]!=' ')
489
2.61k
  || (!RFC2440 && p[1]!=' ' && p[1]!='\n' && p[1]!='\r'))
490
3.04k
      {
491
3.04k
  log_error (_("invalid armor header: "));
492
3.04k
  es_write_sanitized (log_get_stream (), line, len, NULL, NULL);
493
3.04k
  log_printf ("\n");
494
3.04k
  return -1;
495
3.04k
      }
496
497
    /* Chop off the whitespace we detected before */
498
2.49k
    len=len2;
499
2.49k
    line[len2]='\0';
500
501
2.49k
    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
2.49k
    if (afx->dearmor_mode)
508
0
      ;
509
2.49k
    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
2.49k
    else if(!is_armor_tag(line))
524
984
      {
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
984
  log_info(_("unknown armor header: "));
533
984
  es_write_sanitized (log_get_stream (), line, len, NULL, NULL);
534
984
  log_printf ("\n");
535
984
      }
536
537
2.49k
    return 1;
538
2.49k
}
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
12.3k
{
546
12.3k
    int rc = 0;
547
12.3k
    int i;
548
12.3k
    byte *line;
549
12.3k
    unsigned len;
550
12.3k
    unsigned maxlen;
551
12.3k
    int hdr_line = -1;
552
553
    /* read the first line to see whether this is armored data */
554
12.3k
    maxlen = MAX_LINELEN;
555
12.3k
    len = afx->buffer_len = iobuf_read_line( a, &afx->buffer,
556
12.3k
               &afx->buffer_size, &maxlen );
557
12.3k
    line = afx->buffer;
558
12.3k
    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
12.3k
    if( !len ) {
566
55
  return -1; /* eof */
567
55
    }
568
569
    /* (the line is always a C string but maybe longer) */
570
12.2k
    if( *line == '\n' || ( len && (*line == '\r' && line[1]=='\n') ) )
571
474
  ;
572
11.8k
    else if (len >= 2 && !is_armored (line)) {
573
4.42k
  afx->inp_checked = 1;
574
4.42k
  afx->inp_bypass = 1;
575
4.42k
  return 0;
576
4.42k
    }
577
578
    /* find the armor header */
579
18.4k
    while(len) {
580
18.0k
  i = is_armor_header( line, len );
581
18.0k
        if ( i == 42 ) {
582
503
            if (afx->dearmor_mode) {
583
0
                afx->dearmor_state = 1;
584
0
                break;
585
0
            }
586
503
        }
587
17.5k
        else if (i >= 0
588
7.61k
                 && !(afx->only_keyblocks && i != 1 && i != 5 && i != 6 )) {
589
7.41k
      hdr_line = i;
590
7.41k
      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
7.41k
      break;
598
7.41k
  }
599
600
  /* read the next line (skip all truncated lines) */
601
10.6k
  do {
602
10.6k
      maxlen = MAX_LINELEN;
603
10.6k
      afx->buffer_len = iobuf_read_line( a, &afx->buffer,
604
10.6k
                 &afx->buffer_size, &maxlen );
605
10.6k
      line = afx->buffer;
606
10.6k
      len = afx->buffer_len;
607
10.6k
  } while( !maxlen );
608
10.6k
    }
609
610
    /* Parse the header lines.  */
611
10.3k
    while(len) {
612
  /* Read the next line (skip all truncated lines). */
613
9.90k
  do {
614
9.90k
      maxlen = MAX_LINELEN;
615
9.90k
      afx->buffer_len = iobuf_read_line( a, &afx->buffer,
616
9.90k
                 &afx->buffer_size, &maxlen );
617
9.90k
      line = afx->buffer;
618
9.90k
      len = afx->buffer_len;
619
9.90k
  } while( !maxlen );
620
621
9.90k
  i = parse_header_line( afx, line, len );
622
9.90k
  if( i <= 0 ) {
623
7.41k
      if (i && RFC2440)
624
0
    rc = GPG_ERR_INV_ARMOR;
625
7.41k
      break;
626
7.41k
  }
627
9.90k
    }
628
629
630
7.85k
    if( rc )
631
0
  invalid_armor();
632
7.85k
    else if( afx->in_cleartext )
633
0
  afx->faked = 1;
634
7.85k
    else {
635
7.85k
  afx->inp_checked = 1;
636
7.85k
  gcry_md_reset (afx->crc_md);
637
7.85k
  afx->idx = 0;
638
7.85k
  afx->radbuf[0] = 0;
639
7.85k
    }
640
641
7.85k
    return rc;
642
12.2k
}
643
644
13.7k
#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
94
{
841
94
  if ( opt.ignore_crc_error )
842
0
    return 0;
843
94
  log_inc_errorcount();
844
94
  return gpg_error (GPG_ERR_INV_ARMOR);
845
94
}
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
9.27k
{
852
9.27k
    byte val;
853
9.27k
    int c;
854
9.27k
    u32 binc;
855
9.27k
    int checkcrc=0;
856
9.27k
    int rc = 0;
857
9.27k
    size_t n = 0;
858
9.27k
    int idx, onlypad=0;
859
9.27k
    int skip_fast = 0;
860
861
9.27k
    idx = afx->idx;
862
9.27k
    val = afx->radbuf[0];
863
218k
    for( n=0; n < size; ) {
864
865
218k
  if( afx->buffer_pos < afx->buffer_len )
866
203k
      c = afx->buffer[afx->buffer_pos++];
867
14.8k
  else { /* read the next line */
868
14.8k
      unsigned maxlen = MAX_LINELEN;
869
14.8k
      afx->buffer_pos = 0;
870
14.8k
      afx->buffer_len = iobuf_read_line( a, &afx->buffer,
871
14.8k
                 &afx->buffer_size, &maxlen );
872
14.8k
      if( !maxlen )
873
0
    afx->truncated++;
874
14.8k
      if( !afx->buffer_len )
875
1.12k
    break; /* eof */
876
13.7k
      continue;
877
14.8k
  }
878
879
206k
      again:
880
206k
  binc = asctobin[0][c];
881
882
206k
  if( binc != 0xffffffffUL )
883
103k
    {
884
103k
      if( idx == 0 && skip_fast == 0
885
41.5k
    && afx->buffer_pos + (16 - 1) < afx->buffer_len
886
28.4k
    && n + 12 < size)
887
28.4k
        {
888
    /* Fast path for radix64 to binary conversion.  */
889
28.4k
    u32 b0,b1,b2,b3;
890
891
    /* Speculatively load 15 more input bytes.  */
892
28.4k
    b0 = binc << (3 * 6);
893
28.4k
    b0 |= asctobin[2][afx->buffer[afx->buffer_pos + 0]];
894
28.4k
    b0 |= asctobin[1][afx->buffer[afx->buffer_pos + 1]];
895
28.4k
    b0 |= asctobin[0][afx->buffer[afx->buffer_pos + 2]];
896
28.4k
    b1  = asctobin[3][afx->buffer[afx->buffer_pos + 3]];
897
28.4k
    b1 |= asctobin[2][afx->buffer[afx->buffer_pos + 4]];
898
28.4k
    b1 |= asctobin[1][afx->buffer[afx->buffer_pos + 5]];
899
28.4k
    b1 |= asctobin[0][afx->buffer[afx->buffer_pos + 6]];
900
28.4k
    b2  = asctobin[3][afx->buffer[afx->buffer_pos + 7]];
901
28.4k
    b2 |= asctobin[2][afx->buffer[afx->buffer_pos + 8]];
902
28.4k
    b2 |= asctobin[1][afx->buffer[afx->buffer_pos + 9]];
903
28.4k
    b2 |= asctobin[0][afx->buffer[afx->buffer_pos + 10]];
904
28.4k
    b3  = asctobin[3][afx->buffer[afx->buffer_pos + 11]];
905
28.4k
    b3 |= asctobin[2][afx->buffer[afx->buffer_pos + 12]];
906
28.4k
    b3 |= asctobin[1][afx->buffer[afx->buffer_pos + 13]];
907
28.4k
    b3 |= asctobin[0][afx->buffer[afx->buffer_pos + 14]];
908
909
    /* Check if any of the input bytes were invalid. */
910
28.4k
    if( (b0 | b1 | b2 | b3) != 0xffffffffUL )
911
15.8k
      {
912
        /* All 16 bytes are valid. */
913
15.8k
        buf[n + 0] = b0 >> (2 * 8);
914
15.8k
        buf[n + 1] = b0 >> (1 * 8);
915
15.8k
        buf[n + 2] = b0 >> (0 * 8);
916
15.8k
        buf[n + 3] = b1 >> (2 * 8);
917
15.8k
        buf[n + 4] = b1 >> (1 * 8);
918
15.8k
        buf[n + 5] = b1 >> (0 * 8);
919
15.8k
        buf[n + 6] = b2 >> (2 * 8);
920
15.8k
        buf[n + 7] = b2 >> (1 * 8);
921
15.8k
        buf[n + 8] = b2 >> (0 * 8);
922
15.8k
        buf[n + 9] = b3 >> (2 * 8);
923
15.8k
        buf[n + 10] = b3 >> (1 * 8);
924
15.8k
        buf[n + 11] = b3 >> (0 * 8);
925
15.8k
        afx->buffer_pos += 16 - 1;
926
15.8k
        n += 12;
927
15.8k
        continue;
928
15.8k
      }
929
12.5k
    else if( b0 == 0xffffffffUL )
930
5.80k
      {
931
        /* byte[1..3] have invalid character(s).  Switch to slow
932
           path.  */
933
5.80k
        skip_fast = 1;
934
5.80k
      }
935
6.72k
    else if( b1 == 0xffffffffUL )
936
3.53k
      {
937
        /* byte[4..7] have invalid character(s), first 4 bytes are
938
           valid.  */
939
3.53k
        buf[n + 0] = b0 >> (2 * 8);
940
3.53k
        buf[n + 1] = b0 >> (1 * 8);
941
3.53k
        buf[n + 2] = b0 >> (0 * 8);
942
3.53k
        afx->buffer_pos += 4 - 1;
943
3.53k
        n += 3;
944
3.53k
        skip_fast = 1;
945
3.53k
        continue;
946
3.53k
      }
947
3.19k
    else if( b2 == 0xffffffffUL )
948
1.95k
      {
949
        /* byte[8..11] have invalid character(s), first 8 bytes are
950
           valid.  */
951
1.95k
        buf[n + 0] = b0 >> (2 * 8);
952
1.95k
        buf[n + 1] = b0 >> (1 * 8);
953
1.95k
        buf[n + 2] = b0 >> (0 * 8);
954
1.95k
        buf[n + 3] = b1 >> (2 * 8);
955
1.95k
        buf[n + 4] = b1 >> (1 * 8);
956
1.95k
        buf[n + 5] = b1 >> (0 * 8);
957
1.95k
        afx->buffer_pos += 8 - 1;
958
1.95k
        n += 6;
959
1.95k
        skip_fast = 1;
960
1.95k
        continue;
961
1.95k
      }
962
1.23k
    else /*if( b3 == 0xffffffffUL )*/
963
1.23k
      {
964
        /* byte[12..15] have invalid character(s), first 12 bytes
965
           are valid.  */
966
1.23k
        buf[n + 0] = b0 >> (2 * 8);
967
1.23k
        buf[n + 1] = b0 >> (1 * 8);
968
1.23k
        buf[n + 2] = b0 >> (0 * 8);
969
1.23k
        buf[n + 3] = b1 >> (2 * 8);
970
1.23k
        buf[n + 4] = b1 >> (1 * 8);
971
1.23k
        buf[n + 5] = b1 >> (0 * 8);
972
1.23k
        buf[n + 6] = b2 >> (2 * 8);
973
1.23k
        buf[n + 7] = b2 >> (1 * 8);
974
1.23k
        buf[n + 8] = b2 >> (0 * 8);
975
1.23k
        afx->buffer_pos += 12 - 1;
976
1.23k
        n += 9;
977
1.23k
        skip_fast = 1;
978
1.23k
        continue;
979
1.23k
      }
980
28.4k
        }
981
982
81.1k
      switch(idx)
983
81.1k
        {
984
23.0k
    case 0: val =  binc << 2; break;
985
20.2k
    case 1: val |= (binc>>4)&3; buf[n++]=val;val=(binc<<4)&0xf0;break;
986
19.4k
    case 2: val |= (binc>>2)&15; buf[n++]=val;val=(binc<<6)&0xc0;break;
987
18.3k
    case 3: val |= binc&0x3f; buf[n++] = val; break;
988
81.1k
        }
989
81.1k
      idx = (idx+1) % 4;
990
991
81.1k
      continue;
992
81.1k
    }
993
994
102k
  skip_fast = 0;
995
996
102k
  if( c == '\n' || c == ' ' || c == '\r' || c == '\t' )
997
24.2k
      continue;
998
78.2k
  else if( c == '=' ) { /* pad character: stop */
999
      /* some mailers leave quoted-printable encoded characters
1000
       * so we try to workaround this */
1001
9.53k
      if( afx->buffer_pos+2 < afx->buffer_len ) {
1002
6.88k
    int cc1, cc2, cc3;
1003
6.88k
    cc1 = afx->buffer[afx->buffer_pos];
1004
6.88k
    cc2 = afx->buffer[afx->buffer_pos+1];
1005
6.88k
    cc3 = afx->buffer[afx->buffer_pos+2];
1006
6.88k
    if( isxdigit(cc1) && isxdigit(cc2)
1007
2.87k
          && strchr( "=\n\r\t ", cc3 )) {
1008
        /* well it seems to be the case - adjust */
1009
2.60k
        c = isdigit(cc1)? (cc1 - '0'): (ascii_toupper(cc1)-'A'+10);
1010
2.60k
        c <<= 4;
1011
2.60k
        c |= isdigit(cc2)? (cc2 - '0'): (ascii_toupper(cc2)-'A'+10);
1012
2.60k
        afx->buffer_pos += 2;
1013
2.60k
        afx->qp_detected = 1;
1014
2.60k
        goto again;
1015
2.60k
    }
1016
6.88k
      }
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
6.92k
            if (afx->buffer_pos + 6 < afx->buffer_len
1024
1.04k
                && afx->buffer[afx->buffer_pos + 0] == '3'
1025
16
                && 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
6
                && 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
6.92k
      if (!n)
1037
4.26k
        onlypad = 1;
1038
1039
6.92k
      if( idx == 1 )
1040
2.68k
    buf[n++] = val;
1041
6.92k
      checkcrc++;
1042
6.92k
      break;
1043
9.53k
  }
1044
68.7k
        else if (afx->buffer_pos == 1 && c == '-'
1045
2.24k
                 && afx->buffer_len > 9
1046
1.91k
                 && !strncmp (afx->buffer, "-----END ", 9)) {
1047
1.20k
            break; /* End in --dearmor mode or No CRC.  */
1048
1.20k
        }
1049
67.5k
  else {
1050
67.5k
      log_error(_("invalid radix64 character %02X skipped\n"), c);
1051
67.5k
      continue;
1052
67.5k
  }
1053
102k
    }
1054
1055
9.27k
    afx->idx = idx;
1056
9.27k
    afx->radbuf[0] = val;
1057
1058
9.27k
    if( n )
1059
6.56k
      {
1060
6.56k
        gcry_md_write (afx->crc_md, buf, n);
1061
6.56k
        afx->any_data = 1;
1062
6.56k
      }
1063
1064
9.27k
    if( checkcrc ) {
1065
6.92k
  gcry_md_final (afx->crc_md);
1066
6.92k
  afx->inp_checked=0;
1067
6.92k
  afx->faked = 0;
1068
11.2k
  for(;;) { /* skip lf and pad characters */
1069
11.2k
      if( afx->buffer_pos < afx->buffer_len )
1070
10.6k
    c = afx->buffer[afx->buffer_pos++];
1071
687
      else { /* read the next line */
1072
687
    unsigned maxlen = MAX_LINELEN;
1073
687
    afx->buffer_pos = 0;
1074
687
    afx->buffer_len = iobuf_read_line( a, &afx->buffer,
1075
687
               &afx->buffer_size, &maxlen );
1076
687
    if( !maxlen )
1077
0
        afx->truncated++;
1078
687
    if( !afx->buffer_len )
1079
60
        break; /* eof */
1080
627
    continue;
1081
687
      }
1082
10.6k
      if( c == '\n' || c == ' ' || c == '\r'
1083
7.86k
    || c == '\t' || c == '=' )
1084
3.74k
    continue;
1085
6.86k
      break;
1086
10.6k
  }
1087
6.92k
  if( !afx->buffer_len )
1088
6.92k
      log_error(_("premature eof (no CRC)\n"));
1089
6.86k
  else {
1090
6.86k
      u32 mycrc = 0;
1091
6.86k
      idx = 0;
1092
7.91k
      do {
1093
7.91k
    if( (binc = asctobin[0][c]) == 0xffffffffUL )
1094
6.52k
        break;
1095
1.38k
    switch(idx) {
1096
371
      case 0: val =  binc << 2; break;
1097
349
      case 1: val |= (binc>>4)&3; mycrc |= val << 16;val=(binc<<4)&0xf0;break;
1098
336
      case 2: val |= (binc>>2)&15; mycrc |= val << 8;val=(binc<<6)&0xc0;break;
1099
329
      case 3: val |= binc&0x3f; mycrc |= val; break;
1100
1.38k
    }
1101
1.38k
    for(;;) {
1102
1.38k
        if( afx->buffer_pos < afx->buffer_len )
1103
1.36k
      c = afx->buffer[afx->buffer_pos++];
1104
17
        else { /* read the next line */
1105
17
      unsigned maxlen = MAX_LINELEN;
1106
17
      afx->buffer_pos = 0;
1107
17
      afx->buffer_len = iobuf_read_line( a, &afx->buffer,
1108
17
                 &afx->buffer_size,
1109
17
                &maxlen );
1110
17
      if( !maxlen )
1111
0
          afx->truncated++;
1112
17
      if( !afx->buffer_len )
1113
17
          break; /* eof */
1114
0
      continue;
1115
17
        }
1116
1.36k
        break;
1117
1.38k
    }
1118
1.38k
    if( !afx->buffer_len )
1119
17
        break; /* eof */
1120
1.38k
      } while( ++idx < 4 );
1121
6.86k
      if( !afx->buffer_len ) {
1122
17
    log_info(_("premature eof (in CRC)\n"));
1123
17
    rc = invalid_crc();
1124
17
      }
1125
6.85k
      else if( idx == 0 ) {
1126
          /* No CRC at all is legal ("MAY") */
1127
6.49k
          rc=0;
1128
6.49k
      }
1129
354
      else if( idx != 4 ) {
1130
27
    log_info(_("malformed CRC\n"));
1131
27
    rc = invalid_crc();
1132
27
      }
1133
327
      else if( mycrc != get_afx_crc (afx) ) {
1134
50
    log_info (_("CRC error; %06lX - %06lX\n"),
1135
50
            (ulong)get_afx_crc (afx), (ulong)mycrc);
1136
50
    rc = invalid_crc();
1137
50
      }
1138
277
      else {
1139
277
    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
277
      }
1163
6.86k
  }
1164
6.92k
    }
1165
1166
9.27k
    if( !n && !onlypad )
1167
820
  rc = -1;
1168
1169
9.27k
    *retn = n;
1170
9.27k
    return rc;
1171
9.27k
}
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
29.8k
{
1295
29.8k
    size_t size = *ret_len;
1296
29.8k
    armor_filter_context_t *afx = opaque;
1297
29.8k
    int rc=0, c;
1298
29.8k
    byte radbuf[3];
1299
29.8k
    int  idx, idx2;
1300
29.8k
    size_t n=0;
1301
29.8k
    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
29.8k
    if( DBG_FILTER )
1312
29.8k
  log_debug("armor-filter: control: %d\n", control );
1313
29.8k
    if( control == IOBUFCTRL_UNDERFLOW && afx->inp_bypass ) {
1314
5.02k
  n = 0;
1315
5.02k
  if( afx->buffer_len ) {
1316
            /* Copy the data from AFX->BUFFER to BUF.  */
1317
25.0k
            for(; n < size && afx->buffer_pos < afx->buffer_len;)
1318
25.0k
                buf[n++] = afx->buffer[afx->buffer_pos++];
1319
38
      if( afx->buffer_pos >= afx->buffer_len )
1320
28
    afx->buffer_len = 0;
1321
38
  }
1322
        /* If there is still space in BUF, read directly into it.  */
1323
1.26M
  for(; n < size; n++ ) {
1324
1.26M
      if( (c=iobuf_get(a)) == -1 )
1325
4.97k
    break;
1326
1.25M
      buf[n] = c & 0xff;
1327
1.25M
  }
1328
5.02k
  if( !n )
1329
            /* We didn't get any data.  EOF.  */
1330
3.80k
      rc = -1;
1331
5.02k
  *ret_len = n;
1332
5.02k
    }
1333
24.8k
    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
13.7k
  if( size < PARTIAL_CHUNK+1 )
1338
0
      BUG(); /* supplied buffer too short */
1339
1340
13.7k
  if( afx->faked )
1341
0
      rc = fake_packet( afx, a, &n, buf, size );
1342
13.7k
  else if( !afx->inp_checked ) {
1343
12.3k
      rc = check_input( afx, a );
1344
12.3k
      if( afx->inp_bypass ) {
1345
1.06M
    for(n=0; n < size && afx->buffer_pos < afx->buffer_len; )
1346
1.05M
        buf[n++] = afx->buffer[afx->buffer_pos++];
1347
4.42k
    if( afx->buffer_pos >= afx->buffer_len )
1348
4.39k
        afx->buffer_len = 0;
1349
4.42k
    if( !n )
1350
50
        rc = -1;
1351
4.42k
      }
1352
7.90k
      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
7.90k
      else if( !rc )
1403
7.85k
    rc = radix64_read( afx, a, &n, buf, size );
1404
12.3k
  }
1405
1.42k
  else
1406
1.42k
      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
13.7k
  *ret_len = n;
1413
13.7k
    }
1414
11.1k
    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
11.1k
    else if( control == IOBUFCTRL_INIT )
1488
5.56k
      {
1489
5.56k
  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
5.56k
  if(afx->eol[0]==0)
1495
5.56k
    {
1496
#ifdef HAVE_DOSISH_SYSTEM
1497
      afx->eol[0]='\r';
1498
      afx->eol[1]='\n';
1499
#else
1500
5.56k
      afx->eol[0]='\n';
1501
5.56k
#endif
1502
5.56k
    }
1503
5.56k
      }
1504
5.56k
    else if( control == IOBUFCTRL_CANCEL ) {
1505
0
  afx->cancel = 1;
1506
0
    }
1507
5.56k
    else if( control == IOBUFCTRL_FREE ) {
1508
5.56k
  if( afx->cancel )
1509
0
      ;
1510
5.56k
  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
5.56k
  else if( !afx->any_data && !afx->inp_bypass ) {
1564
453
      log_error(_("no valid OpenPGP data found.\n"));
1565
453
      afx->no_openpgp_data = 1;
1566
453
      write_status_text( STATUS_NODATA, "1" );
1567
453
  }
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
5.56k
  if( afx->truncated )
1574
5.56k
      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
5.56k
  if( afx->qp_detected )
1578
5.56k
      log_error(_("quoted printable character in armor - "
1579
37
      "probably a buggy MTA has been used\n") );
1580
5.56k
  xfree( afx->buffer );
1581
5.56k
  afx->buffer = NULL;
1582
5.56k
        release_armor_context (afx);
1583
5.56k
    }
1584
0
    else if( control == IOBUFCTRL_DESC )
1585
0
        mem2str (buf, "armor_filter", *ret_len);
1586
29.8k
    return rc;
1587
29.8k
}
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
}