Coverage Report

Created: 2025-12-14 07:01

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
5.88M
#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
557
#define BEGIN_SIGNATURE 2
83
4.39k
#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
2.51k
{
116
2.51k
  armor_filter_context_t *afx;
117
2.51k
  gpg_error_t err;
118
119
2.51k
  afx = xcalloc (1, sizeof *afx);
120
2.51k
  if (afx)
121
2.51k
    {
122
2.51k
      err = gcry_md_open (&afx->crc_md, GCRY_MD_CRC24_RFC2440, 0);
123
2.51k
      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
2.51k
      afx->refcount = 1;
132
2.51k
    }
133
134
2.51k
  return afx;
135
2.51k
}
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
12.9k
{
142
12.9k
  if (!afx)
143
7.94k
    return;
144
12.9k
  log_assert (afx->refcount);
145
5.02k
  if ( --afx->refcount )
146
2.51k
    return;
147
2.51k
  gcry_md_close (afx->crc_md);
148
2.51k
  xfree (afx);
149
2.51k
}
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
2.51k
{
155
2.51k
  int rc;
156
157
2.51k
  afx->refcount++;
158
2.51k
  rc = iobuf_push_filter (iobuf, armor_filter, afx);
159
2.51k
  if (rc)
160
0
    afx->refcount--;
161
2.51k
  return rc;
162
2.51k
}
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
511
{
200
511
  const byte *crc_buf;
201
511
  u32 crc;
202
203
511
  crc_buf = gcry_md_read (afx->crc_md, GCRY_MD_CRC24_RFC2440);
204
205
511
  crc = crc_buf[0];
206
511
  crc <<= 8;
207
511
  crc |= crc_buf[1];
208
511
  crc <<= 8;
209
511
  crc |= crc_buf[2];
210
211
511
  return crc;
212
511
}
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.1k
{
227
15.1k
  int ctb, pkttype;
228
15.1k
  int indeterminate_length_allowed;
229
230
15.1k
    ctb = *buf;
231
15.1k
    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
5.88k
      return 1;
236
237
9.29k
    pkttype =  ctb & 0x40 ? (ctb & 0x3f) : ((ctb>>2)&0xf);
238
9.29k
    switch( pkttype ) {
239
144
      case PKT_PUBKEY_ENC:
240
2.43k
      case PKT_SIGNATURE:
241
2.56k
      case PKT_SYMKEY_ENC:
242
3.84k
      case PKT_ONEPASS_SIG:
243
3.94k
      case PKT_SECRET_KEY:
244
4.08k
      case PKT_PUBLIC_KEY:
245
4.35k
      case PKT_SECRET_SUBKEY:
246
4.45k
      case PKT_MARKER:
247
4.73k
      case PKT_RING_TRUST:
248
4.84k
      case PKT_USER_ID:
249
4.95k
      case PKT_PUBLIC_SUBKEY:
250
5.15k
      case PKT_ATTRIBUTE:
251
5.72k
      case PKT_MDC:
252
5.72k
  indeterminate_length_allowed = 0;
253
5.72k
        break;
254
255
1.81k
      case PKT_COMPRESSED:
256
1.92k
      case PKT_ENCRYPTED:
257
2.00k
      case PKT_ENCRYPTED_MDC:
258
2.07k
      case PKT_ENCRYPTED_AEAD:
259
2.95k
      case PKT_PLAINTEXT:
260
3.01k
      case PKT_OLD_COMMENT:
261
3.13k
      case PKT_COMMENT:
262
3.27k
      case PKT_GPG_CONTROL:
263
3.27k
  indeterminate_length_allowed = 1;
264
3.27k
        break;
265
266
293
      default:
267
        /* Invalid packet type.  */
268
293
        return 1;
269
9.29k
    }
270
271
9.00k
    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
5.72k
      {
277
5.72k
        int new_format;
278
5.72k
        int indeterminate_length;
279
280
5.72k
        new_format = !! (ctb & (1 << 6));
281
5.72k
        if (new_format)
282
2.17k
          indeterminate_length = (buf[1] >= 224 && buf[1] < 255);
283
3.55k
        else
284
3.55k
          indeterminate_length = (ctb & 3) == 3;
285
286
5.72k
        if (indeterminate_length)
287
928
          return 1;
288
5.72k
      }
289
290
    /* The first CTB seems legit.  It is probably not armored
291
       data.  */
292
8.07k
    return 0;
293
9.00k
}
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
10.4k
{
304
10.4k
    byte buf[2];
305
10.4k
    int n;
306
307
    /* fixme: there might be a problem with iobuf_peek */
308
10.4k
    n = iobuf_peek (a, buf, 2);
309
10.4k
    if( n == -1 )
310
0
  return 0; /* EOF, doesn't matter whether armored or not */
311
10.4k
    if( !n )
312
0
  return 1; /* can't check it: try armored */
313
10.4k
    if (n != 2)
314
30
  return 0; /* short buffer */
315
10.4k
    return is_armored(buf);
316
10.4k
}
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
707
{
339
707
    const char *s, *s2;
340
707
    unsigned found = 0;
341
342
707
    if( strlen(line) < 6  || strlen(line) > 60 )
343
62
  return 0; /* too short or too long */
344
645
    if( memcmp( line, "Hash:", 5 ) )
345
146
  return 0; /* invalid header */
346
347
1.36k
    for(s=line+5;;s=s2) {
348
1.88k
  for(; *s && (*s==' ' || *s == '\t'); s++ )
349
519
      ;
350
1.36k
  if( !*s )
351
328
      break;
352
2.76k
  for(s2=s+1; *s2 && *s2!=' ' && *s2 != '\t' && *s2 != ','; s2++ )
353
1.72k
      ;
354
1.03k
  if( !strncmp( s, "RIPEMD160", s2-s ) )
355
108
      found |= 1;
356
929
  else if( !strncmp( s, "SHA1", s2-s ) )
357
568
      found |= 2;
358
361
  else if( !strncmp( s, "SHA224", s2-s ) )
359
14
      found |= 8;
360
347
  else if( !strncmp( s, "SHA256", s2-s ) )
361
93
      found |= 16;
362
254
  else if( !strncmp( s, "SHA384", s2-s ) )
363
94
      found |= 32;
364
160
  else if( !strncmp( s, "SHA512", s2-s ) )
365
6
      found |= 64;
366
154
  else
367
154
      return 0;
368
1.22k
  for(; *s2 && (*s2==' ' || *s2 == '\t'); s2++ )
369
337
      ;
370
883
  if( *s2 && *s2 != ',' )
371
17
      return 0;
372
866
  if( *s2 )
373
544
      s2++;
374
866
    }
375
328
    return found;
376
499
}
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
1.99k
{
382
1.99k
  if(strncmp(line,"Version",7)==0
383
1.73k
     || strncmp(line,"Comment",7)==0
384
1.59k
     || strncmp(line,"MessageID",9)==0
385
1.47k
     || strncmp(line,"Hash",4)==0
386
1.14k
     || strncmp(line,"Charset",7)==0)
387
1.12k
    return 1;
388
389
870
  return 0;
390
1.99k
}
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
4.34M
{
400
4.34M
    const char *s;
401
4.34M
    byte *save_p, *p;
402
4.34M
    int save_c;
403
4.34M
    int i;
404
405
4.34M
    if( len < 15 )
406
4.30M
  return -1; /* too short */
407
41.8k
    if( memcmp( line, "-----", 5 ) )
408
34.4k
  return -1; /* no */
409
7.41k
    p = strstr( line+5, "-----");
410
7.41k
    if( !p )
411
846
  return -1;
412
6.57k
    save_p = p;
413
6.57k
    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
6.57k
    if(RFC2440)
424
0
      {
425
0
  if( *p == '\r' )
426
0
    p++;
427
0
  if( *p == '\n' )
428
0
    p++;
429
0
      }
430
6.57k
    else
431
13.4k
      while(*p==' ' || *p=='\r' || *p=='\n' || *p=='\t')
432
6.91k
  p++;
433
434
6.57k
    if( *p )
435
570
  return -1; /* garbage after dashes */
436
6.00k
    save_c = *save_p; *save_p = 0;
437
6.00k
    p = line+5;
438
22.0k
    for(i=0; (s=head_strings[i]); i++ )
439
20.5k
  if( !strcmp(s, p) )
440
4.45k
      break;
441
6.00k
    *save_p = save_c;
442
6.00k
    if (!s)
443
1.55k
      {
444
1.55k
        if (!strncmp (p, "BEGIN ", 6))
445
862
          return 42;
446
689
  return -1; /* unknown armor line */
447
1.55k
      }
448
449
4.45k
    if( opt.verbose > 1 )
450
4.45k
  log_info(_("armor: %s\n"), head_strings[i]);
451
4.45k
    return i;
452
6.00k
}
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
7.02k
{
465
7.02k
    byte *p;
466
7.02k
    int hashes=0;
467
7.02k
    unsigned int len2;
468
469
7.02k
    len2 = length_sans_trailing_ws ( line, len );
470
7.02k
    if( !len2 ) {
471
2.05k
        afx->buffer_pos = len2;  /* (it is not the fine way to do it here) */
472
2.05k
  return 0; /* WS only: same as empty line */
473
2.05k
    }
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
4.97k
    p = strchr( line, ':');
486
4.97k
    if (!p && afx->dearmor_state)
487
0
      return 0; /* Special treatment in --dearmor mode.  */
488
4.97k
    if( !p || (RFC2440 && p[1]!=' ')
489
2.74k
  || (!RFC2440 && p[1]!=' ' && p[1]!='\n' && p[1]!='\r'))
490
2.27k
      {
491
2.27k
  log_error (_("invalid armor header: "));
492
2.27k
  es_write_sanitized (log_get_stream (), line, len, NULL, NULL);
493
2.27k
  log_printf ("\n");
494
2.27k
  return -1;
495
2.27k
      }
496
497
    /* Chop off the whitespace we detected before */
498
2.69k
    len=len2;
499
2.69k
    line[len2]='\0';
500
501
2.69k
    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.69k
    if (afx->dearmor_mode)
508
0
      ;
509
2.69k
    else if (afx->in_cleartext)
510
707
      {
511
707
  if( (hashes=parse_hash_header( line )) )
512
328
    afx->hashes |= hashes;
513
379
  else if( strlen(line) > 15 && !memcmp( line, "NotDashEscaped:", 15 ) )
514
114
    afx->not_dash_escaped = 1;
515
265
  else
516
265
    {
517
265
      log_error(_("invalid clearsig header\n"));
518
265
      return -1;
519
265
    }
520
707
      }
521
1.99k
    else if(!is_armor_tag(line))
522
870
      {
523
  /* Section 6.2: "Unknown keys should be reported to the user,
524
     but OpenPGP should continue to process the message."  Note
525
     that in a clearsigned message this applies to the signature
526
     part (i.e. "BEGIN PGP SIGNATURE") and not the signed data
527
     ("BEGIN PGP SIGNED MESSAGE").  The only key allowed in the
528
     signed data section is "Hash". */
529
530
870
  log_info(_("unknown armor header: "));
531
870
  es_write_sanitized (log_get_stream (), line, len, NULL, NULL);
532
870
  log_printf ("\n");
533
870
      }
534
535
2.43k
    return 1;
536
2.69k
}
537
538
539
540
/* figure out whether the data is armored or not */
541
static int
542
check_input( armor_filter_context_t *afx, IOBUF a )
543
5.29k
{
544
5.29k
    int rc = 0;
545
5.29k
    int i;
546
5.29k
    byte *line;
547
5.29k
    unsigned len;
548
5.29k
    unsigned maxlen;
549
5.29k
    int hdr_line = -1;
550
551
    /* read the first line to see whether this is armored data */
552
5.29k
    maxlen = MAX_LINELEN;
553
5.29k
    len = afx->buffer_len = iobuf_read_line( a, &afx->buffer,
554
5.29k
               &afx->buffer_size, &maxlen );
555
5.29k
    line = afx->buffer;
556
5.29k
    if( !maxlen ) {
557
  /* line has been truncated: assume not armored */
558
18
  afx->inp_checked = 1;
559
18
  afx->inp_bypass = 1;
560
18
  return 0;
561
18
    }
562
563
5.27k
    if( !len ) {
564
28
  return -1; /* eof */
565
28
    }
566
567
    /* (the line is always a C string but maybe longer) */
568
5.24k
    if( *line == '\n' || ( len && (*line == '\r' && line[1]=='\n') ) )
569
488
  ;
570
4.76k
    else if (len >= 2 && !is_armored (line)) {
571
155
  afx->inp_checked = 1;
572
155
  afx->inp_bypass = 1;
573
155
  return 0;
574
155
    }
575
576
    /* find the armor header */
577
4.34M
    while(len) {
578
4.34M
  i = is_armor_header( line, len );
579
4.34M
        if ( i == 42 ) {
580
739
            if (afx->dearmor_mode) {
581
0
                afx->dearmor_state = 1;
582
0
                break;
583
0
            }
584
739
        }
585
4.34M
        else if (i >= 0
586
4.39k
                 && !(afx->only_keyblocks && i != 1 && i != 5 && i != 6 )) {
587
4.39k
      hdr_line = i;
588
4.39k
      if( hdr_line == BEGIN_SIGNED_MSG_IDX ) {
589
933
          if( afx->in_cleartext ) {
590
0
        log_error(_("nested clear text signatures\n"));
591
0
        rc = gpg_error (GPG_ERR_INV_ARMOR);
592
0
                }
593
933
    afx->in_cleartext = 1;
594
933
      }
595
4.39k
      break;
596
4.39k
  }
597
598
  /* read the next line (skip all truncated lines) */
599
4.34M
  do {
600
4.34M
      maxlen = MAX_LINELEN;
601
4.34M
      afx->buffer_len = iobuf_read_line( a, &afx->buffer,
602
4.34M
                 &afx->buffer_size, &maxlen );
603
4.34M
      line = afx->buffer;
604
4.34M
      len = afx->buffer_len;
605
4.34M
  } while( !maxlen );
606
4.33M
    }
607
608
    /* Parse the header lines.  */
609
7.35k
    while(len) {
610
  /* Read the next line (skip all truncated lines). */
611
6.72k
  do {
612
6.72k
      maxlen = MAX_LINELEN;
613
6.72k
      afx->buffer_len = iobuf_read_line( a, &afx->buffer,
614
6.72k
                 &afx->buffer_size, &maxlen );
615
6.72k
      line = afx->buffer;
616
6.72k
      len = afx->buffer_len;
617
6.72k
  } while( !maxlen );
618
619
6.65k
  i = parse_header_line( afx, line, len );
620
6.65k
  if( i <= 0 ) {
621
4.39k
      if (i && RFC2440)
622
0
    rc = GPG_ERR_INV_ARMOR;
623
4.39k
      break;
624
4.39k
  }
625
6.65k
    }
626
627
628
5.09k
    if( rc )
629
0
  invalid_armor();
630
5.09k
    else if( afx->in_cleartext )
631
933
  afx->faked = 1;
632
4.16k
    else {
633
4.16k
  afx->inp_checked = 1;
634
4.16k
  gcry_md_reset (afx->crc_md);
635
4.16k
  afx->idx = 0;
636
4.16k
  afx->radbuf[0] = 0;
637
4.16k
    }
638
639
5.09k
    return rc;
640
5.24k
}
641
642
20.9M
#define PARTIAL_CHUNK 512
643
12.8k
#define PARTIAL_POW   9
644
645
/****************
646
 * Fake a literal data packet and wait for the next armor line
647
 * fixme: empty line handling and null length clear text signature are
648
 *    not implemented/checked.
649
 */
