Coverage Report

Created: 2026-07-16 06:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gnupg/g10/armor.c
Line
Count
Source
1
/* armor.c - Armor filter
2
 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
3
 *               2007 Free Software Foundation, Inc.
4
 *
5
 * This file is part of GnuPG.
6
 *
7
 * GnuPG is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * GnuPG is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, see <https://www.gnu.org/licenses/>.
19
 */
20
21
#include <config.h>
22
#include <stdio.h>
23
#include <stdlib.h>
24
#include <string.h>
25
#include <errno.h>
26
#include <ctype.h>
27
28
#include "gpg.h"
29
#include "../common/status.h"
30
#include "../common/iobuf.h"
31
#include "../common/util.h"
32
#include "filter.h"
33
#include "packet.h"
34
#include "options.h"
35
#include "main.h"
36
#include "../common/i18n.h"
37
38
1.01M
#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
2.01k
#define BEGIN_SIGNATURE 2
83
9.13k
#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
3.52k
{
116
3.52k
  armor_filter_context_t *afx;
117
3.52k
  gpg_error_t err;
118
119
3.52k
  afx = xcalloc (1, sizeof *afx);
120
3.52k
  if (afx)
121
3.52k
    {
122
3.52k
      err = gcry_md_open (&afx->crc_md, GCRY_MD_CRC24_RFC2440, 0);
123
3.52k
      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
3.52k
      afx->refcount = 1;
132
3.52k
    }
133
134
3.52k
  return afx;
135
3.52k
}
136
137
/* Release an armor filter context.  Passing NULL is explicitly
138
   allowed and a no-op.  */
139
void
140
release_armor_context (armor_filter_context_t *afx)
141
13.4k
{
142
13.4k
  if (!afx)
143
6.41k
    return;
144
13.4k
  log_assert (afx->refcount);
145
7.04k
  if ( --afx->refcount )
146
3.52k
    return;
147
3.52k
  gcry_md_close (afx->crc_md);
148
3.52k
  xfree (afx);
149
3.52k
}
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
3.52k
{
155
3.52k
  int rc;
156
157
3.52k
  afx->refcount++;
158
3.52k
  rc = iobuf_push_filter (iobuf, armor_filter, afx);
159
3.52k
  if (rc)
160
0
    afx->refcount--;
161
3.52k
  return rc;
162
3.52k
}
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
505
{
200
505
  const byte *crc_buf;
201
505
  u32 crc;
202
203
505
  crc_buf = gcry_md_read (afx->crc_md, GCRY_MD_CRC24_RFC2440);
204
205
505
  crc = crc_buf[0];
206
505
  crc <<= 8;
207
505
  crc |= crc_buf[1];
208
505
  crc <<= 8;
209
505
  crc |= crc_buf[2];
210
211
505
  return crc;
212
505
}
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
25.0k
{
227
25.0k
  int ctb, pkttype;
228
25.0k
  int indeterminate_length_allowed;
229
230
25.0k
    ctb = *buf;
231
25.0k
    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
10.0k
      return 1;
236
237
15.0k
    pkttype =  ctb & 0x40 ? (ctb & 0x3f) : ((ctb>>2)&0xf);
238
15.0k
    switch( pkttype ) {
239
410
      case PKT_PUBKEY_ENC:
240
1.81k
      case PKT_SIGNATURE:
241
2.23k
      case PKT_SYMKEY_ENC:
242
2.49k
      case PKT_ONEPASS_SIG:
243
2.63k
      case PKT_SECRET_KEY:
244
6.11k
      case PKT_PUBLIC_KEY:
245
6.44k
      case PKT_SECRET_SUBKEY:
246
6.57k
      case PKT_MARKER:
247
6.94k
      case PKT_RING_TRUST:
248
7.32k
      case PKT_USER_ID:
249
7.55k
      case PKT_PUBLIC_SUBKEY:
250
8.40k
      case PKT_ATTRIBUTE:
251
8.47k
      case PKT_MDC:
252
8.47k
  indeterminate_length_allowed = 0;
253
8.47k
        break;
254
255
3.07k
      case PKT_COMPRESSED:
256
3.42k
      case PKT_ENCRYPTED:
257
3.67k
      case PKT_ENCRYPTED_MDC:
258
3.78k
      case PKT_ENCRYPTED_AEAD:
259
4.41k
      case PKT_PLAINTEXT:
260
4.54k
      case PKT_OLD_COMMENT:
261
4.61k
      case PKT_COMMENT:
262
4.83k
      case PKT_GPG_CONTROL:
263
4.83k
  indeterminate_length_allowed = 1;
264
4.83k
        break;
265
266
1.70k
      default:
267
        /* Invalid packet type.  */
268
1.70k
        return 1;
269
15.0k
    }
270
271
13.3k
    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
8.47k
      {
277
8.47k
        int new_format;
278
8.47k
        int indeterminate_length;
279
280
8.47k
        new_format = !! (ctb & (1 << 6));
281
8.47k
        if (new_format)
282
4.47k
          indeterminate_length = (buf[1] >= 224 && buf[1] < 255);
283
4.00k
        else
284
4.00k
          indeterminate_length = (ctb & 3) == 3;
285
286
8.47k
        if (indeterminate_length)
287
250
          return 1;
288
8.47k
      }
289
290
    /* The first CTB seems legit.  It is probably not armored
291
       data.  */
292
13.0k
    return 0;
293
13.3k
}
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
16.3k
{
304
16.3k
    byte buf[2];
305
16.3k
    int n;
306
307
    /* fixme: there might be a problem with iobuf_peek */
308
16.3k
    n = iobuf_peek (a, buf, 2);
309
16.3k
    if( n == -1 )
310
0
  return 0; /* EOF, doesn't matter whether armored or not */
311
16.3k
    if( !n )
312
0
  return 1; /* can't check it: try armored */
313
16.3k
    if (n != 2)
314
42
  return 0; /* short buffer */
315
16.3k
    return is_armored(buf);
316
16.3k
}
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
1.61k
{
339
1.61k
    const char *s, *s2;
340
1.61k
    unsigned found = 0;
341
342
1.61k
    if( strlen(line) < 6  || strlen(line) > 60 )
343
10
  return 0; /* too short or too long */
344
1.60k
    if( memcmp( line, "Hash:", 5 ) )
345
25
  return 0; /* invalid header */
346
347
5.16k
    for(s=line+5;;s=s2) {
348
6.77k
  for(; *s && (*s==' ' || *s == '\t'); s++ )
349
1.60k
      ;
350
5.16k
  if( !*s )
351
1.37k
      break;
352
12.1k
  for(s2=s+1; *s2 && *s2!=' ' && *s2 != '\t' && *s2 != ','; s2++ )
353
8.37k
      ;
354
3.79k
  if( !strncmp( s, "RIPEMD160", s2-s ) )
355
656
      found |= 1;
356
3.13k
  else if( !strncmp( s, "SHA1", s2-s ) )
357
1.17k
      found |= 2;
358
1.96k
  else if( !strncmp( s, "SHA224", s2-s ) )
359
672
      found |= 8;
360
1.29k
  else if( !strncmp( s, "SHA256", s2-s ) )
361
702
      found |= 16;
362
588
  else if( !strncmp( s, "SHA384", s2-s ) )
363
38
      found |= 32;
364
550
  else if( !strncmp( s, "SHA512", s2-s ) )
365
350
      found |= 64;
366
200
  else
367
200
      return 0;
368
4.38k
  for(; *s2 && (*s2==' ' || *s2 == '\t'); s2++ )
369
790
      ;
370
3.59k
  if( *s2 && *s2 != ',' )
371
6
      return 0;
372
3.58k
  if( *s2 )
373
2.27k
      s2++;
374
3.58k
    }
375
1.37k
    return found;
376
1.58k
}
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
5.87k
{
382
5.87k
  if(strncmp(line,"Version",7)==0
383
4.94k
     || strncmp(line,"Comment",7)==0
384
4.44k
     || strncmp(line,"MessageID",9)==0
385
3.96k
     || strncmp(line,"Hash",4)==0
386
3.24k
     || strncmp(line,"Charset",7)==0)
387
3.85k
    return 1;
388
389
2.02k
  return 0;
390
5.87k
}
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
585k
{
400
585k
    const char *s;
401
585k
    byte *save_p, *p;
402
585k
    int save_c;
403
585k
    int i;
404
405
585k
    if( len < 15 )
406
561k
  return -1; /* too short */
407
23.9k
    if( memcmp( line, "-----", 5 ) )
408
10.9k
  return -1; /* no */
409
13.0k
    p = strstr( line+5, "-----");
410
13.0k
    if( !p )
411
1.63k
  return -1;
412
11.3k
    save_p = p;
413
11.3k
    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
11.3k
    if(RFC2440)
424
0
      {
425
0
  if( *p == '\r' )
426
0
    p++;
427
0
  if( *p == '\n' )
428
0
    p++;
429
0
      }
430
11.3k
    else
431
22.9k
      while(*p==' ' || *p=='\r' || *p=='\n' || *p=='\t')
432
11.5k
  p++;
433
434
11.3k
    if( *p )
435
476
  return -1; /* garbage after dashes */
436
10.9k
    save_c = *save_p; *save_p = 0;
437
10.9k
    p = line+5;
438
34.6k
    for(i=0; (s=head_strings[i]); i++ )
439
33.0k
  if( !strcmp(s, p) )
440
9.22k
      break;
441
10.9k
    *save_p = save_c;
442
10.9k
    if (!s)
443
1.68k
      {
444
1.68k
        if (!strncmp (p, "BEGIN ", 6))
445
1.03k
          return 42;
446
645
  return -1; /* unknown armor line */
447
1.68k
      }
448
449
9.22k
    if( opt.verbose > 1 )
450
9.22k
  log_info(_("armor: %s\n"), head_strings[i]);
451
9.22k
    return i;
452
10.9k
}
453
454
455
456
/****************
457
 * Parse a header lines
458
 * Return 0: Empty line (end of header lines)
459
 *   -1: invalid header line
460
 *   >0: Good header line
461
 */
