Coverage Report

Created: 2026-06-09 06:38

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
86.8k
#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
6
#define BEGIN_SIGNATURE 2
83
14
#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
16
{
116
16
  armor_filter_context_t *afx;
117
16
  gpg_error_t err;
118
119
16
  afx = xcalloc (1, sizeof *afx);
120
16
  if (afx)
121
16
    {
122
16
      err = gcry_md_open (&afx->crc_md, GCRY_MD_CRC24_RFC2440, 0);
123
16
      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
16
      afx->refcount = 1;
132
16
    }
133
134
16
  return afx;
135
16
}
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
36
{
142
36
  if (!afx)
143
4
    return;
144
36
  log_assert (afx->refcount);
145
32
  if ( --afx->refcount )
146
16
    return;
147
16
  gcry_md_close (afx->crc_md);
148
16
  xfree (afx);
149
16
}
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
16
{
155
16
  int rc;
156
157
16
  afx->refcount++;
158
16
  rc = iobuf_push_filter (iobuf, armor_filter, afx);
159
16
  if (rc)
160
0
    afx->refcount--;
161
16
  return rc;
162
16
}
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
0
{
200
0
  const byte *crc_buf;
201
0
  u32 crc;
202
203
0
  crc_buf = gcry_md_read (afx->crc_md, GCRY_MD_CRC24_RFC2440);
204
205
0
  crc = crc_buf[0];
206
0
  crc <<= 8;
207
0
  crc |= crc_buf[1];
208
0
  crc <<= 8;
209
0
  crc |= crc_buf[2];
210
211
0
  return crc;
212
0
}
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
43
{
227
43
  int ctb, pkttype;
228
43
  int indeterminate_length_allowed;
229
230
43
    ctb = *buf;
231
43
    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
33
      return 1;
236
237
10
    pkttype =  ctb & 0x40 ? (ctb & 0x3f) : ((ctb>>2)&0xf);
238
10
    switch( pkttype ) {
239
0
      case PKT_PUBKEY_ENC:
240
0
      case PKT_SIGNATURE:
241
0
      case PKT_SYMKEY_ENC:
242
0
      case PKT_ONEPASS_SIG:
243
0
      case PKT_SECRET_KEY:
244
0
      case PKT_PUBLIC_KEY:
245
0
      case PKT_SECRET_SUBKEY:
246
0
      case PKT_MARKER:
247
0
      case PKT_RING_TRUST:
248
4
      case PKT_USER_ID:
249
4
      case PKT_PUBLIC_SUBKEY:
250
6
      case PKT_ATTRIBUTE:
251
6
      case PKT_MDC:
252
6
  indeterminate_length_allowed = 0;
253
6
        break;
254
255
2
      case PKT_COMPRESSED:
256
2
      case PKT_ENCRYPTED:
257
2
      case PKT_ENCRYPTED_MDC:
258
2
      case PKT_ENCRYPTED_AEAD:
259
2
      case PKT_PLAINTEXT:
260
2
      case PKT_OLD_COMMENT:
261
2
      case PKT_COMMENT:
262
2
      case PKT_GPG_CONTROL:
263
2
  indeterminate_length_allowed = 1;
264
2
        break;
265
266
2
      default:
267
        /* Invalid packet type.  */
268
2
        return 1;
269
10
    }
270
271
8
    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
6
      {
277
6
        int new_format;
278
6
        int indeterminate_length;
279
280
6
        new_format = !! (ctb & (1 << 6));
281
6
        if (new_format)
282
6
          indeterminate_length = (buf[1] >= 224 && buf[1] < 255);
283
0
        else
284
0
          indeterminate_length = (ctb & 3) == 3;
285
286
6
        if (indeterminate_length)
287
0
          return 1;
288
6
      }
289
290
    /* The first CTB seems legit.  It is probably not armored
291
       data.  */
292
8
    return 0;
293
8
}
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
24
{
304
24
    byte buf[2];
305
24
    int n;
306
307
    /* fixme: there might be a problem with iobuf_peek */
308
24
    n = iobuf_peek (a, buf, 2);
309
24
    if( n == -1 )
310
0
  return 0; /* EOF, doesn't matter whether armored or not */
311
24
    if( !n )
312
0
  return 1; /* can't check it: try armored */
313
24
    if (n != 2)
314
0
  return 0; /* short buffer */
315
24
    return is_armored(buf);
316
24
}
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
5
{
382
5
  if(strncmp(line,"Version",7)==0
383
5
     || strncmp(line,"Comment",7)==0
384
5
     || strncmp(line,"MessageID",9)==0
385
5
     || strncmp(line,"Hash",4)==0
386
5
     || strncmp(line,"Charset",7)==0)
387
0
    return 1;
388
389
5
  return 0;
390
5
}
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
86.4k
{
400
86.4k
    const char *s;
401
86.4k
    byte *save_p, *p;
402
86.4k
    int save_c;
403
86.4k
    int i;
404
405
86.4k
    if( len < 15 )
406
85.2k
  return -1; /* too short */
407
1.18k
    if( memcmp( line, "-----", 5 ) )
408
798
  return -1; /* no */
409
390
    p = strstr( line+5, "-----");
410
390
    if( !p )
411
76
  return -1;
412
314
    save_p = p;
413
314
    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
314
    if(RFC2440)
424
0
      {
425
0
  if( *p == '\r' )
426
0
    p++;
427
0
  if( *p == '\n' )
428
0
    p++;
429
0
      }
430
314
    else
431
460
      while(*p==' ' || *p=='\r' || *p=='\n' || *p=='\t')
432
146
  p++;
433
434
314
    if( *p )
435
170
  return -1; /* garbage after dashes */
436
144
    save_c = *save_p; *save_p = 0;
437
144
    p = line+5;
438
1.08k
    for(i=0; (s=head_strings[i]); i++ )
439
956
  if( !strcmp(s, p) )
440
14
      break;
441
144
    *save_p = save_c;
442
144
    if (!s)
443
130
      {
444
130
        if (!strncmp (p, "BEGIN ", 6))
445
90
          return 42;
446
40
  return -1; /* unknown armor line */
447
130
      }
448
449
14
    if( opt.verbose > 1 )
450
14
  log_info(_("armor: %s\n"), head_strings[i]);
451
14
    return i;
452
144
}
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
25
{
465
25
    byte *p;
466
25
    int hashes=0;
467
25
    unsigned int len2;
468
469
25
    len2 = length_sans_trailing_ws ( line, len );
470
25
    if( !len2 ) {
471
8
        afx->buffer_pos = len2;  /* (it is not the fine way to do it here) */
472
8
  return 0; /* WS only: same as empty line */
473
8
    }
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
17
    p = strchr( line, ':');
486
17
    if (!p && afx->dearmor_state)
487
0
      return 0; /* Special treatment in --dearmor mode.  */
488
17
    if( !p || (RFC2440 && p[1]!=' ')
489
5
  || (!RFC2440 && p[1]!=' ' && p[1]!='\n' && p[1]!='\r'))
490
12
      {
491
12
  log_error (_("invalid armor header: "));
492
12
  es_write_sanitized (log_get_stream (), line, len, NULL, NULL);
493
12
  log_printf ("\n");
494
12
  return -1;
495
12
      }
496
497
    /* Chop off the whitespace we detected before */
498
5
    len=len2;
499
5
    line[len2]='\0';
500
501
5
    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
5
    if (afx->dearmor_mode)
508
0
      ;
509
5
    else if (afx->in_cleartext)
510
0
      {
511
0
  if( (hashes=parse_hash_header( line )) )
512
0
    afx->hashes |= hashes;
513
0
  else if ((opt.compat_flags & COMPAT_ALLOW_NOT_DASH_ESCAPED)
514
0
                 && strlen (line) > 15
515
0
                 && !memcmp( line, "NotDashEscaped:", 15 ) )
516
0
    afx->not_dash_escaped = 1;
517
0
  else
518
0
    {
519
0
      log_error(_("invalid clearsig header\n"));
520
0
      return -1;
521
0
    }
522
0
      }
523
5
    else if(!is_armor_tag(line))
524
5
      {
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
5
  log_info(_("unknown armor header: "));
533
5
  es_write_sanitized (log_get_stream (), line, len, NULL, NULL);
534
5
  log_printf ("\n");
535
5
      }
536
537
5
    return 1;
538
5
}
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
25
{
546
25
    int rc = 0;
547
25
    int i;
548
25
    byte *line;
549
25
    unsigned len;
550
25
    unsigned maxlen;
551
25
    int hdr_line = -1;
552
553
    /* read the first line to see whether this is armored data */
554
25
    maxlen = MAX_LINELEN;
555
25
    len = afx->buffer_len = iobuf_read_line( a, &afx->buffer,
556
25
               &afx->buffer_size, &maxlen );
557
25
    line = afx->buffer;
558
25
    if( !maxlen ) {
559
  /* line has been truncated: assume not armored */
560
5
  afx->inp_checked = 1;
561
5
  afx->inp_bypass = 1;
562
5
  return 0;
563
5
    }
564
565
20
    if( !len ) {
566
0
  return -1; /* eof */
567
0
    }
568
569
    /* (the line is always a C string but maybe longer) */
570
20
    if( *line == '\n' || ( len && (*line == '\r' && line[1]=='\n') ) )
571
1
  ;
572
19
    else if (len >= 2 && !is_armored (line)) {
573
0
  afx->inp_checked = 1;
574
0
  afx->inp_bypass = 1;
575
0
  return 0;
576
0
    }
577
578
    /* find the armor header */
579
86.4k
    while(len) {
580
86.4k
  i = is_armor_header( line, len );
581
86.4k
        if ( i == 42 ) {
582
90
            if (afx->dearmor_mode) {
583
0
                afx->dearmor_state = 1;
584
0
                break;
585
0
            }
586
90
        }
587
86.3k
        else if (i >= 0
588
14
                 && !(afx->only_keyblocks && i != 1 && i != 5 && i != 6 )) {
589
14
      hdr_line = i;
590
14
      if( hdr_line == BEGIN_SIGNED_MSG_IDX ) {
591
9
          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
9
    afx->in_cleartext = 1;
596
9
      }
597
14
      break;
598
14
  }
599
600
  /* read the next line (skip all truncated lines) */
601
86.4k
  do {
602
86.4k
      maxlen = MAX_LINELEN;
603
86.4k
      afx->buffer_len = iobuf_read_line( a, &afx->buffer,
604
86.4k
                 &afx->buffer_size, &maxlen );
605
86.4k
      line = afx->buffer;
606
86.4k
      len = afx->buffer_len;
607
86.4k
  } while( !maxlen );
608
86.4k
    }
609
610
    /* Parse the header lines.  */
611
25
    while(len) {
612
  /* Read the next line (skip all truncated lines). */
613
19
  do {
614
19
      maxlen = MAX_LINELEN;
615
19
      afx->buffer_len = iobuf_read_line( a, &afx->buffer,
616
19
                 &afx->buffer_size, &maxlen );
617
19
      line = afx->buffer;
618
19
      len = afx->buffer_len;
619
19
  } while( !maxlen );
620
621
19
  i = parse_header_line( afx, line, len );
622
19
  if( i <= 0 ) {
623
14
      if (i && RFC2440)
624
0
    rc = GPG_ERR_INV_ARMOR;
625
14
      break;
626
14
  }
627
19
    }
628
629
630
20
    if( rc )
631
0
  invalid_armor();
632
20
    else if( afx->in_cleartext )
633
9
  afx->faked = 1;
634
11
    else {
635
11
  afx->inp_checked = 1;
636
11
  gcry_md_reset (afx->crc_md);
637
11
  afx->idx = 0;
638
11
  afx->radbuf[0] = 0;
639
11
    }
640
641
20
    return rc;
642
20
}
643
644
329k
#define PARTIAL_CHUNK 512
645
312
#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
11
{
656
11
    int rc = 0;
657
11
    size_t len = 0;
658
11
    int lastline = 0;
659
11
    unsigned maxlen, n;
660
11
    byte *p;
661
11
    byte tempbuf[PARTIAL_CHUNK];
662
11
    size_t tempbuf_len=0;
663
11
    int this_truncated;
664
665
1.00k
    while( !rc && size-len>=(PARTIAL_CHUNK+1)) {
666
  /* copy what we have in the line buffer */
667
997
  if( afx->faked == 1 )
668
9
      afx->faked++; /* skip the first (empty) line */
669
988
  else
670
988
    {
671
      /* It's full, so write this partial chunk */
672
988
      if(tempbuf_len==PARTIAL_CHUNK)
673
312
        {
674
312
    buf[len++]=0xE0+PARTIAL_POW;
675
312
    memcpy(&buf[len],tempbuf,PARTIAL_CHUNK);
676
312
    len+=PARTIAL_CHUNK;
677
312
    tempbuf_len=0;
678
312
    continue;
679
312
        }
680
681
162k
      while( tempbuf_len < PARTIAL_CHUNK
682
162k
       && afx->buffer_pos < afx->buffer_len )
683
162k
        tempbuf[tempbuf_len++] = afx->buffer[afx->buffer_pos++];
684
676
      if( tempbuf_len==PARTIAL_CHUNK )
685
312
        continue;
686
676
    }
687
688
  /* read the next line */
689
373
  maxlen = MAX_LINELEN;
690
373
  afx->buffer_pos = 0;
691
373
  afx->buffer_len = iobuf_read_line( a, &afx->buffer,
692
373
             &afx->buffer_size, &maxlen );
693
373
  if( !afx->buffer_len ) {
694
3
      rc = -1; /* eof (should not happen) */
695
3
      continue;
696
3
  }
697
370
  if( !maxlen )
698
1
          {
699
1
      afx->truncated++;
700
1
            this_truncated = 1;
701
1
          }
702
369
        else
703
369
          this_truncated = 0;
704
705
706
370
  p = afx->buffer;
707
370
  n = afx->buffer_len;
708
709
  /* Armor header or dash-escaped line? */
710
370
  if(p[0]=='-')
711
32
    {
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
32
      if(p[1]==' ' && !afx->not_dash_escaped)
719
3
        {
720
    /* It's a dash-escaped line, so skip over the
721
       escape. */
722
3
    afx->buffer_pos = 2;
723
3
        }
724
29
      else if(p[1]=='-' && p[2]=='-' && p[3]=='-' && p[4]=='-')
725
6
        {
726
    /* Five dashes in a row mean it's probably armor
727
       header. */
728
6
    int type = is_armor_header( p, n );
729
6
                if (type == 42)
730
0
                  type = -1;  /* Only OpenPGP armors are expected.  */
731
6
    if( afx->not_dash_escaped && type != BEGIN_SIGNATURE )
732
0
      ; /* this is okay */
733
6
    else
734
6
      {
735
6
        if( type != BEGIN_SIGNATURE )
736
6
          {
737
6
      log_info(_("unexpected armor: "));
738
6
      es_write_sanitized (log_get_stream (), p, n,
739
6
                                            NULL, NULL);
740
6
      log_printf ("\n");
741
6
          }
742
743
6
        lastline = 1;
744
6
        rc = -1;
745
6
      }
746
6
        }
747
23
      else if(!afx->not_dash_escaped)
748
23
        {
749
    /* Bad dash-escaping. */
750
23
    log_info (_("invalid dash escaped line: "));
751
23
    es_write_sanitized (log_get_stream (), p, n, NULL, NULL);
752
23
    log_printf ("\n");
753
23
        }
754
32
    }
755
756
  /* Now handle the end-of-line canonicalization */
757
370
  if( !afx->not_dash_escaped || this_truncated)
758
370
    {
759
370
      int crlf = n > 1 && p[n-2] == '\r' && p[n-1]=='\n';
760
761
370
      afx->buffer_len=
762
370
        trim_trailing_chars( &p[afx->buffer_pos], n-afx->buffer_pos,
763
370
           " \t\r\n");
764
370
      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
370
      if( crlf )
783
238
        afx->buffer[afx->buffer_len++] = '\r';
784
370
      afx->buffer[afx->buffer_len++] = this_truncated? '\f':'\n';
785
370
      afx->buffer[afx->buffer_len] = '\0';
786
370
    }
787
370
    }
788
789
11
    if( lastline ) { /* write last (ending) length header */
790
6
        if(tempbuf_len<192)
791
1
    buf[len++]=tempbuf_len;
792
5
  else
793
5
    {
794
5
      buf[len++]=((tempbuf_len-192)/256) + 192;
795
5
      buf[len++]=(tempbuf_len-192) % 256;
796
5
    }
797
6
  memcpy(&buf[len],tempbuf,tempbuf_len);
798
6
  len+=tempbuf_len;
799
800
6
  rc = 0;
801
6
  afx->faked = 0;
802
6
  afx->in_cleartext = 0;
803
  /* and now read the header lines */
804
6
  afx->buffer_pos = 0;
805
6
  for(;;) {
806
6
      int i;
807
808
      /* read the next line (skip all truncated lines) */
809
6
      do {
810
6
    maxlen = MAX_LINELEN;
811
6
    afx->buffer_len = iobuf_read_line( a, &afx->buffer,
812
6
             &afx->buffer_size, &maxlen );
813
6
      } while( !maxlen );
814
6
      p = afx->buffer;
815
6
      n = afx->buffer_len;
816
6
      if( !n ) {
817
0
    rc = -1;
818
0
    break; /* eof */
819
0
      }
820
6
      i = parse_header_line( afx, p , n );
821
6
      if( i <= 0 ) {
822
6
    if( i )
823
0
        invalid_armor();
824
6
    break;
825
6
      }
826
6
  }
827
6
  afx->inp_checked = 1;
828
6
  gcry_md_reset (afx->crc_md);
829
6
  afx->idx = 0;
830
6
  afx->radbuf[0] = 0;
831
6
    }
832
833
11
    *retn = len;
834
11
    return rc;
835
11
}
836
837
838
static int
839
invalid_crc(void)
840
0
{
841
0
  if ( opt.ignore_crc_error )
842
0
    return 0;
843
0
  log_inc_errorcount();
844
0
  return gpg_error (GPG_ERR_INV_ARMOR);
845
0
}
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
15
{
852
15
    byte val;
853
15
    int c;
854
15
    u32 binc;
855
15
    int checkcrc=0;
856
15
    int rc = 0;
857
15
    size_t n = 0;
858
15
    int idx, onlypad=0;
859
15
    int skip_fast = 0;
860
861
15
    idx = afx->idx;
862
15
    val = afx->radbuf[0];
863
385
    for( n=0; n < size; ) {
864
865
385
  if( afx->buffer_pos < afx->buffer_len )
866
359
      c = afx->buffer[afx->buffer_pos++];
867
26
  else { /* read the next line */
868
26
      unsigned maxlen = MAX_LINELEN;
869
26
      afx->buffer_pos = 0;
870
26
      afx->buffer_len = iobuf_read_line( a, &afx->buffer,
871
26
                 &afx->buffer_size, &maxlen );
872
26
      if( !maxlen )
873
0
    afx->truncated++;
874
26
      if( !afx->buffer_len )
875
6
    break; /* eof */
876
20
      continue;
877
26
  }
878
879
359
      again:
880
359
  binc = asctobin[0][c];
881
882
359
  if( binc != 0xffffffffUL )
883
114
    {
884
114
      if( idx == 0 && skip_fast == 0
885
30
    && afx->buffer_pos + (16 - 1) < afx->buffer_len
886
30
    && n + 12 < size)
887
30
        {
888
    /* Fast path for radix64 to binary conversion.  */
889
30
    u32 b0,b1,b2,b3;
890
891
    /* Speculatively load 15 more input bytes.  */
892
30
    b0 = binc << (3 * 6);
893
30
    b0 |= asctobin[2][afx->buffer[afx->buffer_pos + 0]];
894
30
    b0 |= asctobin[1][afx->buffer[afx->buffer_pos + 1]];
895
30
    b0 |= asctobin[0][afx->buffer[afx->buffer_pos + 2]];
896
30
    b1  = asctobin[3][afx->buffer[afx->buffer_pos + 3]];
897
30
    b1 |= asctobin[2][afx->buffer[afx->buffer_pos + 4]];
898
30
    b1 |= asctobin[1][afx->buffer[afx->buffer_pos + 5]];
899
30
    b1 |= asctobin[0][afx->buffer[afx->buffer_pos + 6]];
900
30
    b2  = asctobin[3][afx->buffer[afx->buffer_pos + 7]];
901
30
    b2 |= asctobin[2][afx->buffer[afx->buffer_pos + 8]];
902
30
    b2 |= asctobin[1][afx->buffer[afx->buffer_pos + 9]];
903
30
    b2 |= asctobin[0][afx->buffer[afx->buffer_pos + 10]];
904
30
    b3  = asctobin[3][afx->buffer[afx->buffer_pos + 11]];
905
30
    b3 |= asctobin[2][afx->buffer[afx->buffer_pos + 12]];
906
30
    b3 |= asctobin[1][afx->buffer[afx->buffer_pos + 13]];
907
30
    b3 |= asctobin[0][afx->buffer[afx->buffer_pos + 14]];
908
909
    /* Check if any of the input bytes were invalid. */
910
30
    if( (b0 | b1 | b2 | b3) != 0xffffffffUL )
911
0
      {
912
        /* All 16 bytes are valid. */
913
0
        buf[n + 0] = b0 >> (2 * 8);
914
0
        buf[n + 1] = b0 >> (1 * 8);
915
0
        buf[n + 2] = b0 >> (0 * 8);
916
0
        buf[n + 3] = b1 >> (2 * 8);
917
0
        buf[n + 4] = b1 >> (1 * 8);
918
0
        buf[n + 5] = b1 >> (0 * 8);
919
0
        buf[n + 6] = b2 >> (2 * 8);
920
0
        buf[n + 7] = b2 >> (1 * 8);
921
0
        buf[n + 8] = b2 >> (0 * 8);
922
0
        buf[n + 9] = b3 >> (2 * 8);
923
0
        buf[n + 10] = b3 >> (1 * 8);
924
0
        buf[n + 11] = b3 >> (0 * 8);
925
0
        afx->buffer_pos += 16 - 1;
926
0
        n += 12;
927
0
        continue;
928
0
      }
929
30
    else if( b0 == 0xffffffffUL )
930
25
      {
931
        /* byte[1..3] have invalid character(s).  Switch to slow
932
           path.  */
933
25
        skip_fast = 1;
934
25
      }
935
5
    else if( b1 == 0xffffffffUL )
936
5
      {
937
        /* byte[4..7] have invalid character(s), first 4 bytes are
938
           valid.  */
939
5
        buf[n + 0] = b0 >> (2 * 8);
940
5
        buf[n + 1] = b0 >> (1 * 8);
941
5
        buf[n + 2] = b0 >> (0 * 8);
942
5
        afx->buffer_pos += 4 - 1;
943
5
        n += 3;
944
5
        skip_fast = 1;
945
5
        continue;
946
5
      }
947
0
    else if( b2 == 0xffffffffUL )
948
0
      {
949
        /* byte[8..11] have invalid character(s), first 8 bytes are
950
           valid.  */
951
0
        buf[n + 0] = b0 >> (2 * 8);
952
0
        buf[n + 1] = b0 >> (1 * 8);
953
0
        buf[n + 2] = b0 >> (0 * 8);
954
0
        buf[n + 3] = b1 >> (2 * 8);
955
0
        buf[n + 4] = b1 >> (1 * 8);
956
0
        buf[n + 5] = b1 >> (0 * 8);
957
0
        afx->buffer_pos += 8 - 1;
958
0
        n += 6;
959
0
        skip_fast = 1;
960
0
        continue;
961
0
      }
962
0
    else /*if( b3 == 0xffffffffUL )*/
963
0
      {
964
        /* byte[12..15] have invalid character(s), first 12 bytes
965
           are valid.  */
966
0
        buf[n + 0] = b0 >> (2 * 8);
967
0
        buf[n + 1] = b0 >> (1 * 8);
968
0
        buf[n + 2] = b0 >> (0 * 8);
969
0
        buf[n + 3] = b1 >> (2 * 8);
970
0
        buf[n + 4] = b1 >> (1 * 8);
971
0
        buf[n + 5] = b1 >> (0 * 8);
972
0
        buf[n + 6] = b2 >> (2 * 8);
973
0
        buf[n + 7] = b2 >> (1 * 8);
974
0
        buf[n + 8] = b2 >> (0 * 8);
975
0
        afx->buffer_pos += 12 - 1;
976
0
        n += 9;
977
0
        skip_fast = 1;
978
0
        continue;
979
0
      }
980
30
        }
981
982
109
      switch(idx)
983
109
        {
984
30
    case 0: val =  binc << 2; break;
985
29
    case 1: val |= (binc>>4)&3; buf[n++]=val;val=(binc<<4)&0xf0;break;
986
25
    case 2: val |= (binc>>2)&15; buf[n++]=val;val=(binc<<6)&0xc0;break;
987
25
    case 3: val |= binc&0x3f; buf[n++] = val; break;
988
109
        }
989
109
      idx = (idx+1) % 4;
990
991
109
      continue;
992
109
    }
993
994
245
  skip_fast = 0;
995
996
245
  if( c == '\n' || c == ' ' || c == '\r' || c == '\t' )
997
24
      continue;
998
221
  else if( c == '=' ) { /* pad character: stop */
999
      /* some mailers leave quoted-printable encoded characters
1000
       * so we try to workaround this */
1001
9
      if( afx->buffer_pos+2 < afx->buffer_len ) {
1002
5
    int cc1, cc2, cc3;
1003
5
    cc1 = afx->buffer[afx->buffer_pos];
1004
5
    cc2 = afx->buffer[afx->buffer_pos+1];
1005
5
    cc3 = afx->buffer[afx->buffer_pos+2];
1006
5
    if( isxdigit(cc1) && isxdigit(cc2)
1007
0
          && strchr( "=\n\r\t ", cc3 )) {
1008
        /* well it seems to be the case - adjust */
1009
0
        c = isdigit(cc1)? (cc1 - '0'): (ascii_toupper(cc1)-'A'+10);
1010
0
        c <<= 4;
1011
0
        c |= isdigit(cc2)? (cc2 - '0'): (ascii_toupper(cc2)-'A'+10);
1012
0
        afx->buffer_pos += 2;
1013
0
        afx->qp_detected = 1;
1014
0
        goto again;
1015
0
    }
1016
5
      }
1017
1018
            /* Occasionally a bug MTA will leave the = escaped as
1019
               =3D.  If the 4 characters following that are valid
1020
               Radix64 characters and they are following by a new
1021
               line, assume that this is the case and skip the
1022
               3D.  */
1023
9
            if (afx->buffer_pos + 6 < afx->buffer_len
1024
5
                && afx->buffer[afx->buffer_pos + 0] == '3'
1025
0
                && afx->buffer[afx->buffer_pos + 1] == 'D'
1026
0
                && asctobin[0][afx->buffer[afx->buffer_pos + 2]] != 0xffffffffUL
1027
0
                && asctobin[0][afx->buffer[afx->buffer_pos + 3]] != 0xffffffffUL
1028
0
                && asctobin[0][afx->buffer[afx->buffer_pos + 4]] != 0xffffffffUL
1029
0
                && asctobin[0][afx->buffer[afx->buffer_pos + 5]] != 0xffffffffUL
1030
0
                && afx->buffer[afx->buffer_pos + 6] == '\n')
1031
0
              {
1032
0
                afx->buffer_pos += 2;
1033
0
                afx->qp_detected = 1;
1034
0
              }
1035
1036
9
      if (!n)
1037
4
        onlypad = 1;
1038
1039
9
      if( idx == 1 )
1040
1
    buf[n++] = val;
1041
9
      checkcrc++;
1042
9
      break;
1043
9
  }
1044
212
        else if (afx->buffer_pos == 1 && c == '-'
1045
0
                 && afx->buffer_len > 9
1046
0
                 && !strncmp (afx->buffer, "-----END ", 9)) {
1047
            /* End in --dearmor mode.  */
1048
0
            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
0
                afx->buffer_pos--;
1053
0
            break;
1054
0
        }
1055
212
  else {
1056
212
      log_error(_("invalid radix64 character %02X skipped\n"), c);
1057
212
      continue;
1058
212
  }
1059
245
    }
1060
1061
15
    afx->idx = idx;
1062
15
    afx->radbuf[0] = val;
1063
1064
15
    if( n )
1065
5
      {
1066
5
        gcry_md_write (afx->crc_md, buf, n);
1067
5
        afx->any_data = 1;
1068
5
      }
1069
1070
15
    if( checkcrc ) {
1071
9
  gcry_md_final (afx->crc_md);
1072
9
  afx->inp_checked=0;
1073
9
  afx->faked = 0;
1074
17
  for(;;) { /* skip lf and pad characters */
1075
17
      if( afx->buffer_pos < afx->buffer_len )
1076
13
    c = afx->buffer[afx->buffer_pos++];
1077
4
      else { /* read the next line */
1078
4
    unsigned maxlen = MAX_LINELEN;
1079
4
    afx->buffer_pos = 0;
1080
4
    afx->buffer_len = iobuf_read_line( a, &afx->buffer,
1081
4
               &afx->buffer_size, &maxlen );
1082
4
    if( !maxlen )
1083
0
        afx->truncated++;
1084
4
    if( !afx->buffer_len )
1085
0
        break; /* eof */
1086
4
    continue;
1087
4
      }
1088
13
      if( c == '\n' || c == ' ' || c == '\r'
1089
9
    || c == '\t' || c == '=' )
1090
4
    continue;
1091
9
      break;
1092
13
  }
1093
9
  if( !afx->buffer_len )
1094
9
      log_error(_("premature eof (no CRC)\n"));
1095
9
  else {
1096
9
      u32 mycrc = 0;
1097
9
      idx = 0;
1098
9
      do {
1099
9
    if( (binc = asctobin[0][c]) == 0xffffffffUL )
1100
9
        break;
1101
0
    switch(idx) {
1102
0
      case 0: val =  binc << 2; break;
1103
0
      case 1: val |= (binc>>4)&3; mycrc |= val << 16;val=(binc<<4)&0xf0;break;
1104
0
      case 2: val |= (binc>>2)&15; mycrc |= val << 8;val=(binc<<6)&0xc0;break;
1105
0
      case 3: val |= binc&0x3f; mycrc |= val; break;
1106
0
    }
1107
0
    for(;;) {
1108
0
        if( afx->buffer_pos < afx->buffer_len )
1109
0
      c = afx->buffer[afx->buffer_pos++];
1110
0
        else { /* read the next line */
1111
0
      unsigned maxlen = MAX_LINELEN;
1112
0
      afx->buffer_pos = 0;
1113
0
      afx->buffer_len = iobuf_read_line( a, &afx->buffer,
1114
0
                 &afx->buffer_size,
1115
0
                &maxlen );
1116
0
      if( !maxlen )
1117
0
          afx->truncated++;
1118
0
      if( !afx->buffer_len )
1119
0
          break; /* eof */
1120
0
      continue;
1121
0
        }
1122
0
        break;
1123
0
    }
1124
0
    if( !afx->buffer_len )
1125
0
        break; /* eof */
1126
0
      } while( ++idx < 4 );
1127
9
      if( !afx->buffer_len ) {
1128
0
    log_info(_("premature eof (in CRC)\n"));
1129
0
    rc = invalid_crc();
1130
0
      }
1131
9
      else if( idx == 0 ) {
1132
          /* No CRC at all is legal ("MAY") */
1133
9
          rc=0;
1134
9
      }
1135
0
      else if( idx != 4 ) {
1136
0
    log_info(_("malformed CRC\n"));
1137
0
    rc = invalid_crc();
1138
0
      }
1139
0
      else if( mycrc != get_afx_crc (afx) ) {
1140
0
    log_info (_("CRC error; %06lX - %06lX\n"),
1141
0
            (ulong)get_afx_crc (afx), (ulong)mycrc);
1142
0
    rc = invalid_crc();
1143
0
      }
1144
0
      else {
1145
0
    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
0
      }
1169
9
  }
1170
9
    }
1171
1172
15
    if( !n && !onlypad )
1173
6
  rc = -1;
1174
1175
15
    *retn = n;
1176
15
    return rc;
1177
15
}
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
74
{
1301
74
    size_t size = *ret_len;
1302
74
    armor_filter_context_t *afx = opaque;
1303
74
    int rc=0, c;
1304
74
    byte radbuf[3];
1305
74
    int  idx, idx2;
1306
74
    size_t n=0;
1307
74
    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
74
    if( DBG_FILTER )
1318
74
  log_debug("armor-filter: control: %d\n", control );
1319
74
    if( control == IOBUFCTRL_UNDERFLOW && afx->inp_bypass ) {
1320
2
  n = 0;
1321
2
  if( afx->buffer_len ) {
1322
            /* Copy the data from AFX->BUFFER to BUF.  */
1323
0
            for(; n < size && afx->buffer_pos < afx->buffer_len;)
1324
0
                buf[n++] = afx->buffer[afx->buffer_pos++];
1325
0
      if( afx->buffer_pos >= afx->buffer_len )
1326
0
    afx->buffer_len = 0;
1327
0
  }
1328
        /* If there is still space in BUF, read directly into it.  */
1329
2
  for(; n < size; n++ ) {
1330
2
      if( (c=iobuf_get(a)) == -1 )
1331
2
    break;
1332
0
      buf[n] = c & 0xff;
1333
0
  }
1334
2
  if( !n )
1335
            /* We didn't get any data.  EOF.  */
1336
2
      rc = -1;
1337
2
  *ret_len = n;
1338
2
    }
1339
72
    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
40
  if( size < PARTIAL_CHUNK+1 )
1344
0
      BUG(); /* supplied buffer too short */
1345
1346
40
  if( afx->faked )
1347
11
      rc = fake_packet( afx, a, &n, buf, size );
1348
29
  else if( !afx->inp_checked ) {
1349
25
      rc = check_input( afx, a );
1350
25
      if( afx->inp_bypass ) {
1351
81.0k
    for(n=0; n < size && afx->buffer_pos < afx->buffer_len; )
1352
81.0k
        buf[n++] = afx->buffer[afx->buffer_pos++];
1353
5
    if( afx->buffer_pos >= afx->buffer_len )
1354
4
        afx->buffer_len = 0;
1355
5
    if( !n )
1356
0
        rc = -1;
1357
5
      }
1358
20
      else if( afx->faked ) {
1359
9
          unsigned int hashes = afx->hashes;
1360
9
                const byte *sesmark;
1361
9
                size_t sesmarklen;
1362
1363
9
                sesmark = get_session_marker( &sesmarklen );
1364
9
                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
9
    hashes &= 1|2|8|16|32|64;
1371
9
    if( !hashes ) {
1372
9
        hashes |= 2;  /* Default to SHA-1. */
1373
9
    }
1374
9
    n=0;
1375
                /* First a gpg control packet... */
1376
9
                buf[n++] = 0xff; /* new format, type 63, 1 length byte */
1377
9
                n++;   /* see below */
1378
9
                memcpy(buf+n, sesmark, sesmarklen ); n+= sesmarklen;
1379
9
                buf[n++] = CTRLPKT_CLEARSIGN_START;
1380
9
                buf[n++] = afx->not_dash_escaped? 0:1; /* sigclass */
1381
9
                if( hashes & 1 )
1382
0
                    buf[n++] = DIGEST_ALGO_RMD160;
1383
9
                if( hashes & 2 )
1384
9
                    buf[n++] = DIGEST_ALGO_SHA1;
1385
9
                if( hashes & 8 )
1386
0
                    buf[n++] = DIGEST_ALGO_SHA224;
1387
9
                if( hashes & 16 )
1388
0
                    buf[n++] = DIGEST_ALGO_SHA256;
1389
9
                if( hashes & 32 )
1390
0
                    buf[n++] = DIGEST_ALGO_SHA384;
1391
9
                if( hashes & 64 )
1392
0
                    buf[n++] = DIGEST_ALGO_SHA512;
1393
9
                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
9
    buf[n++] = 0xCB; /* new packet format, type 11 */
1401
9
    buf[n++] = 0xE1; /* 2^1 == 2 bytes */
1402
9
    buf[n++] = 't';  /* canonical text mode */
1403
9
    buf[n++] = 0;  /* namelength */
1404
9
    buf[n++] = 0xE2; /* 2^2 == 4 more bytes */
1405
9
    memset(buf+n, 0, 4); /* timestamp */
1406
9
    n += 4;
1407
9
      }
1408
11
      else if( !rc )
1409
11
    rc = radix64_read( afx, a, &n, buf, size );
1410
25
  }
1411
4
  else
1412
4
      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
40
  *ret_len = n;
1419
40
    }