650
static int
651
fake_packet( armor_filter_context_t *afx, IOBUF a,
652
       size_t *retn, byte *buf, size_t size  )
653
1.03k
{
654
1.03k
    int rc = 0;
655
1.03k
    size_t len = 0;
656
1.03k
    int lastline = 0;
657
1.03k
    unsigned maxlen, n;
658
1.03k
    byte *p;
659
1.03k
    byte tempbuf[PARTIAL_CHUNK];
660
1.03k
    size_t tempbuf_len=0;
661
1.03k
    int this_truncated;
662
663
1.54M
    while( !rc && size-len>=(PARTIAL_CHUNK+1)) {
664
  /* copy what we have in the line buffer */
665
1.54M
  if( afx->faked == 1 )
666
927
      afx->faked++; /* skip the first (empty) line */
667
1.54M
  else
668
1.54M
    {
669
      /* It's full, so write this partial chunk */
670
1.54M
      if(tempbuf_len==PARTIAL_CHUNK)
671
12.8k
        {
672
12.8k
    buf[len++]=0xE0+PARTIAL_POW;
673
12.8k
    memcpy(&buf[len],tempbuf,PARTIAL_CHUNK);
674
12.8k
    len+=PARTIAL_CHUNK;
675
12.8k
    tempbuf_len=0;
676
12.8k
    continue;
677
12.8k
        }
678
679
8.16M
      while( tempbuf_len < PARTIAL_CHUNK
680
8.15M
       && afx->buffer_pos < afx->buffer_len )
681
6.63M
        tempbuf[tempbuf_len++] = afx->buffer[afx->buffer_pos++];
682
1.53M
      if( tempbuf_len==PARTIAL_CHUNK )
683
12.8k
        continue;
684
1.53M
    }
685
686
  /* read the next line */
687
1.52M
  maxlen = MAX_LINELEN;
688
1.52M
  afx->buffer_pos = 0;
689
1.52M
  afx->buffer_len = iobuf_read_line( a, &afx->buffer,
690
1.52M
             &afx->buffer_size, &maxlen );
691
1.52M
  if( !afx->buffer_len ) {
692
527
      rc = -1; /* eof (should not happen) */
693
527
      continue;
694
527
  }
695
1.52M
  if( !maxlen )
696
100
          {
697
100
      afx->truncated++;
698
100
            this_truncated = 1;
699
100
          }
700
1.52M
        else
701
1.52M
          this_truncated = 0;
702
703
704
1.52M
  p = afx->buffer;
705
1.52M
  n = afx->buffer_len;
706
707
  /* Armor header or dash-escaped line? */
708
1.52M
  if(p[0]=='-')
709
2.22k
    {
710
      /* 2440bis-10: When reversing dash-escaping, an
711
         implementation MUST strip the string "- " if it occurs
712
         at the beginning of a line, and SHOULD warn on "-" and
713
         any character other than a space at the beginning of a
714
         line.  */
715
716
2.22k
      if(p[1]==' ' && !afx->not_dash_escaped)
717
218
        {
718
    /* It's a dash-escaped line, so skip over the
719
       escape. */
720
218
    afx->buffer_pos = 2;
721
218
        }
722
2.00k
      else if(p[1]=='-' && p[2]=='-' && p[3]=='-' && p[4]=='-')
723
555
        {
724
    /* Five dashes in a row mean it's probably armor
725
       header. */
726
555
    int type = is_armor_header( p, n );
727
555
                if (type == 42)
728
123
                  type = -1;  /* Only OpenPGP armors are expected.  */
729
555
    if( afx->not_dash_escaped && type != BEGIN_SIGNATURE )
730
155
      ; /* this is okay */
731
400
    else
732
400
      {
733
400
        if( type != BEGIN_SIGNATURE )
734
378
          {
735
378
      log_info(_("unexpected armor: "));
736
378
      es_write_sanitized (log_get_stream (), p, n,
737
378
                                            NULL, NULL);
738
378
      log_printf ("\n");
739
378
          }
740
741
400
        lastline = 1;
742
400
        rc = -1;
743
400
      }
744
555
        }
745
1.44k
      else if(!afx->not_dash_escaped)
746
1.06k
        {
747
    /* Bad dash-escaping. */
748
1.06k
    log_info (_("invalid dash escaped line: "));
749
1.06k
    es_write_sanitized (log_get_stream (), p, n, NULL, NULL);
750
1.06k
    log_printf ("\n");
751
1.06k
        }
752
2.22k
    }
753
754
  /* Now handle the end-of-line canonicalization */
755
1.52M
  if( !afx->not_dash_escaped || this_truncated)
756
1.52M
    {
757
1.52M
      int crlf = n > 1 && p[n-2] == '\r' && p[n-1]=='\n';
758
759
1.52M
      afx->buffer_len=
760
1.52M
        trim_trailing_chars( &p[afx->buffer_pos], n-afx->buffer_pos,
761
1.52M
           " \t\r\n");
762
1.52M
      afx->buffer_len+=afx->buffer_pos;
763
      /* the buffer is always allocated with enough space to append
764
       * the removed [CR], LF and a Nul
765
       * The reason for this complicated procedure is to keep at least
766
       * the original type of lineending - handling of the removed
767
       * trailing spaces seems to be impossible in our method
768
       * of faking a packet; either we have to use a temporary file
769
       * or calculate the hash here in this module and somehow find
770
       * a way to send the hash down the processing line (well, a special
771
       * faked packet could do the job).
772
             *
773
             * To make sure that a truncated line triggers a bad
774
             * signature error we replace a removed LF by a FF or
775
             * append a FF.  Right, this is a hack but better than a
776
             * global variable and way easier than to introduce a new
777
             * control packet or insert a line like "[truncated]\n"
778
             * into the filter output.
779
       */
780
1.52M
      if( crlf )
781
1.13k
        afx->buffer[afx->buffer_len++] = '\r';
782
1.52M
      afx->buffer[afx->buffer_len++] = this_truncated? '\f':'\n';
783
1.52M
      afx->buffer[afx->buffer_len] = '\0';
784
1.52M
    }
785
1.52M
    }
786
787
1.03k
    if( lastline ) { /* write last (ending) length header */
788
400
        if(tempbuf_len<192)
789
304
    buf[len++]=tempbuf_len;
790
96
  else
791
96
    {
792
96
      buf[len++]=((tempbuf_len-192)/256) + 192;
793
96
      buf[len++]=(tempbuf_len-192) % 256;
794
96
    }
795
400
  memcpy(&buf[len],tempbuf,tempbuf_len);
796
400
  len+=tempbuf_len;
797
798
400
  rc = 0;
799
400
  afx->faked = 0;
800
400
  afx->in_cleartext = 0;
801
  /* and now read the header lines */
802
400
  afx->buffer_pos = 0;
803
571
  for(;;) {
804
571
      int i;
805
806
      /* read the next line (skip all truncated lines) */
807
601
      do {
808
601
    maxlen = MAX_LINELEN;
809
601
    afx->buffer_len = iobuf_read_line( a, &afx->buffer,
810
601
             &afx->buffer_size, &maxlen );
811
601
      } while( !maxlen );
812
571
      p = afx->buffer;
813
571
      n = afx->buffer_len;
814
571
      if( !n ) {
815
202
    rc = -1;
816
202
    break; /* eof */
817
202
      }
818
369
      i = parse_header_line( afx, p , n );
819
369
      if( i <= 0 ) {
820
198
    if( i )
821
0
        invalid_armor();
822
198
    break;
823
198
      }
824
369
  }
825
400
  afx->inp_checked = 1;
826
400
  gcry_md_reset (afx->crc_md);
827
400
  afx->idx = 0;
828
400
  afx->radbuf[0] = 0;
829
400
    }
830
831
1.03k
    *retn = len;
832
1.03k
    return rc;
833
1.03k
}
834
835
836
static int
837
invalid_crc(void)
838
178
{
839
178
  if ( opt.ignore_crc_error )
840
0
    return 0;
841
178
  log_inc_errorcount();
842
178
  return gpg_error (GPG_ERR_INV_ARMOR);
843
178
}
844
845
846
static int
847
radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
848
        byte *buf, size_t size )
