Coverage Report

Created: 2025-12-14 07:02

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
51.2k
#define MAX_LINELEN 20000
39
40
static const byte bintoasc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
41
                               "abcdefghijklmnopqrstuvwxyz"
42
                               "0123456789+/";
43
static u32 asctobin[4][256]; /* runtime initialized */
44
static int is_initialized;
45
46
47
typedef enum {
48
    fhdrHASArmor = 0,
49
    fhdrNOArmor,
50
    fhdrINIT,
51
    fhdrINITCont,
52
    fhdrINITSkip,
53
    fhdrCHECKBegin,
54
    fhdrWAITHeader,
55
    fhdrWAITClearsig,
56
    fhdrSKIPHeader,
57
    fhdrCLEARSIG,
58
    fhdrREADClearsig,
59
    fhdrNullClearsig,
60
    fhdrEMPTYClearsig,
61
    fhdrCHECKClearsig,
62
    fhdrCHECKClearsig2,
63
    fhdrCHECKDashEscaped,
64
    fhdrCHECKDashEscaped2,
65
    fhdrCHECKDashEscaped3,
66
    fhdrREADClearsigNext,
67
    fhdrENDClearsig,
68
    fhdrENDClearsigHelp,
69
    fhdrTESTSpaces,
70
    fhdrCLEARSIGSimple,
71
    fhdrCLEARSIGSimpleNext,
72
    fhdrTEXT,
73
    fhdrTEXTSimple,
74
    fhdrERROR,
75
    fhdrERRORShow,
76
    fhdrEOF
77
} fhdr_state_t;
78
79
80
/* if we encounter this armor string with this index, go
81
 * into a mode which fakes packets and wait for the next armor */
82
0
#define BEGIN_SIGNATURE 2
83
7.30k
#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
4.89k
{
116
4.89k
  armor_filter_context_t *afx;
117
4.89k
  gpg_error_t err;
118
119
4.89k
  afx = xcalloc (1, sizeof *afx);
120
4.89k
  if (afx)
121
4.89k
    {
122
4.89k
      err = gcry_md_open (&afx->crc_md, GCRY_MD_CRC24_RFC2440, 0);
123
4.89k
      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
4.89k
      afx->refcount = 1;
132
4.89k
    }
133
134
4.89k
  return afx;
135
4.89k
}
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
9.78k
{
142
9.78k
  if (!afx)
143
0
    return;
144
9.78k
  log_assert (afx->refcount);
145
9.78k
  if ( --afx->refcount )
146
4.89k
    return;
147
4.89k
  gcry_md_close (afx->crc_md);
148
4.89k
  xfree (afx);
149
4.89k
}
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
4.89k
{
155
4.89k
  int rc;
156
157
4.89k
  afx->refcount++;
158
4.89k
  rc = iobuf_push_filter (iobuf, armor_filter, afx);
159
4.89k
  if (rc)
160
0
    afx->refcount--;
161
4.89k
  return rc;
162
4.89k
}
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
363
{
200
363
  const byte *crc_buf;
201
363
  u32 crc;
202
203
363
  crc_buf = gcry_md_read (afx->crc_md, GCRY_MD_CRC24_RFC2440);
204
205
363
  crc = crc_buf[0];
206
363
  crc <<= 8;
207
363
  crc |= crc_buf[1];
208
363
  crc <<= 8;
209
363
  crc |= crc_buf[2];
210
211
363
  return crc;
212
363
}
213
214
215
/*
216
 * Check whether this is an armored file.  See also
217
 * parse-packet.c for details on this code.
218
 *
219
 * Note that the buffer BUF needs to be at least 2 bytes long.  If in
220
 * doubt that the second byte to 0.
221
 *
222
 * Returns: True if it seems to be armored
223
 */
224
static int
225
is_armored (const byte *buf)
226
11.1k
{
227
11.1k
  int ctb, pkttype;
228
11.1k
  int indeterminate_length_allowed;
229
230
11.1k
    ctb = *buf;
231
11.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
6.98k
      return 1;
236
237
4.12k
    pkttype =  ctb & 0x40 ? (ctb & 0x3f) : ((ctb>>2)&0xf);
238
4.12k
    switch( pkttype ) {
239
76
      case PKT_PUBKEY_ENC:
240
702
      case PKT_SIGNATURE:
241
810
      case PKT_SYMKEY_ENC:
242
847
      case PKT_ONEPASS_SIG:
243
1.16k
      case PKT_SECRET_KEY:
244
2.34k
      case PKT_PUBLIC_KEY:
245
2.53k
      case PKT_SECRET_SUBKEY:
246
2.58k
      case PKT_MARKER:
247
2.74k
      case PKT_RING_TRUST:
248
2.84k
      case PKT_USER_ID:
249
2.86k
      case PKT_PUBLIC_SUBKEY:
250
3.16k
      case PKT_ATTRIBUTE:
251
3.20k
      case PKT_MDC:
252
3.20k
  indeterminate_length_allowed = 0;
253
3.20k
        break;
254
255
54
      case PKT_COMPRESSED:
256
154
      case PKT_ENCRYPTED:
257
272
      case PKT_ENCRYPTED_MDC:
258
338
      case PKT_ENCRYPTED_AEAD:
259
471
      case PKT_PLAINTEXT:
260
511
      case PKT_OLD_COMMENT:
261
552
      case PKT_COMMENT:
262
655
      case PKT_GPG_CONTROL:
263
655
  indeterminate_length_allowed = 1;
264
655
        break;
265
266
263
      default:
267
        /* Invalid packet type.  */
268
263
        return 1;
269
4.12k
    }
270
271
3.86k
    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
3.20k
      {
277
3.20k
        int new_format;
278
3.20k
        int indeterminate_length;
279
280
3.20k
        new_format = !! (ctb & (1 << 6));
281
3.20k
        if (new_format)
282
1.64k
          indeterminate_length = (buf[1] >= 224 && buf[1] < 255);
283
1.56k
        else
284
1.56k
          indeterminate_length = (ctb & 3) == 3;
285
286
3.20k
        if (indeterminate_length)
287
165
          return 1;
288
3.20k
      }
289
290
    /* The first CTB seems legit.  It is probably not armored
291
       data.  */
292
3.69k
    return 0;
293
3.86k
}
294
295
296
/****************
297
 * Try to check whether the iobuf is armored
298
 * Returns true if this may be the case; the caller should use the
299
 *     filter to do further processing.
300
 */