462
static int
463
parse_header_line( armor_filter_context_t *afx, byte *line, unsigned int len )
464
18.1k
{
465
18.1k
    byte *p;
466
18.1k
    int hashes=0;
467
18.1k
    unsigned int len2;
468
469
18.1k
    len2 = length_sans_trailing_ws ( line, len );
470
18.1k
    if( !len2 ) {
471
5.84k
        afx->buffer_pos = len2;  /* (it is not the fine way to do it here) */
472
5.84k
  return 0; /* WS only: same as empty line */
473
5.84k
    }
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
12.3k
    p = strchr( line, ':');
486
12.3k
    if (!p && afx->dearmor_state)
487
0
      return 0; /* Special treatment in --dearmor mode.  */
488
12.3k
    if( !p || (RFC2440 && p[1]!=' ')
489
8.48k
  || (!RFC2440 && p[1]!=' ' && p[1]!='\n' && p[1]!='\r'))
490
4.86k
      {
491
4.86k
  log_error (_("invalid armor header: "));
492
4.86k
  es_write_sanitized (log_get_stream (), line, len, NULL, NULL);
493
4.86k
  log_printf ("\n");
494
4.86k
  return -1;
495
4.86k
      }
496
497
    /* Chop off the whitespace we detected before */
498
7.49k
    len=len2;
499
7.49k
    line[len2]='\0';
500
501
7.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
7.49k
    if (afx->dearmor_mode)
508
0
      ;
509
7.49k
    else if (afx->in_cleartext)
510
1.61k
      {
511
1.61k
  if( (hashes=parse_hash_header( line )) )
512
1.37k
    afx->hashes |= hashes;
513
243
  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
243
  else
518
243
    {
519
243
      log_error(_("invalid clearsig header\n"));
520
243
      return -1;
521
243
    }
522
1.61k
      }
523
5.87k
    else if(!is_armor_tag(line))
524
2.02k
      {
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
2.02k
  log_info(_("unknown armor header: "));
533
2.02k
  es_write_sanitized (log_get_stream (), line, len, NULL, NULL);
534
2.02k
  log_printf ("\n");
535
2.02k
      }
536
537
7.25k
    return 1;
538
7.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
10.3k
{
546
10.3k
    int rc = 0;
547
10.3k
    int i;
548
10.3k
    byte *line;
549
10.3k
    unsigned len;
550
10.3k
    unsigned maxlen;
551
10.3k
    int hdr_line = -1;
552
553
    /* read the first line to see whether this is armored data */
554
10.3k
    maxlen = MAX_LINELEN;
555
10.3k
    len = afx->buffer_len = iobuf_read_line( a, &afx->buffer,
556
10.3k
               &afx->buffer_size, &maxlen );
557
10.3k
    line = afx->buffer;
558
10.3k
    if( !maxlen ) {
559
  /* line has been truncated: assume not armored */
560
26
  afx->inp_checked = 1;
561
26
  afx->inp_bypass = 1;
562
26
  return 0;
563
26
    }
564
565
10.2k
    if( !len ) {
566
126
  return -1; /* eof */
567
126
    }
568
569
    /* (the line is always a C string but maybe longer) */
570
10.1k
    if( *line == '\n' || ( len && (*line == '\r' && line[1]=='\n') ) )
571
1.40k
  ;
572
8.76k
    else if (len >= 2 && !is_armored (line)) {
573
272
  afx->inp_checked = 1;
574
272
  afx->inp_bypass = 1;
575
272
  return 0;
576
272
    }
577
578
    /* find the armor header */
579
584k
    while(len) {
580
583k
  i = is_armor_header( line, len );
581
583k
        if ( i == 42 ) {
582
760
            if (afx->dearmor_mode) {
583
0
                afx->dearmor_state = 1;
584
0
                break;
585
0
            }
586
760
        }
587
582k
        else if (i >= 0
588
9.13k
                 && !(afx->only_keyblocks && i != 1 && i != 5 && i != 6 )) {
589
9.13k
      hdr_line = i;
590
9.13k
      if( hdr_line == BEGIN_SIGNED_MSG_IDX ) {
591
2.57k
          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
2.57k
    afx->in_cleartext = 1;
596
2.57k
      }
597
9.13k
      break;
598
9.13k
  }
599
600
  /* read the next line (skip all truncated lines) */
601
574k
  do {
602
574k
      maxlen = MAX_LINELEN;
603
574k
      afx->buffer_len = iobuf_read_line( a, &afx->buffer,
604
574k
                 &afx->buffer_size, &maxlen );
605
574k
      line = afx->buffer;
606
574k
      len = afx->buffer_len;
607
574k
  } while( !maxlen );
608
574k
    }
609
610
    /* Parse the header lines.  */
611
17.0k
    while(len) {
612
  /* Read the next line (skip all truncated lines). */
613
16.2k
  do {
614
16.2k
      maxlen = MAX_LINELEN;
615
16.2k
      afx->buffer_len = iobuf_read_line( a, &afx->buffer,
616
16.2k
                 &afx->buffer_size, &maxlen );
617
16.2k
      line = afx->buffer;
618
16.2k
      len = afx->buffer_len;
619
16.2k
  } while( !maxlen );
620
621
16.2k
  i = parse_header_line( afx, line, len );
622
16.2k
  if( i <= 0 ) {
623
9.13k
      if (i && RFC2440)
624
0
    rc = GPG_ERR_INV_ARMOR;
625
9.13k
      break;
626
9.13k
  }
627
16.2k
    }
628
629
630
9.89k
    if( rc )
631
0
  invalid_armor();
632
9.89k
    else if( afx->in_cleartext )
633
2.57k
  afx->faked = 1;
634
7.31k
    else {
635
7.31k
  afx->inp_checked = 1;
636
7.31k
  gcry_md_reset (afx->crc_md);
637
7.31k
  afx->idx = 0;
638
7.31k
  afx->radbuf[0] = 0;
639
7.31k
    }
640
641
9.89k
    return rc;
642
10.1k
}
643
644
5.72M
#define PARTIAL_CHUNK 512
645
3.64k
#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
2.58k
{
656
2.58k
    int rc = 0;
657
2.58k
    size_t len = 0;
658
2.58k
    int lastline = 0;
659
2.58k
    unsigned maxlen, n;
660
2.58k
    byte *p;
661
2.58k
    byte tempbuf[PARTIAL_CHUNK];
662
2.58k
    size_t tempbuf_len=0;
663
2.58k
    int this_truncated;
664
665
356k
    while( !rc && size-len>=(PARTIAL_CHUNK+1)) {
666
  /* copy what we have in the line buffer */
667
353k
  if( afx->faked == 1 )
668
2.57k
      afx->faked++; /* skip the first (empty) line */
669
351k
  else
670
351k
    {
671
      /* It's full, so write this partial chunk */
672
351k
      if(tempbuf_len==PARTIAL_CHUNK)
673
3.64k
        {
674
3.64k
    buf[len++]=0xE0+PARTIAL_POW;
675
3.64k
    memcpy(&buf[len],tempbuf,PARTIAL_CHUNK);
676
3.64k
    len+=PARTIAL_CHUNK;
677
3.64k
    tempbuf_len=0;
678
3.64k
    continue;
679
3.64k
        }
680
681
2.32M
      while( tempbuf_len < PARTIAL_CHUNK
682
2.32M
       && afx->buffer_pos < afx->buffer_len )
683
1.97M
        tempbuf[tempbuf_len++] = afx->buffer[afx->buffer_pos++];
684
347k
      if( tempbuf_len==PARTIAL_CHUNK )
685
3.64k
        continue;
686
347k
    }
687
688
  /* read the next line */
689
346k
  maxlen = MAX_LINELEN;
690
346k
  afx->buffer_pos = 0;
691
346k
  afx->buffer_len = iobuf_read_line( a, &afx->buffer,
692
346k
             &afx->buffer_size, &maxlen );
693
346k
  if( !afx->buffer_len ) {
694
558
      rc = -1; /* eof (should not happen) */
695
558
      continue;
696
558
  }
697
345k
  if( !maxlen )
698
9
          {
699
9
      afx->truncated++;
700
9
            this_truncated = 1;
701
9
          }
702
345k
        else
703
345k
          this_truncated = 0;
704
705
706
345k
  p = afx->buffer;
707
345k
  n = afx->buffer_len;
708
709
  /* Armor header or dash-escaped line? */
710
345k
  if(p[0]=='-')
711
9.32k
    {
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
9.32k
      if(p[1]==' ' && !afx->not_dash_escaped)
719
308
        {
720
    /* It's a dash-escaped line, so skip over the
721
       escape. */
722
308
    afx->buffer_pos = 2;
723
308
        }
724
9.01k
      else if(p[1]=='-' && p[2]=='-' && p[3]=='-' && p[4]=='-')
725
2.01k
        {
726
    /* Five dashes in a row mean it's probably armor
727
       header. */
728
2.01k
    int type = is_armor_header( p, n );
729
2.01k
                if (type == 42)
730
276
                  type = -1;  /* Only OpenPGP armors are expected.  */
731
2.01k
    if( afx->not_dash_escaped && type != BEGIN_SIGNATURE )
732
0
      ; /* this is okay */
733
2.01k
    else
734
2.01k
      {
735
2.01k
        if( type != BEGIN_SIGNATURE )
736
1.98k
          {
737
1.98k
      log_info(_("unexpected armor: "));
738
1.98k
      es_write_sanitized (log_get_stream (), p, n,
739
1.98k
                                            NULL, NULL);
740
1.98k
      log_printf ("\n");
741
1.98k
          }
742
743
2.01k
        lastline = 1;
744
2.01k
        rc = -1;
745
2.01k
      }
746
2.01k
        }
747
7.00k
      else if(!afx->not_dash_escaped)
748
7.00k
        {
749
    /* Bad dash-escaping. */
750
7.00k
    log_info (_("invalid dash escaped line: "));
751
7.00k
    es_write_sanitized (log_get_stream (), p, n, NULL, NULL);
752
7.00k
    log_printf ("\n");
753
7.00k
        }
754
9.32k
    }
755
756
  /* Now handle the end-of-line canonicalization */
757
345k
  if( !afx->not_dash_escaped || this_truncated)
758
345k
    {
759
345k
      int crlf = n > 1 && p[n-2] == '\r' && p[n-1]=='\n';
760
761
345k
      afx->buffer_len=
762
345k
        trim_trailing_chars( &p[afx->buffer_pos], n-afx->buffer_pos,
763
345k
           " \t\r\n");
764
345k
      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
345k
      if( crlf )
783
36.1k
        afx->buffer[afx->buffer_len++] = '\r';
784
345k
      afx->buffer[afx->buffer_len++] = this_truncated? '\f':'\n';
785
345k
      afx->buffer[afx->buffer_len] = '\0';
786
345k
    }
787
345k
    }
788
789
2.58k
    if( lastline ) { /* write last (ending) length header */
790
2.01k
        if(tempbuf_len<192)
791
1.84k
    buf[len++]=tempbuf_len;
792
164
  else
793
164
    {
794
164
      buf[len++]=((tempbuf_len-192)/256) + 192;
795
164
      buf[len++]=(tempbuf_len-192) % 256;
796
164
    }
797
2.01k
  memcpy(&buf[len],tempbuf,tempbuf_len);
798
2.01k
  len+=tempbuf_len;
799
800
2.01k
  rc = 0;
801
2.01k
  afx->faked = 0;
802
2.01k
  afx->in_cleartext = 0;
803
  /* and now read the header lines */
804
2.01k
  afx->buffer_pos = 0;
805
2.11k
  for(;;) {
806
2.11k
      int i;
807
808
      /* read the next line (skip all truncated lines) */
809
2.12k
      do {
810
2.12k
    maxlen = MAX_LINELEN;
811
2.12k
    afx->buffer_len = iobuf_read_line( a, &afx->buffer,
812
2.12k
             &afx->buffer_size, &maxlen );
813
2.12k
      } while( !maxlen );
814
2.11k
      p = afx->buffer;
815
2.11k
      n = afx->buffer_len;
816
2.11k
      if( !n ) {
817
198
    rc = -1;
818
198
    break; /* eof */
819
198
      }
820
1.92k
      i = parse_header_line( afx, p , n );
821
1.92k
      if( i <= 0 ) {
822
1.81k
    if( i )
823
0
        invalid_armor();
824
1.81k
    break;
825
1.81k
      }
826
1.92k
  }
827
2.01k
  afx->inp_checked = 1;
828
2.01k
  gcry_md_reset (afx->crc_md);
829
2.01k
  afx->idx = 0;
830
2.01k
  afx->radbuf[0] = 0;
831
2.01k
    }
832
833
2.58k
    *retn = len;
834
2.58k
    return rc;
835
2.58k
}
836
837
838
static int
839
invalid_crc(void)
840
216
{
841
216
  if ( opt.ignore_crc_error )
842
0
    return 0;
843
216
  log_inc_errorcount();
844
216
  return gpg_error (GPG_ERR_INV_ARMOR);
845
216
}
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.48k
{
852
9.48k
    byte val;
853
9.48k
    int c;
854
9.48k
    u32 binc;
855
9.48k
    int checkcrc=0;
856
9.48k
    int rc = 0;
857
9.48k
    size_t n = 0;
858
9.48k
    int idx, onlypad=0;
859
9.48k
    int skip_fast = 0;
860
861
9.48k
    idx = afx->idx;
862
9.48k
    val = afx->radbuf[0];
863
726k
    for( n=0; n < size; ) {
864
865
726k
  if( afx->buffer_pos < afx->buffer_len )
866
664k
      c = afx->buffer[afx->buffer_pos++];
867
61.7k
  else { /* read the next line */
868
61.7k
      unsigned maxlen = MAX_LINELEN;
869
61.7k
      afx->buffer_pos = 0;
870
61.7k
      afx->buffer_len = iobuf_read_line( a, &afx->buffer,
871
61.7k
                 &afx->buffer_size, &maxlen );
872
61.7k
      if( !maxlen )
873
6
    afx->truncated++;
874
61.7k
      if( !afx->buffer_len )
875
2.07k
    break; /* eof */
876
59.6k
      continue;
877
61.7k
  }
878
879
666k
      again:
880
666k
  binc = asctobin[0][c];
881
882
666k
  if( binc != 0xffffffffUL )
883
342k
    {
884
342k
      if( idx == 0 && skip_fast == 0
885
147k
    && afx->buffer_pos + (16 - 1) < afx->buffer_len
886
104k
    && n + 12 < size)
887
104k
        {
888
    /* Fast path for radix64 to binary conversion.  */
889
104k
    u32 b0,b1,b2,b3;
890
891
    /* Speculatively load 15 more input bytes.  */
892
104k
    b0 = binc << (3 * 6);
893
104k
    b0 |= asctobin[2][afx->buffer[afx->buffer_pos + 0]];
894
104k
    b0 |= asctobin[1][afx->buffer[afx->buffer_pos + 1]];
895
104k
    b0 |= asctobin[0][afx->buffer[afx->buffer_pos + 2]];
896
104k
    b1  = asctobin[3][afx->buffer[afx->buffer_pos + 3]];
897
104k
    b1 |= asctobin[2][afx->buffer[afx->buffer_pos + 4]];
898
104k
    b1 |= asctobin[1][afx->buffer[afx->buffer_pos + 5]];
899
104k
    b1 |= asctobin[0][afx->buffer[afx->buffer_pos + 6]];
900
104k
    b2  = asctobin[3][afx->buffer[afx->buffer_pos + 7]];
901
104k
    b2 |= asctobin[2][afx->buffer[afx->buffer_pos + 8]];
902
104k
    b2 |= asctobin[1][afx->buffer[afx->buffer_pos + 9]];
903
104k
    b2 |= asctobin[0][afx->buffer[afx->buffer_pos + 10]];
904
104k
    b3  = asctobin[3][afx->buffer[afx->buffer_pos + 11]];
905
104k
    b3 |= asctobin[2][afx->buffer[afx->buffer_pos + 12]];
906
104k
    b3 |= asctobin[1][afx->buffer[afx->buffer_pos + 13]];
907
104k
    b3 |= asctobin[0][afx->buffer[afx->buffer_pos + 14]];
908
909
    /* Check if any of the input bytes were invalid. */
910
104k
    if( (b0 | b1 | b2 | b3) != 0xffffffffUL )
911
76.4k
      {
912
        /* All 16 bytes are valid. */
913
76.4k
        buf[n + 0] = b0 >> (2 * 8);
914
76.4k
        buf[n + 1] = b0 >> (1 * 8);
915
76.4k
        buf[n + 2] = b0 >> (0 * 8);
916
76.4k
        buf[n + 3] = b1 >> (2 * 8);
917
76.4k
        buf[n + 4] = b1 >> (1 * 8);
918
76.4k
        buf[n + 5] = b1 >> (0 * 8);
919
76.4k
        buf[n + 6] = b2 >> (2 * 8);
920
76.4k
        buf[n + 7] = b2 >> (1 * 8);
921
76.4k
        buf[n + 8] = b2 >> (0 * 8);
922
76.4k
        buf[n + 9] = b3 >> (2 * 8);
923
76.4k
        buf[n + 10] = b3 >> (1 * 8);
924
76.4k
        buf[n + 11] = b3 >> (0 * 8);
925
76.4k
        afx->buffer_pos += 16 - 1;
926
76.4k
        n += 12;
927
76.4k
        continue;
928
76.4k
      }
929
28.0k
    else if( b0 == 0xffffffffUL )
930
13.5k
      {
931
        /* byte[1..3] have invalid character(s).  Switch to slow
932
           path.  */
933
13.5k
        skip_fast = 1;
934
13.5k
      }
935
14.5k
    else if( b1 == 0xffffffffUL )
936
7.06k
      {
937
        /* byte[4..7] have invalid character(s), first 4 bytes are
938
           valid.  */
939
7.06k
        buf[n + 0] = b0 >> (2 * 8);
940
7.06k
        buf[n + 1] = b0 >> (1 * 8);
941
7.06k
        buf[n + 2] = b0 >> (0 * 8);
942
7.06k
        afx->buffer_pos += 4 - 1;
943
7.06k
        n += 3;
944
7.06k
        skip_fast = 1;
945
7.06k
        continue;
946
7.06k
      }
947
7.47k
    else if( b2 == 0xffffffffUL )
948
4.22k
      {
949
        /* byte[8..11] have invalid character(s), first 8 bytes are
950
           valid.  */
951
4.22k
        buf[n + 0] = b0 >> (2 * 8);
952
4.22k
        buf[n + 1] = b0 >> (1 * 8);
953
4.22k
        buf[n + 2] = b0 >> (0 * 8);
954
4.22k
        buf[n + 3] = b1 >> (2 * 8);
955
4.22k
        buf[n + 4] = b1 >> (1 * 8);
956
4.22k
        buf[n + 5] = b1 >> (0 * 8);
957
4.22k
        afx->buffer_pos += 8 - 1;
958
4.22k
        n += 6;
959
4.22k
        skip_fast = 1;
960
4.22k
        continue;
961
4.22k
      }
962
3.25k
    else /*if( b3 == 0xffffffffUL )*/
963
3.25k
      {
964
        /* byte[12..15] have invalid character(s), first 12 bytes
965
           are valid.  */
966
3.25k
        buf[n + 0] = b0 >> (2 * 8);
967
3.25k
        buf[n + 1] = b0 >> (1 * 8);
968
3.25k
        buf[n + 2] = b0 >> (0 * 8);
969
3.25k
        buf[n + 3] = b1 >> (2 * 8);
970
3.25k
        buf[n + 4] = b1 >> (1 * 8);
971
3.25k
        buf[n + 5] = b1 >> (0 * 8);
972
3.25k
        buf[n + 6] = b2 >> (2 * 8);
973
3.25k
        buf[n + 7] = b2 >> (1 * 8);
974
3.25k
        buf[n + 8] = b2 >> (0 * 8);
975
3.25k
        afx->buffer_pos += 12 - 1;
976
3.25k
        n += 9;
977
3.25k
        skip_fast = 1;
978
3.25k
        continue;
979
3.25k
      }
980
104k
        }
981
982
251k
      switch(idx)
983
251k
        {
984
65.7k
    case 0: val =  binc << 2; break;
985
63.5k
    case 1: val |= (binc>>4)&3; buf[n++]=val;val=(binc<<4)&0xf0;break;
986
61.9k
    case 2: val |= (binc>>2)&15; buf[n++]=val;val=(binc<<6)&0xc0;break;
987
60.1k
    case 3: val |= binc&0x3f; buf[n++] = val; break;
988
251k
        }
989
251k
      idx = (idx+1) % 4;
990
991
251k
      continue;
992
251k
    }
993
994
324k
  skip_fast = 0;
995
996
324k
  if( c == '\n' || c == ' ' || c == '\r' || c == '\t' )
997
73.8k
      continue;
998
250k
  else if( c == '=' ) { /* pad character: stop */
999
      /* some mailers leave quoted-printable encoded characters
1000
       * so we try to workaround this */
1001
10.0k
      if( afx->buffer_pos+2 < afx->buffer_len ) {
1002
5.31k
    int cc1, cc2, cc3;
1003
5.31k
    cc1 = afx->buffer[afx->buffer_pos];
1004
5.31k
    cc2 = afx->buffer[afx->buffer_pos+1];
1005
5.31k
    cc3 = afx->buffer[afx->buffer_pos+2];
1006
5.31k
    if( isxdigit(cc1) && isxdigit(cc2)
1007
2.80k
          && strchr( "=\n\r\t ", cc3 )) {
1008
        /* well it seems to be the case - adjust */
1009
2.70k
        c = isdigit(cc1)? (cc1 - '0'): (ascii_toupper(cc1)-'A'+10);
1010
2.70k
        c <<= 4;
1011
2.70k
        c |= isdigit(cc2)? (cc2 - '0'): (ascii_toupper(cc2)-'A'+10);
1012
2.70k
        afx->buffer_pos += 2;
1013
2.70k
        afx->qp_detected = 1;
1014
2.70k
        goto again;
1015
2.70k
    }
1016
5.31k
      }
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
7.32k
            if (afx->buffer_pos + 6 < afx->buffer_len
1024
1.06k
                && afx->buffer[afx->buffer_pos + 0] == '3'
1025
14
                && afx->buffer[afx->buffer_pos + 1] == 'D'
1026
4
                && asctobin[0][afx->buffer[afx->buffer_pos + 2]] != 0xffffffffUL
1027
2
                && asctobin[0][afx->buffer[afx->buffer_pos + 3]] != 0xffffffffUL
1028
2
                && asctobin[0][afx->buffer[afx->buffer_pos + 4]] != 0xffffffffUL
1029
2
                && asctobin[0][afx->buffer[afx->buffer_pos + 5]] != 0xffffffffUL
1030
2
                && 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
7.32k
      if (!n)
1037
3.22k
        onlypad = 1;
1038
1039
7.32k
      if( idx == 1 )
1040
1.97k
    buf[n++] = val;
1041
7.32k
      checkcrc++;
1042
7.32k
      break;
1043
10.0k
  }
1044
240k
        else if (afx->buffer_pos == 1 && c == '-'
1045
3.67k
                 && afx->buffer_len > 9
1046
2.89k
                 && !strncmp (afx->buffer, "-----END ", 9)) {
1047
            /* End in --dearmor mode.  */
1048
7
            if (n)
1049
                /* No CRC found, and the end of the armor is detected.
1050
                   Let return with the result of N-byte now, and come
1051
                   again to process the end of the armor with N=0.  */
1052
4
                afx->buffer_pos--;
1053
7
            break;
1054
7
        }
1055
240k
  else {
1056
240k
      log_error(_("invalid radix64 character %02X skipped\n"), c);
1057
240k
      continue;
1058
240k
  }
1059
324k
    }
1060
1061
9.48k
    afx->idx = idx;
1062
9.48k
    afx->radbuf[0] = val;
1063
1064
9.48k
    if( n )
1065
6.45k
      {
1066
6.45k
        gcry_md_write (afx->crc_md, buf, n);
1067
6.45k
        afx->any_data = 1;
1068
6.45k
      }
1069
1070
9.48k
    if( checkcrc ) {
1071
7.32k
  gcry_md_final (afx->crc_md);
1072
7.32k
  afx->inp_checked=0;
1073
7.32k
  afx->faked = 0;
1074
13.2k
  for(;;) { /* skip lf and pad characters */
1075
13.2k
      if( afx->buffer_pos < afx->buffer_len )
1076
11.5k
    c = afx->buffer[afx->buffer_pos++];
1077
1.69k
      else { /* read the next line */
1078
1.69k
    unsigned maxlen = MAX_LINELEN;
1079
1.69k
    afx->buffer_pos = 0;
1080
1.69k
    afx->buffer_len = iobuf_read_line( a, &afx->buffer,
1081
1.69k
               &afx->buffer_size, &maxlen );
1082
1.69k
    if( !maxlen )
1083
1
        afx->truncated++;
1084
1.69k
    if( !afx->buffer_len )
1085
82
        break; /* eof */
1086
1.61k
    continue;
1087
1.69k
      }
1088
11.5k
      if( c == '\n' || c == ' ' || c == '\r'
1089
8.42k
    || c == '\t' || c == '=' )
1090
4.33k
    continue;
1091
7.24k
      break;
1092
11.5k
  }
1093
7.32k
  if( !afx->buffer_len )
1094
7.32k
      log_error(_("premature eof (no CRC)\n"));
1095
7.24k
  else {
1096
7.24k
      u32 mycrc = 0;
1097
7.24k
      idx = 0;
1098
8.49k
      do {
1099
8.49k
    if( (binc = asctobin[0][c]) == 0xffffffffUL )
1100
6.83k
        break;
1101
1.65k
    switch(idx) {
1102
457
      case 0: val =  binc << 2; break;
1103
421
      case 1: val |= (binc>>4)&3; mycrc |= val << 16;val=(binc<<4)&0xf0;break;
1104
402
      case 2: val |= (binc>>2)&15; mycrc |= val << 8;val=(binc<<6)&0xc0;break;
1105
373
      case 3: val |= binc&0x3f; mycrc |= val; break;
1106
1.65k
    }
1107
1.65k
    for(;;) {
1108
1.65k
        if( afx->buffer_pos < afx->buffer_len )
1109
1.62k
      c = afx->buffer[afx->buffer_pos++];
1110
33
        else { /* read the next line */
1111
33
      unsigned maxlen = MAX_LINELEN;
1112
33
      afx->buffer_pos = 0;
1113
33
      afx->buffer_len = iobuf_read_line( a, &afx->buffer,
1114
33
                 &afx->buffer_size,
1115
33
                &maxlen );
1116
33
      if( !maxlen )
1117
0
          afx->truncated++;
1118
33
      if( !afx->buffer_len )
1119
33
          break; /* eof */
1120
0
      continue;
1121
33
        }
1122
1.62k
        break;
1123
1.65k
    }
1124
1.65k
    if( !afx->buffer_len )
1125
33
        break; /* eof */
1126
1.65k
      } while( ++idx < 4 );
1127
7.24k
      if( !afx->buffer_len ) {
1128
33
    log_info(_("premature eof (in CRC)\n"));
1129
33
    rc = invalid_crc();
1130
33
      }
1131
7.21k
      else if( idx == 0 ) {
1132
          /* No CRC at all is legal ("MAY") */
1133
6.78k
          rc=0;
1134
6.78k
      }
1135
424
      else if( idx != 4 ) {
1136
51
    log_info(_("malformed CRC\n"));
1137
51
    rc = invalid_crc();
1138
51
      }
1139
373
      else if( mycrc != get_afx_crc (afx) ) {
1140
132
    log_info (_("CRC error; %06lX - %06lX\n"),
1141
132
            (ulong)get_afx_crc (afx), (ulong)mycrc);
1142
132
    rc = invalid_crc();
1143
132
      }
1144
241
      else {
1145
241
    rc = 0;
1146
                /* FIXME: Here we should emit another control packet,
1147
                 * so that we know in mainproc that we are processing
1148
                 * a clearsign message */
1149
#if 0
1150
    for(rc=0;!rc;) {
1151
        rc = 0 /*check_trailer( &fhdr, c )*/;
1152
        if( !rc ) {
1153
      if( (c=iobuf_get(a)) == -1 )
1154
          rc = 2;
1155
        }
1156
    }
1157
    if( rc == -1 )
1158
        rc = 0;
1159
    else if( rc == 2 ) {
1160
        log_error(_("premature eof (in trailer)\n"));
1161
        rc = GPG_ERR_INV_ARMOR;
1162
    }
1163
    else {
1164
        log_error(_("error in trailer line\n"));
1165
        rc = GPG_ERR_INV_ARMOR;
1166
    }
1167
#endif
1168
241
      }
1169
7.24k
  }
1170
7.32k
    }
1171
1172
9.48k
    if( !n && !onlypad )
1173
1.38k
  rc = -1;
1174
1175
9.48k
    *retn = n;
1176
9.48k
    return rc;
1177
9.48k
}
1178
1179
static void
1180
armor_output_buf_as_radix64 (armor_filter_context_t *afx, IOBUF a,
1181
           byte *buf, size_t size)
1182
0
{
1183
0
  byte radbuf[sizeof (afx->radbuf)];
1184
0
  byte outbuf[64 + sizeof (afx->eol)];
1185
0
  unsigned int eollen = strlen (afx->eol);
1186
0
  u32 in, in2;
1187
0
  int idx, idx2;
1188
0
  int i;
1189
1190
0
  idx = afx->idx;
1191
0
  idx2 = afx->idx2;
1192
0
  memcpy (radbuf, afx->radbuf, sizeof (afx->radbuf));
1193
1194
0
  if (size && (idx || idx2))
1195
0
    {
1196
      /* preload eol to outbuf buffer */
1197
0
      memcpy (outbuf + 4, afx->eol, sizeof (afx->eol));
1198
1199
0
      for (; size && (idx || idx2); buf++, size--)
1200
0
  {
1201
0
    radbuf[idx++] = *buf;
1202
0
    if (idx > 2)
1203
0
      {
1204
0
        idx = 0;
1205
0
        in = (u32)radbuf[0] << (2 * 8);
1206
0
        in |= (u32)radbuf[1] << (1 * 8);
1207
0
        in |= (u32)radbuf[2] << (0 * 8);
1208
0
        outbuf[0] = bintoasc[(in >> 18) & 077];
1209
0
        outbuf[1] = bintoasc[(in >> 12) & 077];
1210
0
        outbuf[2] = bintoasc[(in >> 6) & 077];
1211
0
        outbuf[3] = bintoasc[(in >> 0) & 077];
1212
0
        if (++idx2 >= (64/4))
1213
0
    { /* pgp doesn't like 72 here */
1214
0
      idx2=0;
1215
0
      iobuf_write (a, outbuf, 4 + eollen);
1216
0
    }
1217
0
        else
1218
0
    {
1219
0
      iobuf_write (a, outbuf, 4);
1220
0
    }
1221
0
      }
1222
0
  }
1223
0
    }
1224
1225
0
  if (size >= (64/4)*3)
1226
0
    {
1227
      /* preload eol to outbuf buffer */
1228
0
      memcpy (outbuf + 64, afx->eol, sizeof(afx->eol));
1229
1230
0
      do
1231
0
  {
1232
    /* idx and idx2 == 0 */
1233
1234
0
    for (i = 0; i < (64/8); i++)
1235
0
      {
1236
0
        in = (u32)buf[0] << (2 * 8);
1237
0
        in |= (u32)buf[1] << (1 * 8);
1238
0
        in |= (u32)buf[2] << (0 * 8);
1239
0
        in2 = (u32)buf[3] << (2 * 8);
1240
0
        in2 |= (u32)buf[4] << (1 * 8);
1241
0
        in2 |= (u32)buf[5] << (0 * 8);
1242
0
        outbuf[i*8+0] = bintoasc[(in >> 18) & 077];
1243
0
        outbuf[i*8+1] = bintoasc[(in >> 12) & 077];
1244
0
        outbuf[i*8+2] = bintoasc[(in >> 6) & 077];
1245
0
        outbuf[i*8+3] = bintoasc[(in >> 0) & 077];
1246
0
        outbuf[i*8+4] = bintoasc[(in2 >> 18) & 077];
1247
0
        outbuf[i*8+5] = bintoasc[(in2 >> 12) & 077];
1248
0
        outbuf[i*8+6] = bintoasc[(in2 >> 6) & 077];
1249
0
        outbuf[i*8+7] = bintoasc[(in2 >> 0) & 077];
1250
0
        buf+=6;
1251
0
        size-=6;
1252
0
      }
1253
1254
    /* pgp doesn't like 72 here */
1255
0
    iobuf_write (a, outbuf, 64 + eollen);
1256
0
  }
1257
0
      while (size >= (64/4)*3);
1258
1259
      /* restore eol for tail handling */
1260
0
      if (size)
1261
0
  memcpy (outbuf + 4, afx->eol, sizeof (afx->eol));
1262
0
    }
1263
1264
0
  for (; size; buf++, size--)
1265
0
    {
1266
0
      radbuf[idx++] = *buf;
1267
0
      if (idx > 2)
1268
0
  {
1269
0
    idx = 0;
1270
0
    in = (u32)radbuf[0] << (2 * 8);
1271
0
    in |= (u32)radbuf[1] << (1 * 8);
1272
0
    in |= (u32)radbuf[2] << (0 * 8);
1273
0
    outbuf[0] = bintoasc[(in >> 18) & 077];
1274
0
    outbuf[1] = bintoasc[(in >> 12) & 077];
1275
0
    outbuf[2] = bintoasc[(in >> 6) & 077];
1276
0
    outbuf[3] = bintoasc[(in >> 0) & 077];
1277
0
    if (++idx2 >= (64/4))
1278
0
      { /* pgp doesn't like 72 here */
1279
0
        idx2=0;
1280
0
        iobuf_write (a, outbuf, 4 + eollen);
1281
0
      }
1282
0
    else
1283
0
      {
1284
0
        iobuf_write (a, outbuf, 4);
1285
0
      }
1286
0
  }
1287
0
    }
1288
1289
0
  memcpy (afx->radbuf, radbuf, sizeof (afx->radbuf));
1290
0
  afx->idx = idx;
1291
0
  afx->idx2 = idx2;
1292
0
}
1293
1294
/****************
1295
 * This filter is used to handle the armor stuff
1296
 */
1297
static int
1298
armor_filter( void *opaque, int control,
1299
       IOBUF a, byte *buf, size_t *ret_len)
1300
22.7k
{
1301
22.7k
    size_t size = *ret_len;
1302
22.7k
    armor_filter_context_t *afx = opaque;
1303
22.7k
    int rc=0, c;
1304
22.7k
    byte radbuf[3];
1305
22.7k
    int  idx, idx2;
1306
22.7k
    size_t n=0;
1307
22.7k
    u32 crc;
1308
#if 0
1309
    static FILE *fp ;
1310
1311
    if( !fp ) {
1312
  fp = fopen("armor.out", "w");
1313
  log_assert(fp);
1314
    }
1315
#endif
1316
1317
22.7k
    if( DBG_FILTER )
1318
22.7k
  log_debug("armor-filter: control: %d\n", control );
1319
22.7k
    if( control == IOBUFCTRL_UNDERFLOW && afx->inp_bypass ) {
1320
652
  n = 0;
1321
652
  if( afx->buffer_len ) {
1322
            /* Copy the data from AFX->BUFFER to BUF.  */
1323
217k
            for(; n < size && afx->buffer_pos < afx->buffer_len;)
1324
217k
                buf[n++] = afx->buffer[afx->buffer_pos++];
1325
251
      if( afx->buffer_pos >= afx->buffer_len )
1326
74
    afx->buffer_len = 0;
1327
251
  }
1328
        /* If there is still space in BUF, read directly into it.  */
1329
158k
  for(; n < size; n++ ) {
1330
158k
      if( (c=iobuf_get(a)) == -1 )
1331
380
    break;
1332
157k
      buf[n] = c & 0xff;
1333
157k
  }
1334
652
  if( !n )
1335
            /* We didn't get any data.  EOF.  */
1336
210
      rc = -1;
1337
652
  *ret_len = n;
1338
652
    }
1339
22.1k
    else if( control == IOBUFCTRL_UNDERFLOW ) {
1340
        /* We need some space for the faked packet.  The minimum
1341
         * required size is the PARTIAL_CHUNK size plus a byte for the
1342
         * length itself */
1343
15.0k
  if( size < PARTIAL_CHUNK+1 )
1344
0
      BUG(); /* supplied buffer too short */
1345
1346
15.0k
  if( afx->faked )
1347
2.58k
      rc = fake_packet( afx, a, &n, buf, size );
1348
12.4k
  else if( !afx->inp_checked ) {
1349
10.3k
      rc = check_input( afx, a );
1350
10.3k
      if( afx->inp_bypass ) {
1351
592k
    for(n=0; n < size && afx->buffer_pos < afx->buffer_len; )
1352
592k
        buf[n++] = afx->buffer[afx->buffer_pos++];
1353
298
    if( afx->buffer_pos >= afx->buffer_len )
1354
217
        afx->buffer_len = 0;
1355
298
    if( !n )
1356
40
        rc = -1;
1357
298
      }
1358
10.0k
      else if( afx->faked ) {
1359
2.57k
          unsigned int hashes = afx->hashes;
1360
2.57k
                const byte *sesmark;
1361
2.57k
                size_t sesmarklen;
1362
1363
2.57k
                sesmark = get_session_marker( &sesmarklen );
1364
2.57k
                if ( sesmarklen > 20 )
1365
0
                    BUG();
1366
1367
    /* the buffer is at least 15+n*15 bytes long, so it
1368
     * is easy to construct the packets */
1369
1370
2.57k
    hashes &= 1|2|8|16|32|64;
1371
2.57k
    if( !hashes ) {
1372
2.38k
        hashes |= 2;  /* Default to SHA-1. */
1373
2.38k
    }
1374
2.57k
    n=0;
1375
                /* First a gpg control packet... */
1376
2.57k
                buf[n++] = 0xff; /* new format, type 63, 1 length byte */
1377
2.57k
                n++;   /* see below */
1378
2.57k
                memcpy(buf+n, sesmark, sesmarklen ); n+= sesmarklen;
1379
2.57k
                buf[n++] = CTRLPKT_CLEARSIGN_START;
1380
2.57k
                buf[n++] = afx->not_dash_escaped? 0:1; /* sigclass */
1381
2.57k
                if( hashes & 1 )
1382
36
                    buf[n++] = DIGEST_ALGO_RMD160;
1383
2.57k
                if( hashes & 2 )
1384
2.46k
                    buf[n++] = DIGEST_ALGO_SHA1;
1385
2.57k
                if( hashes & 8 )
1386
42
                    buf[n++] = DIGEST_ALGO_SHA224;
1387
2.57k
                if( hashes & 16 )
1388
84
                    buf[n++] = DIGEST_ALGO_SHA256;
1389
2.57k
                if( hashes & 32 )
1390
18
                    buf[n++] = DIGEST_ALGO_SHA384;
1391
2.57k
                if( hashes & 64 )
1392
20
                    buf[n++] = DIGEST_ALGO_SHA512;
1393
2.57k
                buf[1] = n - 2;
1394
1395
    /* ...followed by an invented plaintext packet.
1396
       Amusingly enough, this packet is not compliant with
1397
       2440 as the initial partial length is less than 512
1398
       bytes.  Of course, we'll accept it anyway ;) */
1399
1400
2.57k
    buf[n++] = 0xCB; /* new packet format, type 11 */
1401
2.57k
    buf[n++] = 0xE1; /* 2^1 == 2 bytes */
1402
2.57k
    buf[n++] = 't';  /* canonical text mode */
1403
2.57k
    buf[n++] = 0;  /* namelength */
1404
2.57k
    buf[n++] = 0xE2; /* 2^2 == 4 more bytes */
1405
2.57k
    memset(buf+n, 0, 4); /* timestamp */
1406
2.57k
    n += 4;
1407
2.57k
      }
1408
7.44k
      else if( !rc )
1409
7.31k
    rc = radix64_read( afx, a, &n, buf, size );
1410
10.3k
  }
1411
2.16k
  else
1412
2.16k
      rc = radix64_read( afx, a, &n, buf, size );
1413
#if 0
1414
  if( n )
1415
      if( fwrite(buf, n, 1, fp ) != 1 )
1416
    BUG();
1417
#endif
1418
15.0k
  *ret_len = n;
1419
15.0k
    }
1420
7.04k
    else if( control == IOBUFCTRL_FLUSH && !afx->cancel ) {
1421
0
  if( !afx->status ) { /* write the header line */
1422
0
      const char *s;
1423
0
      strlist_t comment=opt.comments;
1424
1425
0
      if( afx->what >= DIM(head_strings) )
1426
0
    log_bug("afx->what=%d", afx->what);
1427
0
      iobuf_writestr(a, "-----");
1428
0
      iobuf_writestr(a, head_strings[afx->what] );
1429
0
      iobuf_writestr(a, "-----" );
1430
0
      iobuf_writestr(a,afx->eol);
1431
0
      if (opt.emit_version)
1432
0
        {
1433
0
    iobuf_writestr (a, "Version: "GNUPG_NAME" v");
1434
0
                for (s=VERSION; *s && *s != '.'; s++)
1435
0
                  iobuf_writebyte (a, *s);
1436
0
                if (opt.emit_version > 1 && *s)
1437
0
                  {
1438
0
                    iobuf_writebyte (a, *s++);
1439
0
                    for (; *s && *s != '.'; s++)
1440
0
                      iobuf_writebyte (a, *s);
1441
0
                    if (opt.emit_version > 2)
1442
0
                      {
1443
0
                        for (; *s && *s != '-' && !spacep (s); s++)
1444
0
                          iobuf_writebyte (a, *s);
1445
0
                        if (opt.emit_version > 3)
1446
0
                          iobuf_writestr (a, " (" PRINTABLE_OS_NAME ")");
1447
0
                      }
1448
0
                  }
1449
0
    iobuf_writestr(a,afx->eol);
1450
0
        }
1451
1452
      /* write the comment strings */
1453
0
      for(;comment;comment=comment->next)
1454
0
        {
1455
0
    iobuf_writestr(a, "Comment: " );
1456
0
    for( s=comment->d; *s; s++ )
1457
0
      {
1458
0
        if( *s == '\n' )
1459
0
          iobuf_writestr(a, "\\n" );
1460
0
        else if( *s == '\r' )
1461
0
          iobuf_writestr(a, "\\r" );
1462
0
        else if( *s == '\v' )
1463
0
          iobuf_writestr(a, "\\v" );
1464
0
        else
1465
0
          iobuf_put(a, *s );
1466
0
      }
1467
1468
0
    iobuf_writestr(a,afx->eol);
1469
0
        }
1470
1471
0
      if ( afx->hdrlines ) {
1472
0
                for ( s = afx->hdrlines; *s; s++ ) {
1473
#ifdef HAVE_DOSISH_SYSTEM
1474
                    if ( *s == '\n' )
1475
                        iobuf_put( a, '\r');
1476
#endif
1477
0
                    iobuf_put(a, *s );
1478
0
                }
1479
0
            }
1480
1481
0
      iobuf_writestr(a,afx->eol);
1482
0
      afx->status++;
1483
0
      afx->idx = 0;
1484
0
      afx->idx2 = 0;
1485
0
      gcry_md_reset (afx->crc_md);
1486
0
  }
1487
1488
0
  if( size ) {
1489
0
      gcry_md_write (afx->crc_md, buf, size);
1490
0
      armor_output_buf_as_radix64 (afx, a, buf, size);
1491
0
        }
1492
0
    }
1493
7.04k
    else if( control == IOBUFCTRL_INIT )
1494
3.52k
      {
1495
3.52k
  if( !is_initialized )
1496
1
    initialize();
1497
1498
  /* Figure out what we're using for line endings if the caller
1499
     didn't specify. */
1500
3.52k
  if(afx->eol[0]==0)
1501
3.52k
    {
1502
#ifdef HAVE_DOSISH_SYSTEM
1503
      afx->eol[0]='\r';
1504
      afx->eol[1]='\n';
1505
#else
1506
3.52k
      afx->eol[0]='\n';
1507
3.52k
#endif
1508
3.52k
    }
1509
3.52k
      }
1510
3.52k
    else if( control == IOBUFCTRL_CANCEL ) {
1511
0
  afx->cancel = 1;
1512
0
    }
1513
3.52k
    else if( control == IOBUFCTRL_FREE ) {
1514
3.52k
  if( afx->cancel )
1515
0
      ;
1516
3.52k
  else if( afx->status ) { /* pad, write checksum, and bottom line */
1517
0
      gcry_md_final (afx->crc_md);
1518
0
      crc = get_afx_crc (afx);
1519
0
      idx = afx->idx;
1520
0
      idx2 = afx->idx2;
1521
0
      if( idx ) {
1522
0
    c = bintoasc[(afx->radbuf[0]>>2)&077];
1523
0
    iobuf_put(a, c);
1524
0
    if( idx == 1 ) {
1525
0
        c = bintoasc[((afx->radbuf[0] << 4) & 060) & 077];
1526
0
        iobuf_put(a, c);
1527
0
        iobuf_put(a, '=');
1528
0
        iobuf_put(a, '=');
1529
0
    }
1530
0
    else { /* 2 */
1531
0
        c = bintoasc[(((afx->radbuf[0]<<4)&060)
1532
0
                                  |((afx->radbuf[1]>>4)&017))&077];
1533
0
        iobuf_put(a, c);
1534
0
        c = bintoasc[((afx->radbuf[1] << 2) & 074) & 077];
1535
0
        iobuf_put(a, c);
1536
0
        iobuf_put(a, '=');
1537
0
    }
1538
0
    if( ++idx2 >= (64/4) )
1539
0
      { /* pgp doesn't like 72 here */
1540
0
        iobuf_writestr(a,afx->eol);
1541
0
        idx2=0;
1542
0
      }
1543
0
      }
1544
      /* may need a linefeed */
1545
0
      if( idx2 )
1546
0
        iobuf_writestr(a,afx->eol);
1547
      /* write the CRC */
1548
0
      iobuf_put(a, '=');
1549
0
      radbuf[0] = crc >>16;
1550
0
      radbuf[1] = crc >> 8;
1551
0
      radbuf[2] = crc;
1552
0
      c = bintoasc[(*radbuf >> 2) & 077];
1553
0
      iobuf_put(a, c);
1554
0
      c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
1555
0
      iobuf_put(a, c);
1556
0
      c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
1557
0
      iobuf_put(a, c);
1558
0
      c = bintoasc[radbuf[2]&077];
1559
0
      iobuf_put(a, c);
1560
0
      iobuf_writestr(a,afx->eol);
1561
      /* and the trailer */
1562
0
      if( afx->what >= DIM(tail_strings) )
1563
0
    log_bug("afx->what=%d", afx->what);
1564
0
      iobuf_writestr(a, "-----");
1565
0
      iobuf_writestr(a, tail_strings[afx->what] );
1566
0
      iobuf_writestr(a, "-----" );
1567
0
      iobuf_writestr(a,afx->eol);
1568
0
  }
1569
3.52k
  else if( !afx->any_data && !afx->inp_bypass ) {
1570
1.56k
      log_error(_("no valid OpenPGP data found.\n"));
1571
1.56k
      afx->no_openpgp_data = 1;
1572
1.56k
      write_status_text( STATUS_NODATA, "1" );
1573
1.56k
  }
1574
        /* Note that in a cleartext signature truncated lines in the
1575
         * plaintext are detected and propagated to the signature
1576
         * checking code by inserting a \f into the plaintext.  We do
1577
         * not use log_info here because some of the truncated lines
1578
         * are harmless.  */
1579
3.52k
  if( afx->truncated )
1580
3.52k
      log_info(_("invalid armor: line longer than %d characters\n"),
1581
14
          MAX_LINELEN );
1582
  /* issue an error to enforce dissemination of correct software */
1583
3.52k
  if( afx->qp_detected )
1584
3.52k
      log_error(_("quoted printable character in armor - "
1585
84
      "probably a buggy MTA has been used\n") );
1586
3.52k
  xfree( afx->buffer );
1587
3.52k
  afx->buffer = NULL;
1588
3.52k
        release_armor_context (afx);
1589
3.52k
    }
1590
0
    else if( control == IOBUFCTRL_DESC )
1591
0
        mem2str (buf, "armor_filter", *ret_len);
1592
22.7k
    return rc;
1593
22.7k
}
1594
1595
1596
/****************
1597
 * create a radix64 encoded string.
1598
 */
1599
char *
1600
make_radix64_string( const byte *data, size_t len )
1601
0
{
1602
0
    char *buffer, *p;
1603
1604
0
    buffer = p = xmalloc( (len+2)/3*4 + 1 );
1605
0
    for( ; len >= 3 ; len -= 3, data += 3 ) {
1606
0
  *p++ = bintoasc[(data[0] >> 2) & 077];
1607
0
  *p++ = bintoasc[(((data[0] <<4)&060)|((data[1] >> 4)&017))&077];
1608
0
  *p++ = bintoasc[(((data[1]<<2)&074)|((data[2]>>6)&03))&077];
1609
0
  *p++ = bintoasc[data[2]&077];
1610
0
    }
1611
0
    if( len == 2 ) {
1612
0
  *p++ = bintoasc[(data[0] >> 2) & 077];
1613
0
  *p++ = bintoasc[(((data[0] <<4)&060)|((data[1] >> 4)&017))&077];
1614
0
  *p++ = bintoasc[((data[1]<<2)&074)];
1615
0
    }
1616
0
    else if( len == 1 ) {
1617
0
  *p++ = bintoasc[(data[0] >> 2) & 077];
1618
0
  *p++ = bintoasc[(data[0] <<4)&060];
1619
0
    }
1620
0
    *p = 0;
1621
0
    return buffer;
1622
0
}