849
4.55k
{
850
4.55k
    byte val;
851
4.55k
    int c;
852
4.55k
    u32 binc;
853
4.55k
    int checkcrc=0;
854
4.55k
    int rc = 0;
855
4.55k
    size_t n = 0;
856
4.55k
    int idx, onlypad=0;
857
4.55k
    int skip_fast = 0;
858
859
4.55k
    idx = afx->idx;
860
4.55k
    val = afx->radbuf[0];
861
442k
    for( n=0; n < size; ) {
862
863
442k
  if( afx->buffer_pos < afx->buffer_len )
864
431k
      c = afx->buffer[afx->buffer_pos++];
865
10.6k
  else { /* read the next line */
866
10.6k
      unsigned maxlen = MAX_LINELEN;
867
10.6k
      afx->buffer_pos = 0;
868
10.6k
      afx->buffer_len = iobuf_read_line( a, &afx->buffer,
869
10.6k
                 &afx->buffer_size, &maxlen );
870
10.6k
      if( !maxlen )
871
2
    afx->truncated++;
872
10.6k
      if( !afx->buffer_len )
873
1.33k
    break; /* eof */
874
9.28k
      continue;
875
10.6k
  }
876
877
432k
      again:
878
432k
  binc = asctobin[0][c];
879
880
432k
  if( binc != 0xffffffffUL )
881
181k
    {
882
181k
      if( idx == 0 && skip_fast == 0
883
63.9k
    && afx->buffer_pos + (16 - 1) < afx->buffer_len
884
47.5k
    && n + 12 < size)
885
47.3k
        {
886
    /* Fast path for radix64 to binary conversion.  */
887
47.3k
    u32 b0,b1,b2,b3;
888
889
    /* Speculatively load 15 more input bytes.  */
890
47.3k
    b0 = binc << (3 * 6);
891
47.3k
    b0 |= asctobin[2][afx->buffer[afx->buffer_pos + 0]];
892
47.3k
    b0 |= asctobin[1][afx->buffer[afx->buffer_pos + 1]];
893
47.3k
    b0 |= asctobin[0][afx->buffer[afx->buffer_pos + 2]];
894
47.3k
    b1  = asctobin[3][afx->buffer[afx->buffer_pos + 3]];
895
47.3k
    b1 |= asctobin[2][afx->buffer[afx->buffer_pos + 4]];
896
47.3k
    b1 |= asctobin[1][afx->buffer[afx->buffer_pos + 5]];
897
47.3k
    b1 |= asctobin[0][afx->buffer[afx->buffer_pos + 6]];
898
47.3k
    b2  = asctobin[3][afx->buffer[afx->buffer_pos + 7]];
899
47.3k
    b2 |= asctobin[2][afx->buffer[afx->buffer_pos + 8]];
900
47.3k
    b2 |= asctobin[1][afx->buffer[afx->buffer_pos + 9]];
901
47.3k
    b2 |= asctobin[0][afx->buffer[afx->buffer_pos + 10]];
902
47.3k
    b3  = asctobin[3][afx->buffer[afx->buffer_pos + 11]];
903
47.3k
    b3 |= asctobin[2][afx->buffer[afx->buffer_pos + 12]];
904
47.3k
    b3 |= asctobin[1][afx->buffer[afx->buffer_pos + 13]];
905
47.3k
    b3 |= asctobin[0][afx->buffer[afx->buffer_pos + 14]];
906
907
    /* Check if any of the input bytes were invalid. */
908
47.3k
    if( (b0 | b1 | b2 | b3) != 0xffffffffUL )
909
20.4k
      {
910
        /* All 16 bytes are valid. */
911
20.4k
        buf[n + 0] = b0 >> (2 * 8);
912
20.4k
        buf[n + 1] = b0 >> (1 * 8);
913
20.4k
        buf[n + 2] = b0 >> (0 * 8);
914
20.4k
        buf[n + 3] = b1 >> (2 * 8);
915
20.4k
        buf[n + 4] = b1 >> (1 * 8);
916
20.4k
        buf[n + 5] = b1 >> (0 * 8);
917
20.4k
        buf[n + 6] = b2 >> (2 * 8);
918
20.4k
        buf[n + 7] = b2 >> (1 * 8);
919
20.4k
        buf[n + 8] = b2 >> (0 * 8);
920
20.4k
        buf[n + 9] = b3 >> (2 * 8);
921
20.4k
        buf[n + 10] = b3 >> (1 * 8);
922
20.4k
        buf[n + 11] = b3 >> (0 * 8);
923
20.4k
        afx->buffer_pos += 16 - 1;
924
20.4k
        n += 12;
925
20.4k
        continue;
926
20.4k
      }
927
26.8k
    else if( b0 == 0xffffffffUL )
928
15.2k
      {
929
        /* byte[1..3] have invalid character(s).  Switch to slow
930
           path.  */
931
15.2k
        skip_fast = 1;
932
15.2k
      }
933
11.6k
    else if( b1 == 0xffffffffUL )
934
8.15k
      {
935
        /* byte[4..7] have invalid character(s), first 4 bytes are
936
           valid.  */
937
8.15k
        buf[n + 0] = b0 >> (2 * 8);
938
8.15k
        buf[n + 1] = b0 >> (1 * 8);
939
8.15k
        buf[n + 2] = b0 >> (0 * 8);
940
8.15k
        afx->buffer_pos += 4 - 1;
941
8.15k
        n += 3;
942
8.15k
        skip_fast = 1;
943
8.15k
        continue;
944
8.15k
      }
945
3.47k
    else if( b2 == 0xffffffffUL )
946
1.92k
      {
947
        /* byte[8..11] have invalid character(s), first 8 bytes are
948
           valid.  */
949
1.92k
        buf[n + 0] = b0 >> (2 * 8);
950
1.92k
        buf[n + 1] = b0 >> (1 * 8);
951
1.92k
        buf[n + 2] = b0 >> (0 * 8);
952
1.92k
        buf[n + 3] = b1 >> (2 * 8);
953
1.92k
        buf[n + 4] = b1 >> (1 * 8);
954
1.92k
        buf[n + 5] = b1 >> (0 * 8);
955
1.92k
        afx->buffer_pos += 8 - 1;
956
1.92k
        n += 6;
957
1.92k
        skip_fast = 1;
958
1.92k
        continue;
959
1.92k
      }
960
1.55k
    else /*if( b3 == 0xffffffffUL )*/
961
1.55k
      {
962
        /* byte[12..15] have invalid character(s), first 12 bytes
963
           are valid.  */
964
1.55k
        buf[n + 0] = b0 >> (2 * 8);
965
1.55k
        buf[n + 1] = b0 >> (1 * 8);
966
1.55k
        buf[n + 2] = b0 >> (0 * 8);
967
1.55k
        buf[n + 3] = b1 >> (2 * 8);
968
1.55k
        buf[n + 4] = b1 >> (1 * 8);
969
1.55k
        buf[n + 5] = b1 >> (0 * 8);
970
1.55k
        buf[n + 6] = b2 >> (2 * 8);
971
1.55k
        buf[n + 7] = b2 >> (1 * 8);
972
1.55k
        buf[n + 8] = b2 >> (0 * 8);
973
1.55k
        afx->buffer_pos += 12 - 1;
974
1.55k
        n += 9;
975
1.55k
        skip_fast = 1;
976
1.55k
        continue;
977
1.55k
      }
978
47.3k
        }
979
980
149k
      switch(idx)
981
149k
        {
982
38.8k
    case 0: val =  binc << 2; break;
983
37.6k
    case 1: val |= (binc>>4)&3; buf[n++]=val;val=(binc<<4)&0xf0;break;
984
36.9k
    case 2: val |= (binc>>2)&15; buf[n++]=val;val=(binc<<6)&0xc0;break;
985
35.9k
    case 3: val |= binc&0x3f; buf[n++] = val; break;
986
149k
        }
987
149k
      idx = (idx+1) % 4;
988
989
149k
      continue;
990
149k
    }
991
992
251k
  skip_fast = 0;
993
994
251k
  if( c == '\n' || c == ' ' || c == '\r' || c == '\t' )
995
20.9k
      continue;
996
230k
  else if( c == '=' ) { /* pad character: stop */
997
      /* some mailers leave quoted-printable encoded characters
998
       * so we try to workaround this */
999
4.11k
      if( afx->buffer_pos+2 < afx->buffer_len ) {
1000
2.32k
    int cc1, cc2, cc3;
1001
2.32k
    cc1 = afx->buffer[afx->buffer_pos];
1002
2.32k
    cc2 = afx->buffer[afx->buffer_pos+1];
1003
2.32k
    cc3 = afx->buffer[afx->buffer_pos+2];
1004
2.32k
    if( isxdigit(cc1) && isxdigit(cc2)
1005
1.09k
          && strchr( "=\n\r\t ", cc3 )) {
1006
        /* well it seems to be the case - adjust */
1007
984
        c = isdigit(cc1)? (cc1 - '0'): (ascii_toupper(cc1)-'A'+10);
1008
984
        c <<= 4;
1009
984
        c |= isdigit(cc2)? (cc2 - '0'): (ascii_toupper(cc2)-'A'+10);
1010
984
        afx->buffer_pos += 2;
1011
984
        afx->qp_detected = 1;
1012
984
        goto again;
1013
984
    }
1014
2.32k
      }
1015
1016
            /* Occasionally a bug MTA will leave the = escaped as
1017
               =3D.  If the 4 characters following that are valid
1018
               Radix64 characters and they are following by a new
1019
               line, assume that this is the case and skip the
1020
               3D.  */
1021
3.12k
            if (afx->buffer_pos + 6 < afx->buffer_len
1022
868
                && afx->buffer[afx->buffer_pos + 0] == '3'
1023
30
                && afx->buffer[afx->buffer_pos + 1] == 'D'
1024
28
                && asctobin[0][afx->buffer[afx->buffer_pos + 2]] != 0xffffffffUL
1025
24
                && asctobin[0][afx->buffer[afx->buffer_pos + 3]] != 0xffffffffUL
1026
21
                && asctobin[0][afx->buffer[afx->buffer_pos + 4]] != 0xffffffffUL
1027
17
                && asctobin[0][afx->buffer[afx->buffer_pos + 5]] != 0xffffffffUL
1028
15
                && afx->buffer[afx->buffer_pos + 6] == '\n')
1029
2
              {
1030
2
                afx->buffer_pos += 2;
1031
2
                afx->qp_detected = 1;
1032
2
              }
1033
1034
3.12k
      if (!n)
1035
1.08k
        onlypad = 1;
1036
1037
3.12k
      if( idx == 1 )
1038
1.07k
    buf[n++] = val;
1039
3.12k
      checkcrc++;
1040
3.12k
      break;
1041
4.11k
  }
1042
226k
        else if (afx->buffer_pos == 1 && c == '-'
1043
616
                 && afx->buffer_len > 9
1044
441
                 && !strncmp (afx->buffer, "-----END ", 9)) {
1045
0
            break; /* End in --dearmor mode or No CRC.  */
1046
0
        }
1047
226k
  else {
1048
226k
      log_error(_("invalid radix64 character %02X skipped\n"), c);
1049
226k
      continue;
1050
226k
  }
1051
251k
    }
1052
1053
4.55k
    afx->idx = idx;
1054
4.55k
    afx->radbuf[0] = val;
1055
1056
4.55k
    if( n )
1057
3.16k
      {
1058
3.16k
        gcry_md_write (afx->crc_md, buf, n);
1059
3.16k
        afx->any_data = 1;
1060
3.16k
      }
1061
1062
4.55k
    if( checkcrc ) {
1063
3.12k
  gcry_md_final (afx->crc_md);
1064
3.12k
  afx->inp_checked=0;
1065
3.12k
  afx->faked = 0;
1066
39.4k
  for(;;) { /* skip lf and pad characters */
1067
39.4k
      if( afx->buffer_pos < afx->buffer_len )
1068
38.0k
    c = afx->buffer[afx->buffer_pos++];
1069
1.38k
      else { /* read the next line */
1070
1.38k
    unsigned maxlen = MAX_LINELEN;
1071
1.38k
    afx->buffer_pos = 0;
1072
1.38k
    afx->buffer_len = iobuf_read_line( a, &afx->buffer,
1073
1.38k
               &afx->buffer_size, &maxlen );
1074
1.38k
    if( !maxlen )
1075
0
        afx->truncated++;
1076
1.38k
    if( !afx->buffer_len )
1077
86
        break; /* eof */
1078
1.30k
    continue;
1079
1.38k
      }
1080
38.0k
      if( c == '\n' || c == ' ' || c == '\r'
1081
29.9k
    || c == '\t' || c == '=' )
1082
34.9k
    continue;
1083
3.04k
      break;
1084
38.0k
  }
1085
3.12k
  if( !afx->buffer_len )
1086
3.12k
      log_error(_("premature eof (no CRC)\n"));
1087
3.04k
  else {
1088
3.04k
      u32 mycrc = 0;
1089
3.04k
      idx = 0;
1090
4.37k
      do {
1091
4.37k
    if( (binc = asctobin[0][c]) == 0xffffffffUL )
1092
2.56k
        break;
1093
1.81k
    switch(idx) {
1094
511
      case 0: val =  binc << 2; break;
1095
445
      case 1: val |= (binc>>4)&3; mycrc |= val << 16;val=(binc<<4)&0xf0;break;
1096
433
      case 2: val |= (binc>>2)&15; mycrc |= val << 8;val=(binc<<6)&0xc0;break;
1097
422
      case 3: val |= binc&0x3f; mycrc |= val; break;
1098
1.81k
    }
1099
1.81k
    for(;;) {
1100
1.81k
        if( afx->buffer_pos < afx->buffer_len )
1101
1.75k
      c = afx->buffer[afx->buffer_pos++];
1102
52
        else { /* read the next line */
1103
52
      unsigned maxlen = MAX_LINELEN;
1104
52
      afx->buffer_pos = 0;
1105
52
      afx->buffer_len = iobuf_read_line( a, &afx->buffer,
1106
52
                 &afx->buffer_size,
1107
52
                &maxlen );
1108
52
      if( !maxlen )
1109
0
          afx->truncated++;
1110
52
      if( !afx->buffer_len )
1111
52
          break; /* eof */
1112
0
      continue;
1113
52
        }
1114
1.75k
        break;
1115
1.81k
    }
1116
1.81k
    if( !afx->buffer_len )
1117
52
        break; /* eof */
1118
1.81k
      } while( ++idx < 4 );
1119
3.04k
      if( !afx->buffer_len ) {
1120
52
    log_info(_("premature eof (in CRC)\n"));
1121
52
    rc = invalid_crc();
1122
52
      }
1123
2.98k
      else if( idx == 0 ) {
1124
          /* No CRC at all is legal ("MAY") */
1125
2.52k
          rc=0;
1126
2.52k
      }
1127
459
      else if( idx != 4 ) {
1128
37
    log_info(_("malformed CRC\n"));
1129
37
    rc = invalid_crc();
1130
37
      }
1131
422
      else if( mycrc != get_afx_crc (afx) ) {
1132
89
    log_info (_("CRC error; %06lX - %06lX\n"),
1133
89
            (ulong)get_afx_crc (afx), (ulong)mycrc);
1134
89
    rc = invalid_crc();
1135
89
      }
1136
333
      else {
1137
333
    rc = 0;
1138
                /* FIXME: Here we should emit another control packet,
1139
                 * so that we know in mainproc that we are processing
1140
                 * a clearsign message */
1141
#if 0
1142
    for(rc=0;!rc;) {
1143
        rc = 0 /*check_trailer( &fhdr, c )*/;
1144
        if( !rc ) {
1145
      if( (c=iobuf_get(a)) == -1 )
1146
          rc = 2;
1147
        }
1148
    }
1149
    if( rc == -1 )
1150
        rc = 0;
1151
    else if( rc == 2 ) {
1152
        log_error(_("premature eof (in trailer)\n"));
1153
        rc = GPG_ERR_INV_ARMOR;
1154
    }
1155
    else {
1156
        log_error(_("error in trailer line\n"));
1157
        rc = GPG_ERR_INV_ARMOR;
1158
    }
1159
#endif
1160
333
      }
1161
3.04k
  }
1162
3.12k
    }
1163
1164
4.55k
    if( !n && !onlypad )
1165
1.14k
  rc = -1;
1166
1167
4.55k
    *retn = n;
1168
4.55k
    return rc;
1169
4.55k
}
1170
1171
static void
1172
armor_output_buf_as_radix64 (armor_filter_context_t *afx, IOBUF a,
1173
           byte *buf, size_t size)