301
int
302
use_armor_filter( IOBUF a )
303
0
{
304
0
    byte buf[2];
305
0
    int n;
306
307
    /* fixme: there might be a problem with iobuf_peek */
308
0
    n = iobuf_peek (a, buf, 2);
309
0
    if( n == -1 )
310
0
  return 0; /* EOF, doesn't matter whether armored or not */
311
0
    if( !n )
312
0
  return 1; /* can't check it: try armored */
313
0
    if (n != 2)
314
0
  return 0; /* short buffer */
315
0
    return is_armored(buf);
316
0
}
317
318
319
320
321
static void
322
invalid_armor(void)
323
0
{
324
0
    write_status(STATUS_BADARMOR);
325
0
    g10_exit(1); /* stop here */
326
0
}
327
328
329
/****************
330
 * check whether the armor header is valid on a signed message.
331
 * this is for security reasons: the header lines are not included in the
332
 * hash and by using some creative formatting rules, Mallory could fake
333
 * any text at the beginning of a document; assuming it is read with
334
 * a simple viewer. We only allow the Hash Header.
335
 */
336
static int
337
parse_hash_header( const char *line )
338
0
{
339
0
    const char *s, *s2;
340
0
    unsigned found = 0;
341
342
0
    if( strlen(line) < 6  || strlen(line) > 60 )
343
0
  return 0; /* too short or too long */
344
0
    if( memcmp( line, "Hash:", 5 ) )
345
0
  return 0; /* invalid header */
346
347
0
    for(s=line+5;;s=s2) {
348
0
  for(; *s && (*s==' ' || *s == '\t'); s++ )
349
0
      ;
350
0
  if( !*s )
351
0
      break;
352
0
  for(s2=s+1; *s2 && *s2!=' ' && *s2 != '\t' && *s2 != ','; s2++ )
353
0
      ;
354
0
  if( !strncmp( s, "RIPEMD160", s2-s ) )
355
0
      found |= 1;
356
0
  else if( !strncmp( s, "SHA1", s2-s ) )
357
0
      found |= 2;
358
0
  else if( !strncmp( s, "SHA224", s2-s ) )
359
0
      found |= 8;
360
0
  else if( !strncmp( s, "SHA256", s2-s ) )
361
0
      found |= 16;
362
0
  else if( !strncmp( s, "SHA384", s2-s ) )
363
0
      found |= 32;
364
0
  else if( !strncmp( s, "SHA512", s2-s ) )
365
0
      found |= 64;
366
0
  else
367
0
      return 0;
368
0
  for(; *s2 && (*s2==' ' || *s2 == '\t'); s2++ )
369
0
      ;
370
0
  if( *s2 && *s2 != ',' )
371
0
      return 0;
372
0
  if( *s2 )
373
0
      s2++;
374
0
    }
375
0
    return found;
376
0
}
377
378
/* Returns true if this is a valid armor tag as per RFC-2440bis-21. */
379
static int
380
is_armor_tag(const char *line)
381
3.01k
{
382
3.01k
  if(strncmp(line,"Version",7)==0
383
2.43k
     || strncmp(line,"Comment",7)==0
384
2.27k
     || strncmp(line,"MessageID",9)==0
385
1.72k
     || strncmp(line,"Hash",4)==0
386
1.30k
     || strncmp(line,"Charset",7)==0)
387
1.78k
    return 1;
388
389
1.23k
  return 0;
390
3.01k
}
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
21.0k
{
400
21.0k
    const char *s;
401
21.0k
    byte *save_p, *p;
402
21.0k
    int save_c;
403
21.0k
    int i;
404
405
21.0k
    if( len < 15 )
406
8.69k
  return -1; /* too short */
407
12.3k
    if( memcmp( line, "-----", 5 ) )
408
2.10k
  return -1; /* no */
409
10.2k
    p = strstr( line+5, "-----");
410
10.2k
    if( !p )
411
891
  return -1;
412
9.32k
    save_p = p;
413
9.32k
    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
9.32k
    if(RFC2440)
424
0
      {
425
0
  if( *p == '\r' )
426
0
    p++;
427
0
  if( *p == '\n' )
428
0
    p++;
429
0
      }
430
9.32k
    else
431
18.4k
      while(*p==' ' || *p=='\r' || *p=='\n' || *p=='\t')
432
9.16k
  p++;
433
434
9.32k
    if( *p )
435
354
  return -1; /* garbage after dashes */
436
8.96k
    save_c = *save_p; *save_p = 0;
437
8.96k
    p = line+5;
438
31.7k
    for(i=0; (s=head_strings[i]); i++ )
439
30.3k
  if( !strcmp(s, p) )
440
7.51k
      break;
441
8.96k
    *save_p = save_c;
442
8.96k
    if (!s)
443
1.44k
      {
444
1.44k
        if (!strncmp (p, "BEGIN ", 6))
445
962
          return 42;
446
487
  return -1; /* unknown armor line */
447
1.44k
      }
448
449
7.51k
    if( opt.verbose > 1 )
450
7.51k
  log_info(_("armor: %s\n"), head_strings[i]);
451
7.51k
    return i;
452
8.96k
}
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
10.3k
{
465
10.3k
    byte *p;
466
10.3k
    int hashes=0;
467
10.3k
    unsigned int len2;
468
469
10.3k
    len2 = length_sans_trailing_ws ( line, len );
470
10.3k
    if( !len2 ) {
471
3.92k
        afx->buffer_pos = len2;  /* (it is not the fine way to do it here) */
472
3.92k
  return 0; /* WS only: same as empty line */
473
3.92k
    }
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
6.39k
    p = strchr( line, ':');
486
6.39k
    if (!p && afx->dearmor_state)
487
0
      return 0; /* Special treatment in --dearmor mode.  */
488
6.39k
    if( !p || (RFC2440 && p[1]!=' ')
489
3.13k
  || (!RFC2440 && p[1]!=' ' && p[1]!='\n' && p[1]!='\r'))
490
3.38k
      {
491
3.38k
  log_error (_("invalid armor header: "));
492
3.38k
  es_write_sanitized (log_get_stream (), line, len, NULL, NULL);
493
3.38k
  log_printf ("\n");
494
3.38k
  return -1;
495
3.38k
      }
496
497
    /* Chop off the whitespace we detected before */
498
3.01k
    len=len2;
499
3.01k
    line[len2]='\0';
500
501
3.01k
    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
3.01k
    if (afx->dearmor_mode)
508
0
      ;
509
3.01k
    else if (afx->in_cleartext)
510
0
      {
511
0
  if( (hashes=parse_hash_header( line )) )
512
0
    afx->hashes |= hashes;
513
0
  else if( strlen(line) > 15 && !memcmp( line, "NotDashEscaped:", 15 ) )
514
0
    afx->not_dash_escaped = 1;
515
0
  else
516
0
    {
517
0
      log_error(_("invalid clearsig header\n"));
518
0
      return -1;
519
0
    }
520
0
      }
521
3.01k
    else if(!is_armor_tag(line))
522
1.23k
      {
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
1.23k
  log_info(_("unknown armor header: "));
531
1.23k
  es_write_sanitized (log_get_stream (), line, len, NULL, NULL);
532
1.23k
  log_printf ("\n");
533
1.23k
      }
534
535
3.01k
    return 1;
536
3.01k
}
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
11.5k
{
544
11.5k
    int rc = 0;
545
11.5k
    int i;
546
11.5k
    byte *line;
547
11.5k
    unsigned len;
548
11.5k
    unsigned maxlen;
549
11.5k
    int hdr_line = -1;
550
551
    /* read the first line to see whether this is armored data */
552
11.5k
    maxlen = MAX_LINELEN;
553
11.5k
    len = afx->buffer_len = iobuf_read_line( a, &afx->buffer,
554
11.5k
               &afx->buffer_size, &maxlen );
555
11.5k
    line = afx->buffer;
556
11.5k
    if( !maxlen ) {
557
  /* line has been truncated: assume not armored */
558
0
  afx->inp_checked = 1;
559
0
  afx->inp_bypass = 1;
560
0
  return 0;
561
0
    }
562
563
11.5k
    if( !len ) {
564
48
  return -1; /* eof */
565
48
    }
566
567
    /* (the line is always a C string but maybe longer) */
568
11.4k
    if( *line == '\n' || ( len && (*line == '\r' && line[1]=='\n') ) )
569
352
  ;
570
11.1k
    else if (len >= 2 && !is_armored (line)) {
571
3.69k
  afx->inp_checked = 1;
572
3.69k
  afx->inp_bypass = 1;
573
3.69k
  return 0;
574
3.69k
    }
575
576
    /* find the armor header */
577
21.4k
    while(len) {
578
21.0k
  i = is_armor_header( line, len );
579
21.0k
        if ( i == 42 ) {
580
962
            if (afx->dearmor_mode) {
581
0
                afx->dearmor_state = 1;
582
0
                break;
583
0
            }
584
962
        }
585
20.0k
        else if (i >= 0
586
7.51k
                 && !(afx->only_keyblocks && i != 1 && i != 5 && i != 6 )) {
587
7.30k
      hdr_line = i;
588
7.30k
      if( hdr_line == BEGIN_SIGNED_MSG_IDX ) {
589
0
          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
0
    afx->in_cleartext = 1;
594
0
      }
595
7.30k
      break;
596
7.30k
  }
597
598
  /* read the next line (skip all truncated lines) */
599
13.7k
  do {
600
13.7k
      maxlen = MAX_LINELEN;
601
13.7k
      afx->buffer_len = iobuf_read_line( a, &afx->buffer,
602
13.7k
                 &afx->buffer_size, &maxlen );
603
13.7k
      line = afx->buffer;
604
13.7k
      len = afx->buffer_len;
605
13.7k
  } while( !maxlen );
606
13.7k
    }
607
608
    /* Parse the header lines.  */
609
10.8k
    while(len) {
610
  /* Read the next line (skip all truncated lines). */
611
10.3k
  do {
612
10.3k
      maxlen = MAX_LINELEN;
613
10.3k
      afx->buffer_len = iobuf_read_line( a, &afx->buffer,
614
10.3k
                 &afx->buffer_size, &maxlen );
615
10.3k
      line = afx->buffer;
616
10.3k
      len = afx->buffer_len;
617
10.3k
  } while( !maxlen );
618
619
10.3k
  i = parse_header_line( afx, line, len );
620
10.3k
  if( i <= 0 ) {
621
7.30k
      if (i && RFC2440)
622
0
    rc = GPG_ERR_INV_ARMOR;
623
7.30k
      break;
624
7.30k
  }
625
10.3k
    }
626
627
628
7.78k
    if( rc )
629
0
  invalid_armor();
630
7.78k
    else if( afx->in_cleartext )
631
0
  afx->faked = 1;
632
7.78k
    else {
633
7.78k
  afx->inp_checked = 1;
634
7.78k
  gcry_md_reset (afx->crc_md);
635
7.78k
  afx->idx = 0;
636
7.78k
  afx->radbuf[0] = 0;
637
7.78k
    }
638
639
7.78k
    return rc;
640
11.4k
}
641
642
11.6k
#define PARTIAL_CHUNK 512
643
0
#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
0
{
654
0
    int rc = 0;
655
0
    size_t len = 0;
656
0
    int lastline = 0;
657
0
    unsigned maxlen, n;
658
0
    byte *p;
659
0
    byte tempbuf[PARTIAL_CHUNK];
660
0
    size_t tempbuf_len=0;
661
0
    int this_truncated;
662
663
0
    while( !rc && size-len>=(PARTIAL_CHUNK+1)) {
664
  /* copy what we have in the line buffer */
665
0
  if( afx->faked == 1 )
666
0
      afx->faked++; /* skip the first (empty) line */
667
0
  else
668
0
    {
669
      /* It's full, so write this partial chunk */
670
0
      if(tempbuf_len==PARTIAL_CHUNK)
671
0
        {
672
0
    buf[len++]=0xE0+PARTIAL_POW;
673
0
    memcpy(&buf[len],tempbuf,PARTIAL_CHUNK);
674
0
    len+=PARTIAL_CHUNK;
675
0
    tempbuf_len=0;
676
0
    continue;
677
0
        }
678
679
0
      while( tempbuf_len < PARTIAL_CHUNK
680
0
       && afx->buffer_pos < afx->buffer_len )
681
0
        tempbuf[tempbuf_len++] = afx->buffer[afx->buffer_pos++];
682
0
      if( tempbuf_len==PARTIAL_CHUNK )
683
0
        continue;
684
0
    }
685
686
  /* read the next line */
687
0
  maxlen = MAX_LINELEN;
688
0
  afx->buffer_pos = 0;
689
0
  afx->buffer_len = iobuf_read_line( a, &afx->buffer,
690
0
             &afx->buffer_size, &maxlen );
691
0
  if( !afx->buffer_len ) {
692
0
      rc = -1; /* eof (should not happen) */
693
0
      continue;
694
0
  }
695
0
  if( !maxlen )
696
0
          {
697
0
      afx->truncated++;
698
0
            this_truncated = 1;
699
0
          }
700
0
        else
701
0
          this_truncated = 0;
702
703
704
0
  p = afx->buffer;
705
0
  n = afx->buffer_len;
706
707
  /* Armor header or dash-escaped line? */
708
0
  if(p[0]=='-')
709
0
    {
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
0
      if(p[1]==' ' && !afx->not_dash_escaped)
717
0
        {
718
    /* It's a dash-escaped line, so skip over the
719
       escape. */
720
0
    afx->buffer_pos = 2;
721
0
        }
722
0
      else if(p[1]=='-' && p[2]=='-' && p[3]=='-' && p[4]=='-')
723
0
        {
724
    /* Five dashes in a row mean it's probably armor
725
       header. */
726
0
    int type = is_armor_header( p, n );
727
0
                if (type == 42)
728
0
                  type = -1;  /* Only OpenPGP armors are expected.  */
729
0
    if( afx->not_dash_escaped && type != BEGIN_SIGNATURE )
730
0
      ; /* this is okay */
731
0
    else
732
0
      {
733
0
        if( type != BEGIN_SIGNATURE )
734
0
          {
735
0
      log_info(_("unexpected armor: "));
736
0
      es_write_sanitized (log_get_stream (), p, n,
737
0
                                            NULL, NULL);
738
0
      log_printf ("\n");
739
0
          }
740
741
0
        lastline = 1;
742
0
        rc = -1;
743
0
      }
744
0
        }
745
0
      else if(!afx->not_dash_escaped)
746
0
        {
747
    /* Bad dash-escaping. */
748
0
    log_info (_("invalid dash escaped line: "));
749
0
    es_write_sanitized (log_get_stream (), p, n, NULL, NULL);
750
0
    log_printf ("\n");
751
0
        }
752
0
    }
753
754
  /* Now handle the end-of-line canonicalization */
755
0
  if( !afx->not_dash_escaped || this_truncated)
756
0
    {
757
0
      int crlf = n > 1 && p[n-2] == '\r' && p[n-1]=='\n';
758
759
0
      afx->buffer_len=
760
0
        trim_trailing_chars( &p[afx->buffer_pos], n-afx->buffer_pos,
761
0
           " \t\r\n");
762
0
      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
0
      if( crlf )
781
0
        afx->buffer[afx->buffer_len++] = '\r';
782
0
      afx->buffer[afx->buffer_len++] = this_truncated? '\f':'\n';
783
0
      afx->buffer[afx->buffer_len] = '\0';
784
0
    }
785
0
    }
786
787
0
    if( lastline ) { /* write last (ending) length header */
788
0
        if(tempbuf_len<192)
789
0
    buf[len++]=tempbuf_len;
790
0
  else
791
0
    {
792
0
      buf[len++]=((tempbuf_len-192)/256) + 192;
793
0
      buf[len++]=(tempbuf_len-192) % 256;
794
0
    }
795
0
  memcpy(&buf[len],tempbuf,tempbuf_len);
796
0
  len+=tempbuf_len;
797
798
0
  rc = 0;
799
0
  afx->faked = 0;
800
0
  afx->in_cleartext = 0;
801
  /* and now read the header lines */
802
0
  afx->buffer_pos = 0;
803
0
  for(;;) {
804
0
      int i;
805
806
      /* read the next line (skip all truncated lines) */
807
0
      do {
808
0
    maxlen = MAX_LINELEN;
809
0
    afx->buffer_len = iobuf_read_line( a, &afx->buffer,
810
0
             &afx->buffer_size, &maxlen );
811
0
      } while( !maxlen );
812
0
      p = afx->buffer;
813
0
      n = afx->buffer_len;
814
0
      if( !n ) {
815
0
    rc = -1;
816
0
    break; /* eof */
817
0
      }
818
0
      i = parse_header_line( afx, p , n );
819
0
      if( i <= 0 ) {
820
0
    if( i )
821
0
        invalid_armor();
822
0
    break;
823
0
      }
824
0
  }
825
0
  afx->inp_checked = 1;
826
0
  gcry_md_reset (afx->crc_md);
827
0
  afx->idx = 0;
828
0
  afx->radbuf[0] = 0;
829
0
    }
830
831
0
    *retn = len;
832
0
    return rc;
833
0
}
834
835
836
static int
837
invalid_crc(void)
838
91
{
839
91
  if ( opt.ignore_crc_error )
840
0
    return 0;
841
91
  log_inc_errorcount();
842
91
  return gpg_error (GPG_ERR_INV_ARMOR);
843
91
}
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
7.93k
{
850
7.93k
    byte val;
851
7.93k
    int c;
852
7.93k
    u32 binc;
853
7.93k
    int checkcrc=0;
854
7.93k
    int rc = 0;
855
7.93k
    size_t n = 0;
856
7.93k
    int idx, onlypad=0;
857
7.93k
    int skip_fast = 0;
858
859
7.93k
    idx = afx->idx;
860
7.93k
    val = afx->radbuf[0];
861
218k
    for( n=0; n < size; ) {
862
863
218k
  if( afx->buffer_pos < afx->buffer_len )
864
203k
      c = afx->buffer[afx->buffer_pos++];
865
15.0k
  else { /* read the next line */
866
15.0k
      unsigned maxlen = MAX_LINELEN;
867
15.0k
      afx->buffer_pos = 0;
868
15.0k
      afx->buffer_len = iobuf_read_line( a, &afx->buffer,
869
15.0k
                 &afx->buffer_size, &maxlen );
870
15.0k
      if( !maxlen )
871
0
    afx->truncated++;
872
15.0k
      if( !afx->buffer_len )
873
1.12k
    break; /* eof */
874
13.9k
      continue;
875
15.0k
  }
876
877
203k
      again:
878
203k
  binc = asctobin[0][c];
879
880
203k
  if( binc != 0xffffffffUL )
881
93.4k
    {
882
93.4k
      if( idx == 0 && skip_fast == 0
883
44.4k
    && afx->buffer_pos + (16 - 1) < afx->buffer_len
884
33.2k
    && n + 12 < size)
885
33.2k
        {
886
    /* Fast path for radix64 to binary conversion.  */
887
33.2k
    u32 b0,b1,b2,b3;
888
889
    /* Speculatively load 15 more input bytes.  */
890
33.2k
    b0 = binc << (3 * 6);
891
33.2k
    b0 |= asctobin[2][afx->buffer[afx->buffer_pos + 0]];
892
33.2k
    b0 |= asctobin[1][afx->buffer[afx->buffer_pos + 1]];
893
33.2k
    b0 |= asctobin[0][afx->buffer[afx->buffer_pos + 2]];
894
33.2k
    b1  = asctobin[3][afx->buffer[afx->buffer_pos + 3]];
895
33.2k
    b1 |= asctobin[2][afx->buffer[afx->buffer_pos + 4]];
896
33.2k
    b1 |= asctobin[1][afx->buffer[afx->buffer_pos + 5]];
897
33.2k
    b1 |= asctobin[0][afx->buffer[afx->buffer_pos + 6]];
898
33.2k
    b2  = asctobin[3][afx->buffer[afx->buffer_pos + 7]];
899
33.2k
    b2 |= asctobin[2][afx->buffer[afx->buffer_pos + 8]];
900
33.2k
    b2 |= asctobin[1][afx->buffer[afx->buffer_pos + 9]];
901
33.2k
    b2 |= asctobin[0][afx->buffer[afx->buffer_pos + 10]];
902
33.2k
    b3  = asctobin[3][afx->buffer[afx->buffer_pos + 11]];
903
33.2k
    b3 |= asctobin[2][afx->buffer[afx->buffer_pos + 12]];
904
33.2k
    b3 |= asctobin[1][afx->buffer[afx->buffer_pos + 13]];
905
33.2k
    b3 |= asctobin[0][afx->buffer[afx->buffer_pos + 14]];
906
907
    /* Check if any of the input bytes were invalid. */
908
33.2k
    if( (b0 | b1 | b2 | b3) != 0xffffffffUL )
909
24.2k
      {
910
        /* All 16 bytes are valid. */
911
24.2k
        buf[n + 0] = b0 >> (2 * 8);
912
24.2k
        buf[n + 1] = b0 >> (1 * 8);
913
24.2k
        buf[n + 2] = b0 >> (0 * 8);
914
24.2k
        buf[n + 3] = b1 >> (2 * 8);
915
24.2k
        buf[n + 4] = b1 >> (1 * 8);
916
24.2k
        buf[n + 5] = b1 >> (0 * 8);
917
24.2k
        buf[n + 6] = b2 >> (2 * 8);
918
24.2k
        buf[n + 7] = b2 >> (1 * 8);
919
24.2k
        buf[n + 8] = b2 >> (0 * 8);
920
24.2k
        buf[n + 9] = b3 >> (2 * 8);
921
24.2k
        buf[n + 10] = b3 >> (1 * 8);
922
24.2k
        buf[n + 11] = b3 >> (0 * 8);
923
24.2k
        afx->buffer_pos += 16 - 1;
924
24.2k
        n += 12;
925
24.2k
        continue;
926
24.2k
      }
927
9.02k
    else if( b0 == 0xffffffffUL )
928
3.37k
      {
929
        /* byte[1..3] have invalid character(s).  Switch to slow
930
           path.  */
931
3.37k
        skip_fast = 1;
932
3.37k
      }
933
5.64k
    else if( b1 == 0xffffffffUL )
934
2.46k
      {
935
        /* byte[4..7] have invalid character(s), first 4 bytes are
936
           valid.  */
937
2.46k
        buf[n + 0] = b0 >> (2 * 8);
938
2.46k
        buf[n + 1] = b0 >> (1 * 8);
939
2.46k
        buf[n + 2] = b0 >> (0 * 8);
940
2.46k
        afx->buffer_pos += 4 - 1;
941
2.46k
        n += 3;
942
2.46k
        skip_fast = 1;
943
2.46k
        continue;
944
2.46k
      }
945
3.18k
    else if( b2 == 0xffffffffUL )
946
1.75k
      {
947
        /* byte[8..11] have invalid character(s), first 8 bytes are
948
           valid.  */
949
1.75k
        buf[n + 0] = b0 >> (2 * 8);
950
1.75k
        buf[n + 1] = b0 >> (1 * 8);
951
1.75k
        buf[n + 2] = b0 >> (0 * 8);
952
1.75k
        buf[n + 3] = b1 >> (2 * 8);
953
1.75k
        buf[n + 4] = b1 >> (1 * 8);
954
1.75k
        buf[n + 5] = b1 >> (0 * 8);
955
1.75k
        afx->buffer_pos += 8 - 1;
956
1.75k
        n += 6;
957
1.75k
        skip_fast = 1;
958
1.75k
        continue;
959
1.75k
      }
960
1.42k
    else /*if( b3 == 0xffffffffUL )*/
961
1.42k
      {
962
        /* byte[12..15] have invalid character(s), first 12 bytes
963
           are valid.  */
964
1.42k
        buf[n + 0] = b0 >> (2 * 8);
965
1.42k
        buf[n + 1] = b0 >> (1 * 8);
966
1.42k
        buf[n + 2] = b0 >> (0 * 8);
967
1.42k
        buf[n + 3] = b1 >> (2 * 8);
968
1.42k
        buf[n + 4] = b1 >> (1 * 8);
969
1.42k
        buf[n + 5] = b1 >> (0 * 8);
970
1.42k
        buf[n + 6] = b2 >> (2 * 8);
971
1.42k
        buf[n + 7] = b2 >> (1 * 8);
972
1.42k
        buf[n + 8] = b2 >> (0 * 8);
973
1.42k
        afx->buffer_pos += 12 - 1;
974
1.42k
        n += 9;
975
1.42k
        skip_fast = 1;
976
1.42k
        continue;
977
1.42k
      }
978
33.2k
        }
979
980
63.6k
      switch(idx)
981
63.6k
        {
982
18.5k
    case 0: val =  binc << 2; break;
983
15.8k
    case 1: val |= (binc>>4)&3; buf[n++]=val;val=(binc<<4)&0xf0;break;
984
15.0k
    case 2: val |= (binc>>2)&15; buf[n++]=val;val=(binc<<6)&0xc0;break;
985
14.1k
    case 3: val |= binc&0x3f; buf[n++] = val; break;
986
63.6k
        }
987
63.6k
      idx = (idx+1) % 4;
988
989
63.6k
      continue;
990
63.6k
    }
991
992
110k
  skip_fast = 0;
993
994
110k
  if( c == '\n' || c == ' ' || c == '\r' || c == '\t' )
995
24.2k
      continue;
996
86.1k
  else if( c == '=' ) { /* pad character: stop */
997
      /* some mailers leave quoted-printable encoded characters
998
       * so we try to workaround this */
999
7.15k
      if( afx->buffer_pos+2 < afx->buffer_len ) {
1000
4.71k
    int cc1, cc2, cc3;
1001
4.71k
    cc1 = afx->buffer[afx->buffer_pos];
1002
4.71k
    cc2 = afx->buffer[afx->buffer_pos+1];
1003
4.71k
    cc3 = afx->buffer[afx->buffer_pos+2];
1004
4.71k
    if( isxdigit(cc1) && isxdigit(cc2)
1005
570
          && strchr( "=\n\r\t ", cc3 )) {
1006
        /* well it seems to be the case - adjust */
1007
348
        c = isdigit(cc1)? (cc1 - '0'): (ascii_toupper(cc1)-'A'+10);
1008
348
        c <<= 4;
1009
348
        c |= isdigit(cc2)? (cc2 - '0'): (ascii_toupper(cc2)-'A'+10);
1010
348
        afx->buffer_pos += 2;
1011
348
        afx->qp_detected = 1;
1012
348
        goto again;
1013
348
    }
1014
4.71k
      }
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
6.81k
            if (afx->buffer_pos + 6 < afx->buffer_len
1022
1.01k
                && afx->buffer[afx->buffer_pos + 0] == '3'
1023
12
                && afx->buffer[afx->buffer_pos + 1] == 'D'
1024
8
                && asctobin[0][afx->buffer[afx->buffer_pos + 2]] != 0xffffffffUL
1025
8
                && asctobin[0][afx->buffer[afx->buffer_pos + 3]] != 0xffffffffUL
1026
7
                && asctobin[0][afx->buffer[afx->buffer_pos + 4]] != 0xffffffffUL
1027
5
                && asctobin[0][afx->buffer[afx->buffer_pos + 5]] != 0xffffffffUL
1028
4
                && afx->buffer[afx->buffer_pos + 6] == '\n')
1029
0
              {
1030
0
                afx->buffer_pos += 2;
1031
0
                afx->qp_detected = 1;
1032
0
              }
1033
1034
6.81k
      if (!n)
1035
4.10k
        onlypad = 1;
1036
1037
6.81k
      if( idx == 1 )
1038
2.68k
    buf[n++] = val;
1039
6.81k
      checkcrc++;
1040
6.81k
      break;
1041
7.15k
  }
1042
78.9k
        else if (afx->buffer_pos == 1 && c == '-'
1043
797
                 && afx->buffer_len > 9
1044
729
                 && !strncmp (afx->buffer, "-----END ", 9)) {
1045
1
            break; /* End in --dearmor mode or No CRC.  */
1046
1
        }
1047
78.9k
  else {
1048
78.9k
      log_error(_("invalid radix64 character %02X skipped\n"), c);
1049
78.9k
      continue;
1050
78.9k
  }
1051
110k
    }
1052
1053
7.93k
    afx->idx = idx;
1054
7.93k
    afx->radbuf[0] = val;
1055
1056
7.93k
    if( n )
1057
5.29k
      {
1058
5.29k
        gcry_md_write (afx->crc_md, buf, n);
1059
5.29k
        afx->any_data = 1;
1060
5.29k
      }
1061
1062
7.93k
    if( checkcrc ) {
1063
6.81k
  gcry_md_final (afx->crc_md);
1064
6.81k
  afx->inp_checked=0;
1065
6.81k
  afx->faked = 0;
1066
11.3k
  for(;;) { /* skip lf and pad characters */
1067
11.3k
      if( afx->buffer_pos < afx->buffer_len )
1068
10.6k
    c = afx->buffer[afx->buffer_pos++];
1069
678
      else { /* read the next line */
1070
678
    unsigned maxlen = MAX_LINELEN;
1071
678
    afx->buffer_pos = 0;
1072
678
    afx->buffer_len = iobuf_read_line( a, &afx->buffer,
1073
678
               &afx->buffer_size, &maxlen );
1074
678
    if( !maxlen )
1075
0
        afx->truncated++;
1076
678
    if( !afx->buffer_len )
1077
67
        break; /* eof */
1078
611
    continue;
1079
678
      }
1080
10.6k
      if( c == '\n' || c == ' ' || c == '\r'
1081
8.05k
    || c == '\t' || c == '=' )
1082
3.88k
    continue;
1083
6.74k
      break;
1084
10.6k
  }
1085
6.81k
  if( !afx->buffer_len )
1086
6.81k
      log_error(_("premature eof (no CRC)\n"));
1087
6.74k
  else {
1088
6.74k
      u32 mycrc = 0;
1089
6.74k
      idx = 0;
1090
7.70k
      do {
1091
7.70k
    if( (binc = asctobin[0][c]) == 0xffffffffUL )
1092
6.42k
        break;
1093
1.27k
    switch(idx) {
1094
338
      case 0: val =  binc << 2; break;
1095
318
      case 1: val |= (binc>>4)&3; mycrc |= val << 16;val=(binc<<4)&0xf0;break;
1096
312
      case 2: val |= (binc>>2)&15; mycrc |= val << 8;val=(binc<<6)&0xc0;break;
1097
305
      case 3: val |= binc&0x3f; mycrc |= val; break;
1098
1.27k
    }
1099
1.27k
    for(;;) {
1100
1.27k
        if( afx->buffer_pos < afx->buffer_len )
1101
1.26k
      c = afx->buffer[afx->buffer_pos++];
1102
11
        else { /* read the next line */
1103
11
      unsigned maxlen = MAX_LINELEN;
1104
11
      afx->buffer_pos = 0;
1105
11
      afx->buffer_len = iobuf_read_line( a, &afx->buffer,
1106
11
                 &afx->buffer_size,
1107
11
                &maxlen );
1108
11
      if( !maxlen )
1109
0
          afx->truncated++;
1110
11
      if( !afx->buffer_len )
1111
11
          break; /* eof */
1112
0
      continue;
1113
11
        }
1114
1.26k
        break;
1115
1.27k
    }
1116
1.27k
    if( !afx->buffer_len )
1117
11
        break; /* eof */
1118
1.27k
      } while( ++idx < 4 );
1119
6.74k
      if( !afx->buffer_len ) {
1120
11
    log_info(_("premature eof (in CRC)\n"));
1121
11
    rc = invalid_crc();
1122
11
      }
1123
6.73k
      else if( idx == 0 ) {
1124
          /* No CRC at all is legal ("MAY") */
1125
6.40k
          rc=0;
1126
6.40k
      }
1127
327
      else if( idx != 4 ) {
1128
22
    log_info(_("malformed CRC\n"));
1129
22
    rc = invalid_crc();
1130
22
      }
1131
305
      else if( mycrc != get_afx_crc (afx) ) {
1132
58
    log_info (_("CRC error; %06lX - %06lX\n"),
1133
58
            (ulong)get_afx_crc (afx), (ulong)mycrc);
1134
58
    rc = invalid_crc();
1135
58
      }
1136
247
      else {
1137
247
    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
247
      }
1161
6.74k
  }
1162
6.81k
    }
1163
1164
7.93k
    if( !n && !onlypad )
1165
853
  rc = -1;
1166
1167
7.93k
    *retn = n;
1168
7.93k
    return rc;
1169
7.93k
}
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
25.6k
{
1293
25.6k
    size_t size = *ret_len;
1294
25.6k
    armor_filter_context_t *afx = opaque;
1295
25.6k
    int rc=0, c;
1296
25.6k
    byte radbuf[3];
1297
25.6k
    int  idx, idx2;
1298
25.6k
    size_t n=0;
1299
25.6k
    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
25.6k
    if( DBG_FILTER )
1310
25.6k
  log_debug("armor-filter: control: %d\n", control );
1311
25.6k
    if( control == IOBUFCTRL_UNDERFLOW && afx->inp_bypass ) {
1312
4.18k
  n = 0;
1313
4.18k
  if( afx->buffer_len ) {
1314
            /* Copy the data from AFX->BUFFER to BUF.  */
1315
13.4k
            for(; n < size && afx->buffer_pos < afx->buffer_len;)
1316
13.4k
                buf[n++] = afx->buffer[afx->buffer_pos++];
1317
28
      if( afx->buffer_pos >= afx->buffer_len )
1318
23
    afx->buffer_len = 0;
1319
28
  }
1320
        /* If there is still space in BUF, read directly into it.  */
1321
1.59M
  for(; n < size; n++ ) {
1322
1.59M
      if( (c=iobuf_get(a)) == -1 )
1323
4.14k
    break;
1324
1.59M
      buf[n] = c & 0xff;
1325
1.59M
  }
1326
4.18k
  if( !n )
1327
            /* We didn't get any data.  EOF.  */
1328
3.01k
      rc = -1;
1329
4.18k
  *ret_len = n;
1330
4.18k
    }
1331
21.4k
    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
11.6k
  if( size < PARTIAL_CHUNK+1 )
1336
0
      BUG(); /* supplied buffer too short */
1337
1338
11.6k
  if( afx->faked )
1339
0
      rc = fake_packet( afx, a, &n, buf, size );
1340
11.6k
  else if( !afx->inp_checked ) {
1341
11.5k
      rc = check_input( afx, a );
1342
11.5k
      if( afx->inp_bypass ) {
1343
874k
    for(n=0; n < size && afx->buffer_pos < afx->buffer_len; )
1344
870k
        buf[n++] = afx->buffer[afx->buffer_pos++];
1345
3.69k
    if( afx->buffer_pos >= afx->buffer_len )
1346
3.67k
        afx->buffer_len = 0;
1347
3.69k
    if( !n )
1348
53
        rc = -1;
1349
3.69k
      }
1350
7.83k
      else if( afx->faked ) {
1351
0
          unsigned int hashes = afx->hashes;
1352
0
                const byte *sesmark;
1353
0
                size_t sesmarklen;
1354
1355
0
                sesmark = get_session_marker( &sesmarklen );
1356
0
                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
0
    hashes &= 1|2|8|16|32|64;
1363
0
    if( !hashes ) {
1364
0
        hashes |= 2;  /* Default to SHA-1. */
1365
0
    }
1366
0
    n=0;
1367
                /* First a gpg control packet... */
1368
0
                buf[n++] = 0xff; /* new format, type 63, 1 length byte */
1369
0
                n++;   /* see below */
1370
0
                memcpy(buf+n, sesmark, sesmarklen ); n+= sesmarklen;
1371
0
                buf[n++] = CTRLPKT_CLEARSIGN_START;
1372
0
                buf[n++] = afx->not_dash_escaped? 0:1; /* sigclass */
1373
0
                if( hashes & 1 )
1374
0
                    buf[n++] = DIGEST_ALGO_RMD160;
1375
0
                if( hashes & 2 )
1376
0
                    buf[n++] = DIGEST_ALGO_SHA1;
1377
0
                if( hashes & 8 )
1378
0
                    buf[n++] = DIGEST_ALGO_SHA224;
1379
0
                if( hashes & 16 )
1380
0
                    buf[n++] = DIGEST_ALGO_SHA256;
1381
0
                if( hashes & 32 )
1382
0
                    buf[n++] = DIGEST_ALGO_SHA384;
1383
0
                if( hashes & 64 )
1384
0
                    buf[n++] = DIGEST_ALGO_SHA512;
1385
0
                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
0
    buf[n++] = 0xCB; /* new packet format, type 11 */
1393
0
    buf[n++] = 0xE1; /* 2^1 == 2 bytes */
1394
0
    buf[n++] = 't';  /* canonical text mode */
1395
0
    buf[n++] = 0;  /* namelength */
1396
0
    buf[n++] = 0xE2; /* 2^2 == 4 more bytes */
1397
0
    memset(buf+n, 0, 4); /* timestamp */
1398
0
    n += 4;
1399
0
      }
1400
7.83k
      else if( !rc )
1401
7.78k
    rc = radix64_read( afx, a, &n, buf, size );
1402
11.5k
  }
1403
154
  else
1404
154
      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
11.6k
  *ret_len = n;
1411
11.6k
    }