1420
32
    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
32
    else if( control == IOBUFCTRL_INIT )
1494
16
      {
1495
16
  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
16
  if(afx->eol[0]==0)
1501
16
    {
1502
#ifdef HAVE_DOSISH_SYSTEM
1503
      afx->eol[0]='\r';
1504
      afx->eol[1]='\n';
1505
#else
1506
16
      afx->eol[0]='\n';
1507
16
#endif
1508
16
    }
1509
16
      }
1510
16
    else if( control == IOBUFCTRL_CANCEL ) {
1511
0
  afx->cancel = 1;
1512
0
    }
1513
16
    else if( control == IOBUFCTRL_FREE ) {
1514
16
  if( afx->cancel )
1515
0
      ;
1516
16
  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
16
  else if( !afx->any_data && !afx->inp_bypass ) {
1570
8
      log_error(_("no valid OpenPGP data found.\n"));
1571
8
      afx->no_openpgp_data = 1;
1572
8
      write_status_text( STATUS_NODATA, "1" );
1573
8
  }
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
16
  if( afx->truncated )
1580
16
      log_info(_("invalid armor: line longer than %d characters\n"),
1581
1
          MAX_LINELEN );
1582
  /* issue an error to enforce dissemination of correct software */
1583
16
  if( afx->qp_detected )
1584
16
      log_error(_("quoted printable character in armor - "
1585
0
      "probably a buggy MTA has been used\n") );
1586
16
  xfree( afx->buffer );
1587
16
  afx->buffer = NULL;
1588
16
        release_armor_context (afx);
1589
16
    }
1590
0
    else if( control == IOBUFCTRL_DESC )
1591
0
        mem2str (buf, "armor_filter", *ret_len);
1592
74
    return rc;
1593
74
}
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
}