1174
0
{
1175
0
  byte radbuf[sizeof (afx->radbuf)];
1176
0
  byte outbuf[64 + sizeof (afx->eol)];
1177
0
  unsigned int eollen = strlen (afx->eol);
1178
0
  u32 in, in2;
1179
0
  int idx, idx2;
1180
0
  int i;
1181
1182
0
  idx = afx->idx;
1183
0
  idx2 = afx->idx2;
1184
0
  memcpy (radbuf, afx->radbuf, sizeof (afx->radbuf));
1185
1186
0
  if (size && (idx || idx2))
1187
0
    {
1188
      /* preload eol to outbuf buffer */
1189
0
      memcpy (outbuf + 4, afx->eol, sizeof (afx->eol));
1190
1191
0
      for (; size && (idx || idx2); buf++, size--)
1192
0
  {
1193
0
    radbuf[idx++] = *buf;
1194
0
    if (idx > 2)
1195
0
      {
1196
0
        idx = 0;
1197
0
        in = (u32)radbuf[0] << (2 * 8);
1198
0
        in |= (u32)radbuf[1] << (1 * 8);
1199
0
        in |= (u32)radbuf[2] << (0 * 8);
1200
0
        outbuf[0] = bintoasc[(in >> 18) & 077];
1201
0
        outbuf[1] = bintoasc[(in >> 12) & 077];
1202
0
        outbuf[2] = bintoasc[(in >> 6) & 077];
1203
0
        outbuf[3] = bintoasc[(in >> 0) & 077];
1204
0
        if (++idx2 >= (64/4))
1205
0
    { /* pgp doesn't like 72 here */
1206
0
      idx2=0;
1207
0
      iobuf_write (a, outbuf, 4 + eollen);
1208
0
    }
1209
0
        else
1210
0
    {
1211
0
      iobuf_write (a, outbuf, 4);
1212
0
    }
1213
0
      }
1214
0
  }
1215
0
    }
1216
1217
0
  if (size >= (64/4)*3)
1218
0
    {
1219
      /* preload eol to outbuf buffer */
1220
0
      memcpy (outbuf + 64, afx->eol, sizeof(afx->eol));
1221
1222
0
      do
1223
0
  {
1224
    /* idx and idx2 == 0 */
1225
1226
0
    for (i = 0; i < (64/8); i++)
1227
0
      {
1228
0
        in = (u32)buf[0] << (2 * 8);
1229
0
        in |= (u32)buf[1] << (1 * 8);
1230
0
        in |= (u32)buf[2] << (0 * 8);
1231
0
        in2 = (u32)buf[3] << (2 * 8);
1232
0
        in2 |= (u32)buf[4] << (1 * 8);
1233
0
        in2 |= (u32)buf[5] << (0 * 8);
1234
0
        outbuf[i*8+0] = bintoasc[(in >> 18) & 077];
1235
0
        outbuf[i*8+1] = bintoasc[(in >> 12) & 077];
1236
0
        outbuf[i*8+2] = bintoasc[(in >> 6) & 077];
1237
0
        outbuf[i*8+3] = bintoasc[(in >> 0) & 077];
1238
0
        outbuf[i*8+4] = bintoasc[(in2 >> 18) & 077];
1239
0
        outbuf[i*8+5] = bintoasc[(in2 >> 12) & 077];
1240
0
        outbuf[i*8+6] = bintoasc[(in2 >> 6) & 077];
1241
0
        outbuf[i*8+7] = bintoasc[(in2 >> 0) & 077];
1242
0
        buf+=6;
1243
0
        size-=6;
1244
0
      }
1245
1246
    /* pgp doesn't like 72 here */
1247
0
    iobuf_write (a, outbuf, 64 + eollen);
1248
0
  }
1249
0
      while (size >= (64/4)*3);
1250
1251
      /* restore eol for tail handling */
1252
0
      if (size)
1253
0
  memcpy (outbuf + 4, afx->eol, sizeof (afx->eol));
1254
0
    }
1255
1256
0
  for (; size; buf++, size--)
1257
0
    {
1258
0
      radbuf[idx++] = *buf;
1259
0
      if (idx > 2)
1260
0
  {
1261
0
    idx = 0;
1262
0
    in = (u32)radbuf[0] << (2 * 8);
1263
0
    in |= (u32)radbuf[1] << (1 * 8);
1264
0
    in |= (u32)radbuf[2] << (0 * 8);
1265
0
    outbuf[0] = bintoasc[(in >> 18) & 077];
1266
0
    outbuf[1] = bintoasc[(in >> 12) & 077];
1267
0
    outbuf[2] = bintoasc[(in >> 6) & 077];
1268
0
    outbuf[3] = bintoasc[(in >> 0) & 077];
1269
0
    if (++idx2 >= (64/4))
1270
0
      { /* pgp doesn't like 72 here */
1271
0
        idx2=0;
1272
0
        iobuf_write (a, outbuf, 4 + eollen);
1273
0
      }
1274
0
    else
1275
0
      {
1276
0
        iobuf_write (a, outbuf, 4);
1277
0
      }
1278
0
  }
1279
0
    }
1280
1281
0
  memcpy (afx->radbuf, radbuf, sizeof (afx->radbuf));
1282
0
  afx->idx = idx;
1283
0
  afx->idx2 = idx2;
1284
0
}
1285
1286
/****************
1287
 * This filter is used to handle the armor stuff
1288
 */