1412
9.78k
    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
9.78k
    else if( control == IOBUFCTRL_INIT )
1486
4.89k
      {
1487
4.89k
  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
4.89k
  if(afx->eol[0]==0)
1493
4.89k
    {
1494
#ifdef HAVE_DOSISH_SYSTEM
1495
      afx->eol[0]='\r';
1496
      afx->eol[1]='\n';
1497
#else
1498
4.89k
      afx->eol[0]='\n';
1499
4.89k
#endif
1500
4.89k
    }
1501
4.89k
      }
1502
4.89k
    else if( control == IOBUFCTRL_CANCEL ) {
1503
0
  afx->cancel = 1;
1504
0
    }
1505
4.89k
    else if( control == IOBUFCTRL_FREE ) {
1506
4.89k
  if( afx->cancel )
1507
0
      ;
1508
4.89k
  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
4.89k
  else if( !afx->any_data && !afx->inp_bypass ) {
1562
540
      log_error(_("no valid OpenPGP data found.\n"));
1563
540
      afx->no_openpgp_data = 1;
1564
540
      write_status_text( STATUS_NODATA, "1" );
1565
540
  }
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
4.89k
  if( afx->truncated )
1572
4.89k
      log_info(_("invalid armor: line longer than %d characters\n"),
1573
0
          MAX_LINELEN );
1574
  /* issue an error to enforce dissemination of correct software */
1575
4.89k
  if( afx->qp_detected )
1576
4.89k
      log_error(_("quoted printable character in armor - "
1577
31
      "probably a buggy MTA has been used\n") );
1578
4.89k
  xfree( afx->buffer );
1579
4.89k
  afx->buffer = NULL;
1580
4.89k
        release_armor_context (afx);
1581
4.89k
    }
1582
0
    else if( control == IOBUFCTRL_DESC )
1583
0
        mem2str (buf, "armor_filter", *ret_len);
1584
25.6k
    return rc;
1585
25.6k
}
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
}