1289
static int
1290
armor_filter( void *opaque, int control,
1291
       IOBUF a, byte *buf, size_t *ret_len)
1292
12.3k
{
1293
12.3k
    size_t size = *ret_len;
1294
12.3k
    armor_filter_context_t *afx = opaque;
1295
12.3k
    int rc=0, c;
1296
12.3k
    byte radbuf[3];
1297
12.3k
    int  idx, idx2;
1298
12.3k
    size_t n=0;
1299
12.3k
    u32 crc;
1300
#if 0
1301
    static FILE *fp ;
1302
1303
    if( !fp ) {
1304
  fp = fopen("armor.out", "w");
1305
  log_assert(fp);
1306
    }
1307
#endif
1308
1309
12.3k
    if( DBG_FILTER )
1310
12.3k
  log_debug("armor-filter: control: %d\n", control );
1311
12.3k
    if( control == IOBUFCTRL_UNDERFLOW && afx->inp_bypass ) {
1312
624
  n = 0;
1313
624
  if( afx->buffer_len ) {
1314
            /* Copy the data from AFX->BUFFER to BUF.  */
1315
495k
            for(; n < size && afx->buffer_pos < afx->buffer_len;)
1316
494k
                buf[n++] = afx->buffer[afx->buffer_pos++];
1317
174
      if( afx->buffer_pos >= afx->buffer_len )
1318
72
    afx->buffer_len = 0;
1319
174
  }
1320
        /* If there is still space in BUF, read directly into it.  */
1321
7.87M
  for(; n < size; n++ ) {
1322
7.87M
      if( (c=iobuf_get(a)) == -1 )
1323
247
    break;
1324
7.87M
      buf[n] = c & 0xff;
1325
7.87M
  }
1326
624
  if( !n )
1327
            /* We didn't get any data.  EOF.  */
1328
127
      rc = -1;
1329
624
  *ret_len = n;
1330
624
    }
1331
11.7k
    else if( control == IOBUFCTRL_UNDERFLOW ) {
1332
        /* We need some space for the faked packet.  The minimum
1333
         * required size is the PARTIAL_CHUNK size plus a byte for the
1334
         * length itself */
1335
6.71k
  if( size < PARTIAL_CHUNK+1 )
1336
0
      BUG(); /* supplied buffer too short */
1337
1338
6.71k
  if( afx->faked )
1339
1.03k
      rc = fake_packet( afx, a, &n, buf, size );
1340
5.68k
  else if( !afx->inp_checked ) {
1341
5.29k
      rc = check_input( afx, a );
1342
5.29k
      if( afx->inp_bypass ) {
1343
452k
    for(n=0; n < size && afx->buffer_pos < afx->buffer_len; )
1344
452k
        buf[n++] = afx->buffer[afx->buffer_pos++];
1345
173
    if( afx->buffer_pos >= afx->buffer_len )
1346
93
        afx->buffer_len = 0;
1347
173
    if( !n )
1348
8
        rc = -1;
1349
173
      }
1350
5.12k
      else if( afx->faked ) {
1351
933
          unsigned int hashes = afx->hashes;
1352
933
                const byte *sesmark;
1353
933
                size_t sesmarklen;
1354
1355
933
                sesmark = get_session_marker( &sesmarklen );
1356
933
                if ( sesmarklen > 20 )
1357
0
                    BUG();
1358
1359
    /* the buffer is at least 15+n*15 bytes long, so it
1360
     * is easy to construct the packets */
1361
1362
933
    hashes &= 1|2|8|16|32|64;
1363
933
    if( !hashes ) {
1364
843
        hashes |= 2;  /* Default to SHA-1. */
1365
843
    }
1366
933
    n=0;
1367
                /* First a gpg control packet... */
1368
933
                buf[n++] = 0xff; /* new format, type 63, 1 length byte */
1369
933
                n++;   /* see below */
1370
933
                memcpy(buf+n, sesmark, sesmarklen ); n+= sesmarklen;
1371
933
                buf[n++] = CTRLPKT_CLEARSIGN_START;
1372
933
                buf[n++] = afx->not_dash_escaped? 0:1; /* sigclass */
1373
933
                if( hashes & 1 )
1374
26
                    buf[n++] = DIGEST_ALGO_RMD160;
1375
933
                if( hashes & 2 )
1376
876
                    buf[n++] = DIGEST_ALGO_SHA1;
1377
933
                if( hashes & 8 )
1378
8
                    buf[n++] = DIGEST_ALGO_SHA224;
1379
933
                if( hashes & 16 )
1380
31
                    buf[n++] = DIGEST_ALGO_SHA256;
1381
933
                if( hashes & 32 )
1382
12
                    buf[n++] = DIGEST_ALGO_SHA384;
1383
933
                if( hashes & 64 )
1384
4
                    buf[n++] = DIGEST_ALGO_SHA512;
1385
933
                buf[1] = n - 2;
1386
1387
    /* ...followed by an invented plaintext packet.
1388
       Amusingly enough, this packet is not compliant with
1389
       2440 as the initial partial length is less than 512
1390
       bytes.  Of course, we'll accept it anyway ;) */
1391
1392
933
    buf[n++] = 0xCB; /* new packet format, type 11 */
1393
933
    buf[n++] = 0xE1; /* 2^1 == 2 bytes */
1394
933
    buf[n++] = 't';  /* canonical text mode */
1395
933
    buf[n++] = 0;  /* namelength */
1396
933
    buf[n++] = 0xE2; /* 2^2 == 4 more bytes */
1397
933
    memset(buf+n, 0, 4); /* timestamp */
1398
933
    n += 4;
1399
933
      }
1400
4.18k
      else if( !rc )
1401
4.16k
    rc = radix64_read( afx, a, &n, buf, size );
1402
5.29k
  }
1403
390
  else
1404
390
      rc = radix64_read( afx, a, &n, buf, size );
1405
#if 0
1406
  if( n )
1407
      if( fwrite(buf, n, 1, fp ) != 1 )
1408
    BUG();
1409
#endif
1410
6.71k
  *ret_len = n;
1411
6.71k
    }
1412
5.02k
    else if( control == IOBUFCTRL_FLUSH && !afx->cancel ) {
1413
0
  if( !afx->status ) { /* write the header line */
1414
0
      const char *s;
1415
0
      strlist_t comment=opt.comments;
1416
1417
0
      if( afx->what >= DIM(head_strings) )
1418
0
    log_bug("afx->what=%d", afx->what);
1419
0
      iobuf_writestr(a, "-----");
1420
0
      iobuf_writestr(a, head_strings[afx->what] );
1421
0
      iobuf_writestr(a, "-----" );
1422
0
      iobuf_writestr(a,afx->eol);
1423
0
      if (opt.emit_version)
1424
0
        {
1425
0
    iobuf_writestr (a, "Version: "GNUPG_NAME" v");
1426
0
                for (s=VERSION; *s && *s != '.'; s++)
1427
0
                  iobuf_writebyte (a, *s);
1428
0
                if (opt.emit_version > 1 && *s)
1429
0
                  {
1430
0
                    iobuf_writebyte (a, *s++);
1431
0
                    for (; *s && *s != '.'; s++)
1432
0
                      iobuf_writebyte (a, *s);
1433
0
                    if (opt.emit_version > 2)
1434
0
                      {
1435
0
                        for (; *s && *s != '-' && !spacep (s); s++)
1436
0
                          iobuf_writebyte (a, *s);
1437
0
                        if (opt.emit_version > 3)
1438
0
                          iobuf_writestr (a, " (" PRINTABLE_OS_NAME ")");
1439
0
                      }
1440
0
                  }
1441
0
    iobuf_writestr(a,afx->eol);
1442
0
        }
1443
1444
      /* write the comment strings */
1445
0
      for(;comment;comment=comment->next)
1446
0
        {
1447
0
    iobuf_writestr(a, "Comment: " );
1448
0
    for( s=comment->d; *s; s++ )
1449
0
      {
1450
0
        if( *s == '\n' )
1451
0
          iobuf_writestr(a, "\\n" );
1452
0
        else if( *s == '\r' )
1453
0
          iobuf_writestr(a, "\\r" );
1454
0
        else if( *s == '\v' )
1455
0
          iobuf_writestr(a, "\\v" );
1456
0
        else
1457
0
          iobuf_put(a, *s );
1458
0
      }
1459
1460
0
    iobuf_writestr(a,afx->eol);
1461
0
        }
1462
1463
0
      if ( afx->hdrlines ) {
1464
0
                for ( s = afx->hdrlines; *s; s++ ) {
1465
#ifdef HAVE_DOSISH_SYSTEM
1466
                    if ( *s == '\n' )
1467
                        iobuf_put( a, '\r');
1468
#endif
1469
0
                    iobuf_put(a, *s );
1470
0
                }
1471
0
            }
1472
1473
0
      iobuf_writestr(a,afx->eol);
1474
0
      afx->status++;
1475
0
      afx->idx = 0;
1476
0
      afx->idx2 = 0;
1477
0
      gcry_md_reset (afx->crc_md);
1478
0
  }
1479
1480
0
  if( size ) {
1481
0
      gcry_md_write (afx->crc_md, buf, size);
1482
0
      armor_output_buf_as_radix64 (afx, a, buf, size);
1483
0
        }
1484
0
    }
1485
5.02k
    else if( control == IOBUFCTRL_INIT )
1486
2.51k
      {
1487
2.51k
  if( !is_initialized )
1488
1
    initialize();
1489
1490
  /* Figure out what we're using for line endings if the caller
1491
     didn't specify. */
1492
2.51k
  if(afx->eol[0]==0)
1493
2.51k
    {
1494
#ifdef HAVE_DOSISH_SYSTEM
1495
      afx->eol[0]='\r';
1496
      afx->eol[1]='\n';
1497
#else
1498
2.51k
      afx->eol[0]='\n';
1499
2.51k
#endif
1500
2.51k
    }
1501
2.51k
      }
1502
2.51k
    else if( control == IOBUFCTRL_CANCEL ) {
1503
0
  afx->cancel = 1;
1504
0
    }
1505
2.51k
    else if( control == IOBUFCTRL_FREE ) {
1506
2.51k
  if( afx->cancel )
1507
0
      ;
1508
2.51k
  else if( afx->status ) { /* pad, write checksum, and bottom line */
1509
0
      gcry_md_final (afx->crc_md);
1510
0
      crc = get_afx_crc (afx);
1511
0
      idx = afx->idx;
1512
0
      idx2 = afx->idx2;
1513
0
      if( idx ) {
1514
0
    c = bintoasc[(afx->radbuf[0]>>2)&077];
1515
0
    iobuf_put(a, c);
1516
0
    if( idx == 1 ) {
1517
0
        c = bintoasc[((afx->radbuf[0] << 4) & 060) & 077];
1518
0
        iobuf_put(a, c);
1519
0
        iobuf_put(a, '=');
1520
0
        iobuf_put(a, '=');
1521
0
    }
1522
0
    else { /* 2 */
1523
0
        c = bintoasc[(((afx->radbuf[0]<<4)&060)
1524
0
                                  |((afx->radbuf[1]>>4)&017))&077];
1525
0
        iobuf_put(a, c);
1526
0
        c = bintoasc[((afx->radbuf[1] << 2) & 074) & 077];
1527
0
        iobuf_put(a, c);
1528
0
        iobuf_put(a, '=');
1529
0
    }
1530
0
    if( ++idx2 >= (64/4) )
1531
0
      { /* pgp doesn't like 72 here */
1532
0
        iobuf_writestr(a,afx->eol);
1533
0
        idx2=0;
1534
0
      }
1535
0
      }
1536
      /* may need a linefeed */
1537
0
      if( idx2 )
1538
0
        iobuf_writestr(a,afx->eol);
1539
      /* write the CRC */
1540
0
      iobuf_put(a, '=');
1541
0
      radbuf[0] = crc >>16;
1542
0
      radbuf[1] = crc >> 8;
1543
0
      radbuf[2] = crc;
1544
0
      c = bintoasc[(*radbuf >> 2) & 077];
1545
0
      iobuf_put(a, c);
1546
0
      c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
1547
0
      iobuf_put(a, c);
1548
0
      c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
1549
0
      iobuf_put(a, c);
1550
0
      c = bintoasc[radbuf[2]&077];
1551
0
      iobuf_put(a, c);
1552
0
      iobuf_writestr(a,afx->eol);
1553
      /* and the trailer */
1554
0
      if( afx->what >= DIM(tail_strings) )
1555
0
    log_bug("afx->what=%d", afx->what);
1556
0
      iobuf_writestr(a, "-----");
1557
0
      iobuf_writestr(a, tail_strings[afx->what] );
1558
0
      iobuf_writestr(a, "-----" );
1559
0
      iobuf_writestr(a,afx->eol);
1560
0
  }
1561
2.51k
  else if( !afx->any_data && !afx->inp_bypass ) {
1562
1.69k
      log_error(_("no valid OpenPGP data found.\n"));
1563
1.69k
      afx->no_openpgp_data = 1;
1564
1.69k
      write_status_text( STATUS_NODATA, "1" );
1565
1.69k
  }
1566
        /* Note that in a cleartext signature truncated lines in the
1567
         * plaintext are detected and propagated to the signature
1568
         * checking code by inserting a \f into the plaintext.  We do
1569
         * not use log_info here because some of the truncated lines
1570
         * are harmless.  */
1571
2.51k
  if( afx->truncated )
1572
2.51k
      log_info(_("invalid armor: line longer than %d characters\n"),
1573
20
          MAX_LINELEN );
1574
  /* issue an error to enforce dissemination of correct software */
1575
2.51k
  if( afx->qp_detected )
1576
2.51k
      log_error(_("quoted printable character in armor - "
1577
48
      "probably a buggy MTA has been used\n") );
1578
2.51k
  xfree( afx->buffer );
1579
2.51k
  afx->buffer = NULL;
1580
2.51k
        release_armor_context (afx);
1581
2.51k
    }
1582
0
    else if( control == IOBUFCTRL_DESC )
1583
0
        mem2str (buf, "armor_filter", *ret_len);
1584
12.3k
    return rc;
1585
12.3k
}
1586
1587
1588
/****************
1589
 * create a radix64 encoded string.
1590
 */
1591
char *
1592
make_radix64_string( const byte *data, size_t len )
1593
0
{
1594
0
    char *buffer, *p;
1595
1596
0
    buffer = p = xmalloc( (len+2)/3*4 + 1 );
1597
0
    for( ; len >= 3 ; len -= 3, data += 3 ) {
1598
0
  *p++ = bintoasc[(data[0] >> 2) & 077];
1599
0
  *p++ = bintoasc[(((data[0] <<4)&060)|((data[1] >> 4)&017))&077];
1600
0
  *p++ = bintoasc[(((data[1]<<2)&074)|((data[2]>>6)&03))&077];
1601
0
  *p++ = bintoasc[data[2]&077];
1602
0
    }
1603
0
    if( len == 2 ) {
1604
0
  *p++ = bintoasc[(data[0] >> 2) & 077];
1605
0
  *p++ = bintoasc[(((data[0] <<4)&060)|((data[1] >> 4)&017))&077];
1606
0
  *p++ = bintoasc[((data[1]<<2)&074)];
1607
0
    }
1608
0
    else if( len == 1 ) {
1609
0
  *p++ = bintoasc[(data[0] >> 2) & 077];
1610
0
  *p++ = bintoasc[(data[0] <<4)&060];
1611
0
    }
1612
0
    *p = 0;
1613
0
    return buffer;
1614
0
}