sm: Print Yubikey attestation extensions with --dump-cert.
[gnupg.git] / g10 / armor.c
index fb74655..9727665 100644 (file)
@@ -1,4 +1,4 @@
-/* armor.c - Armor flter
+/* armor.c - Armor filter
  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
  *               2007 Free Software Foundation, Inc.
  *
@@ -15,7 +15,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
 #include <ctype.h>
 
 #include "gpg.h"
-#include "status.h"
-#include "iobuf.h"
-#include "util.h"
+#include "../common/status.h"
+#include "../common/iobuf.h"
+#include "../common/util.h"
 #include "filter.h"
 #include "packet.h"
 #include "options.h"
 #include "main.h"
-#include "status.h"
-#include "i18n.h"
+#include "../common/i18n.h"
 
 #define MAX_LINELEN 20000
 
-#define CRCINIT 0xB704CE
-#define CRCPOLY 0X864CFB
-#define CRCUPDATE(a,c) do {                                                \
-                       a = ((a) << 8) ^ crc_table[((a)&0xff >> 16) ^ (c)]; \
-                       a &= 0x00ffffff;                                    \
-                   } while(0)
-static u32 crc_table[256];
-static byte bintoasc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-                        "abcdefghijklmnopqrstuvwxyz"
-                        "0123456789+/";
-static byte asctobin[256]; /* runtime initialized */
+static const byte bintoasc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                               "abcdefghijklmnopqrstuvwxyz"
+                               "0123456789+/";
+static u32 asctobin[4][256]; /* runtime initialized */
 static int is_initialized;
 
 
@@ -122,9 +114,22 @@ armor_filter_context_t *
 new_armor_context (void)
 {
   armor_filter_context_t *afx;
+  gpg_error_t err;
 
   afx = xcalloc (1, sizeof *afx);
-  afx->refcount = 1;
+  if (afx)
+    {
+      err = gcry_md_open (&afx->crc_md, GCRY_MD_CRC24_RFC2440, 0);
+      if (err != 0)
+       {
+         log_error ("gcry_md_open failed for GCRY_MD_CRC24_RFC2440: %s",
+                   gpg_strerror (err));
+         xfree (afx);
+         return NULL;
+       }
+
+      afx->refcount = 1;
+    }
 
   return afx;
 }
@@ -139,6 +144,7 @@ release_armor_context (armor_filter_context_t *afx)
   log_assert (afx->refcount);
   if ( --afx->refcount )
     return;
+  gcry_md_close (afx->crc_md);
   xfree (afx);
 }
 
@@ -162,41 +168,53 @@ push_armor_filter (armor_filter_context_t *afx, iobuf_t iobuf)
 static void
 initialize(void)
 {
-    int i, j;
-    u32 t;
-    byte *s;
-
-    /* init the crc lookup table */
-    crc_table[0] = 0;
-    for(i=j=0; j < 128; j++ ) {
-       t = crc_table[j];
-       if( t & 0x00800000 ) {
-           t <<= 1;
-           crc_table[i++] = t ^ CRCPOLY;
-           crc_table[i++] = t;
-       }
-       else {
-           t <<= 1;
-           crc_table[i++] = t;
-           crc_table[i++] = t ^ CRCPOLY;
-       }
-    }
-    /* build the helptable for radix64 to bin conversion */
-    for(i=0; i < 256; i++ )
-       asctobin[i] = 255; /* used to detect invalid characters */
+    u32 i;
+    const byte *s;
+
+    /* Build the helptable for radix64 to bin conversion.  Value 0xffffffff is
+       used to detect invalid characters.  */
+    memset (asctobin, 0xff, sizeof(asctobin));
     for(s=bintoasc,i=0; *s; s++,i++ )
-       asctobin[*s] = i;
+      {
+       asctobin[0][*s] = i << (0 * 6);
+       asctobin[1][*s] = i << (1 * 6);
+       asctobin[2][*s] = i << (2 * 6);
+       asctobin[3][*s] = i << (3 * 6);
+      }
 
     is_initialized=1;
 }
 
-/****************
- * Check whether this is an armored file or not See also
+
+static inline u32
+get_afx_crc (armor_filter_context_t *afx)
+{
+  const byte *crc_buf;
+  u32 crc;
+
+  crc_buf = gcry_md_read (afx->crc_md, GCRY_MD_CRC24_RFC2440);
+
+  crc = crc_buf[0];
+  crc <<= 8;
+  crc |= crc_buf[1];
+  crc <<= 8;
+  crc |= crc_buf[2];
+
+  return crc;
+}
+
+
+/*
+ * Check whether this is an armored file.  See also
  * parse-packet.c for details on this code.
+ *
+ * Note that the buffer BUF needs to be at least 2 bytes long.  If in
+ * doubt that the second byte to 0.
+ *
  * Returns: True if it seems to be armored
  */
 static int
-is_armored( const byte *buf )
+is_armored (const byte *buf)
 {
   int ctb, pkttype;
   int indeterminate_length_allowed;
@@ -274,15 +292,17 @@ is_armored( const byte *buf )
 int
 use_armor_filter( IOBUF a )
 {
-    byte buf[1];
+    byte buf[2];
     int n;
 
     /* fixme: there might be a problem with iobuf_peek */
-    n = iobuf_peek(a, buf, 1 );
+    n = iobuf_peek (a, buf, 2);
     if( n == -1 )
        return 0; /* EOF, doesn't matter whether armored or not */
     if( !n )
        return 1; /* can't check it: try armored */
+    if (n != 2)
+       return 0; /* short buffer */
     return is_armored(buf);
 }
 
@@ -530,7 +550,7 @@ check_input( armor_filter_context_t *afx, IOBUF a )
     /* (the line is always a C string but maybe longer) */
     if( *line == '\n' || ( len && (*line == '\r' && line[1]=='\n') ) )
        ;
-    else if( !is_armored( line ) ) {
+    else if (len >= 2 && !is_armored (line)) {
        afx->inp_checked = 1;
        afx->inp_bypass = 1;
        return 0;
@@ -586,7 +606,7 @@ check_input( armor_filter_context_t *afx, IOBUF a )
        afx->faked = 1;
     else {
        afx->inp_checked = 1;
-       afx->crc = CRCINIT;
+       gcry_md_reset (afx->crc_md);
        afx->idx = 0;
        afx->radbuf[0] = 0;
     }
@@ -762,7 +782,7 @@ fake_packet( armor_filter_context_t *afx, IOBUF a,
            }
        }
        afx->inp_checked = 1;
-       afx->crc = CRCINIT;
+       gcry_md_reset (afx->crc_md);
        afx->idx = 0;
        afx->radbuf[0] = 0;
     }
@@ -787,14 +807,14 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
              byte *buf, size_t size )
 {
     byte val;
-    int c=0, c2; /*init c because gcc is not clever enough for the continue*/
+    int c;
+    u32 binc;
     int checkcrc=0;
     int rc = 0;
     size_t n = 0;
-    int  idx, i, onlypad=0;
-    u32 crc;
+    int idx, onlypad=0;
+    int skip_fast = 0;
 
-    crc = afx->crc;
     idx = afx->idx;
     val = afx->radbuf[0];
     for( n=0; n < size; ) {
@@ -814,6 +834,122 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
        }
 
       again:
+       binc = asctobin[0][c];
+
+       if( binc != 0xffffffffUL )
+         {
+           if( idx == 0 && skip_fast == 0
+               && afx->buffer_pos + (16 - 1) < afx->buffer_len
+               && n + 12 < size)
+             {
+               /* Fast path for radix64 to binary conversion.  */
+               u32 b0,b1,b2,b3;
+
+               /* Speculatively load 15 more input bytes.  */
+               b0 = binc << (3 * 6);
+               b0 |= asctobin[2][afx->buffer[afx->buffer_pos + 0]];
+               b0 |= asctobin[1][afx->buffer[afx->buffer_pos + 1]];
+               b0 |= asctobin[0][afx->buffer[afx->buffer_pos + 2]];
+               b1  = asctobin[3][afx->buffer[afx->buffer_pos + 3]];
+               b1 |= asctobin[2][afx->buffer[afx->buffer_pos + 4]];
+               b1 |= asctobin[1][afx->buffer[afx->buffer_pos + 5]];
+               b1 |= asctobin[0][afx->buffer[afx->buffer_pos + 6]];
+               b2  = asctobin[3][afx->buffer[afx->buffer_pos + 7]];
+               b2 |= asctobin[2][afx->buffer[afx->buffer_pos + 8]];
+               b2 |= asctobin[1][afx->buffer[afx->buffer_pos + 9]];
+               b2 |= asctobin[0][afx->buffer[afx->buffer_pos + 10]];
+               b3  = asctobin[3][afx->buffer[afx->buffer_pos + 11]];
+               b3 |= asctobin[2][afx->buffer[afx->buffer_pos + 12]];
+               b3 |= asctobin[1][afx->buffer[afx->buffer_pos + 13]];
+               b3 |= asctobin[0][afx->buffer[afx->buffer_pos + 14]];
+
+               /* Check if any of the input bytes were invalid. */
+               if( (b0 | b1 | b2 | b3) != 0xffffffffUL )
+                 {
+                   /* All 16 bytes are valid. */
+                   buf[n + 0] = b0 >> (2 * 8);
+                   buf[n + 1] = b0 >> (1 * 8);
+                   buf[n + 2] = b0 >> (0 * 8);
+                   buf[n + 3] = b1 >> (2 * 8);
+                   buf[n + 4] = b1 >> (1 * 8);
+                   buf[n + 5] = b1 >> (0 * 8);
+                   buf[n + 6] = b2 >> (2 * 8);
+                   buf[n + 7] = b2 >> (1 * 8);
+                   buf[n + 8] = b2 >> (0 * 8);
+                   buf[n + 9] = b3 >> (2 * 8);
+                   buf[n + 10] = b3 >> (1 * 8);
+                   buf[n + 11] = b3 >> (0 * 8);
+                   afx->buffer_pos += 16 - 1;
+                   n += 12;
+                   continue;
+                 }
+               else if( b0 == 0xffffffffUL )
+                 {
+                   /* byte[1..3] have invalid character(s).  Switch to slow
+                      path.  */
+                   skip_fast = 1;
+                 }
+               else if( b1 == 0xffffffffUL )
+                 {
+                   /* byte[4..7] have invalid character(s), first 4 bytes are
+                      valid.  */
+                   buf[n + 0] = b0 >> (2 * 8);
+                   buf[n + 1] = b0 >> (1 * 8);
+                   buf[n + 2] = b0 >> (0 * 8);
+                   afx->buffer_pos += 4 - 1;
+                   n += 3;
+                   skip_fast = 1;
+                   continue;
+                 }
+               else if( b2 == 0xffffffffUL )
+                 {
+                   /* byte[8..11] have invalid character(s), first 8 bytes are
+                      valid.  */
+                   buf[n + 0] = b0 >> (2 * 8);
+                   buf[n + 1] = b0 >> (1 * 8);
+                   buf[n + 2] = b0 >> (0 * 8);
+                   buf[n + 3] = b1 >> (2 * 8);
+                   buf[n + 4] = b1 >> (1 * 8);
+                   buf[n + 5] = b1 >> (0 * 8);
+                   afx->buffer_pos += 8 - 1;
+                   n += 6;
+                   skip_fast = 1;
+                   continue;
+                 }
+               else /*if( b3 == 0xffffffffUL )*/
+                 {
+                   /* byte[12..15] have invalid character(s), first 12 bytes
+                      are valid.  */
+                   buf[n + 0] = b0 >> (2 * 8);
+                   buf[n + 1] = b0 >> (1 * 8);
+                   buf[n + 2] = b0 >> (0 * 8);
+                   buf[n + 3] = b1 >> (2 * 8);
+                   buf[n + 4] = b1 >> (1 * 8);
+                   buf[n + 5] = b1 >> (0 * 8);
+                   buf[n + 6] = b2 >> (2 * 8);
+                   buf[n + 7] = b2 >> (1 * 8);
+                   buf[n + 8] = b2 >> (0 * 8);
+                   afx->buffer_pos += 12 - 1;
+                   n += 9;
+                   skip_fast = 1;
+                   continue;
+                 }
+             }
+
+           switch(idx)
+             {
+               case 0: val =  binc << 2; break;
+               case 1: val |= (binc>>4)&3; buf[n++]=val;val=(binc<<4)&0xf0;break;
+               case 2: val |= (binc>>2)&15; buf[n++]=val;val=(binc<<6)&0xc0;break;
+               case 3: val |= binc&0x3f; buf[n++] = val; break;
+             }
+           idx = (idx+1) % 4;
+
+           continue;
+         }
+
+       skip_fast = 0;
+
        if( c == '\n' || c == ' ' || c == '\r' || c == '\t' )
            continue;
        else if( c == '=' ) { /* pad character: stop */
@@ -844,10 +980,10 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
             if (afx->buffer_pos + 6 < afx->buffer_len
                 && afx->buffer[afx->buffer_pos + 0] == '3'
                 && afx->buffer[afx->buffer_pos + 1] == 'D'
-                && asctobin[afx->buffer[afx->buffer_pos + 2]] != 255
-                && asctobin[afx->buffer[afx->buffer_pos + 3]] != 255
-                && asctobin[afx->buffer[afx->buffer_pos + 4]] != 255
-                && asctobin[afx->buffer[afx->buffer_pos + 5]] != 255
+                && asctobin[0][afx->buffer[afx->buffer_pos + 2]] != 0xffffffffUL
+                && asctobin[0][afx->buffer[afx->buffer_pos + 3]] != 0xffffffffUL
+                && asctobin[0][afx->buffer[afx->buffer_pos + 4]] != 0xffffffffUL
+                && asctobin[0][afx->buffer[afx->buffer_pos + 5]] != 0xffffffffUL
                 && afx->buffer[afx->buffer_pos + 6] == '\n')
               {
                 afx->buffer_pos += 2;
@@ -862,27 +998,20 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
            checkcrc++;
            break;
        }
-       else if( (c = asctobin[(c2=c)]) == 255 ) {
-           log_error(_("invalid radix64 character %02X skipped\n"), c2);
+       else {
+           log_error(_("invalid radix64 character %02X skipped\n"), c);
            continue;
        }
-       switch(idx) {
-         case 0: val =  c << 2; break;
-         case 1: val |= (c>>4)&3; buf[n++]=val;val=(c<<4)&0xf0;break;
-         case 2: val |= (c>>2)&15; buf[n++]=val;val=(c<<6)&0xc0;break;
-         case 3: val |= c&0x3f; buf[n++] = val; break;
-       }
-       idx = (idx+1) % 4;
     }
 
-    for(i=0; i < n; i++ )
-       crc = (crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ buf[i]];
-    crc &= 0x00ffffff;
-    afx->crc = crc;
     afx->idx = idx;
     afx->radbuf[0] = val;
 
+    if( n )
+      gcry_md_write (afx->crc_md, buf, n);
+
     if( checkcrc ) {
+       gcry_md_final (afx->crc_md);
        afx->any_data = 1;
        afx->inp_checked=0;
        afx->faked = 0;
@@ -905,19 +1034,19 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
                continue;
            break;
        }
-       if( c == -1 )
+       if( !afx->buffer_len )
            log_error(_("premature eof (no CRC)\n"));
        else {
            u32 mycrc = 0;
            idx = 0;
            do {
-               if( (c = asctobin[c]) == 255 )
+               if( (binc = asctobin[0][c]) == 0xffffffffUL )
                    break;
                switch(idx) {
-                 case 0: val =  c << 2; break;
-                 case 1: val |= (c>>4)&3; mycrc |= val << 16;val=(c<<4)&0xf0;break;
-                 case 2: val |= (c>>2)&15; mycrc |= val << 8;val=(c<<6)&0xc0;break;
-                 case 3: val |= c&0x3f; mycrc |= val; break;
+                 case 0: val =  binc << 2; break;
+                 case 1: val |= (binc>>4)&3; mycrc |= val << 16;val=(binc<<4)&0xf0;break;
+                 case 2: val |= (binc>>2)&15; mycrc |= val << 8;val=(binc<<6)&0xc0;break;
+                 case 3: val |= binc&0x3f; mycrc |= val; break;
                }
                for(;;) {
                    if( afx->buffer_pos < afx->buffer_len )
@@ -939,7 +1068,7 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
                if( !afx->buffer_len )
                    break; /* eof */
            } while( ++idx < 4 );
-           if( c == -1 ) {
+           if( !afx->buffer_len ) {
                log_info(_("premature eof (in CRC)\n"));
                rc = invalid_crc();
            }
@@ -951,10 +1080,10 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
                log_info(_("malformed CRC\n"));
                rc = invalid_crc();
            }
-           else if( mycrc != afx->crc ) {
-                log_info (_("CRC error; %06lX - %06lX\n"),
-                                   (ulong)afx->crc, (ulong)mycrc);
-                rc = invalid_crc();
+           else if( mycrc != get_afx_crc (afx) ) {
+               log_info (_("CRC error; %06lX - %06lX\n"),
+                                   (ulong)get_afx_crc (afx), (ulong)mycrc);
+               rc = invalid_crc();
            }
            else {
                rc = 0;
@@ -991,6 +1120,121 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
     return rc;
 }
 
+static void
+armor_output_buf_as_radix64 (armor_filter_context_t *afx, IOBUF a,
+                            byte *buf, size_t size)
+{
+  byte radbuf[sizeof (afx->radbuf)];
+  byte outbuf[64 + sizeof (afx->eol)];
+  unsigned int eollen = strlen (afx->eol);
+  u32 in, in2;
+  int idx, idx2;
+  int i;
+
+  idx = afx->idx;
+  idx2 = afx->idx2;
+  memcpy (radbuf, afx->radbuf, sizeof (afx->radbuf));
+
+  if (size && (idx || idx2))
+    {
+      /* preload eol to outbuf buffer */
+      memcpy (outbuf + 4, afx->eol, sizeof (afx->eol));
+
+      for (; size && (idx || idx2); buf++, size--)
+       {
+         radbuf[idx++] = *buf;
+         if (idx > 2)
+           {
+             idx = 0;
+             in = (u32)radbuf[0] << (2 * 8);
+             in |= (u32)radbuf[1] << (1 * 8);
+             in |= (u32)radbuf[2] << (0 * 8);
+             outbuf[0] = bintoasc[(in >> 18) & 077];
+             outbuf[1] = bintoasc[(in >> 12) & 077];
+             outbuf[2] = bintoasc[(in >> 6) & 077];
+             outbuf[3] = bintoasc[(in >> 0) & 077];
+             if (++idx2 >= (64/4))
+               { /* pgp doesn't like 72 here */
+                 idx2=0;
+                 iobuf_write (a, outbuf, 4 + eollen);
+               }
+             else
+               {
+                 iobuf_write (a, outbuf, 4);
+               }
+           }
+       }
+    }
+
+  if (size >= (64/4)*3)
+    {
+      /* preload eol to outbuf buffer */
+      memcpy (outbuf + 64, afx->eol, sizeof(afx->eol));
+
+      do
+       {
+         /* idx and idx2 == 0 */
+
+         for (i = 0; i < (64/8); i++)
+           {
+             in = (u32)buf[0] << (2 * 8);
+             in |= (u32)buf[1] << (1 * 8);
+             in |= (u32)buf[2] << (0 * 8);
+             in2 = (u32)buf[3] << (2 * 8);
+             in2 |= (u32)buf[4] << (1 * 8);
+             in2 |= (u32)buf[5] << (0 * 8);
+             outbuf[i*8+0] = bintoasc[(in >> 18) & 077];
+             outbuf[i*8+1] = bintoasc[(in >> 12) & 077];
+             outbuf[i*8+2] = bintoasc[(in >> 6) & 077];
+             outbuf[i*8+3] = bintoasc[(in >> 0) & 077];
+             outbuf[i*8+4] = bintoasc[(in2 >> 18) & 077];
+             outbuf[i*8+5] = bintoasc[(in2 >> 12) & 077];
+             outbuf[i*8+6] = bintoasc[(in2 >> 6) & 077];
+             outbuf[i*8+7] = bintoasc[(in2 >> 0) & 077];
+             buf+=6;
+             size-=6;
+           }
+
+         /* pgp doesn't like 72 here */
+         iobuf_write (a, outbuf, 64 + eollen);
+       }
+      while (size >= (64/4)*3);
+
+      /* restore eol for tail handling */
+      if (size)
+       memcpy (outbuf + 4, afx->eol, sizeof (afx->eol));
+    }
+
+  for (; size; buf++, size--)
+    {
+      radbuf[idx++] = *buf;
+      if (idx > 2)
+       {
+         idx = 0;
+         in = (u32)radbuf[0] << (2 * 8);
+         in |= (u32)radbuf[1] << (1 * 8);
+         in |= (u32)radbuf[2] << (0 * 8);
+         outbuf[0] = bintoasc[(in >> 18) & 077];
+         outbuf[1] = bintoasc[(in >> 12) & 077];
+         outbuf[2] = bintoasc[(in >> 6) & 077];
+         outbuf[3] = bintoasc[(in >> 0) & 077];
+         if (++idx2 >= (64/4))
+           { /* pgp doesn't like 72 here */
+             idx2=0;
+             iobuf_write (a, outbuf, 4 + eollen);
+           }
+         else
+           {
+             iobuf_write (a, outbuf, 4);
+           }
+       }
+    }
+
+  memcpy (afx->radbuf, radbuf, sizeof (afx->radbuf));
+  afx->idx = idx;
+  afx->idx2 = idx2;
+}
+
 /****************
  * This filter is used to handle the armor stuff
  */
@@ -1000,7 +1244,7 @@ armor_filter( void *opaque, int control,
 {
     size_t size = *ret_len;
     armor_filter_context_t *afx = opaque;
-    int rc=0, i, c;
+    int rc=0, c;
     byte radbuf[3];
     int  idx, idx2;
     size_t n=0;
@@ -1019,17 +1263,20 @@ armor_filter( void *opaque, int control,
     if( control == IOBUFCTRL_UNDERFLOW && afx->inp_bypass ) {
        n = 0;
        if( afx->buffer_len ) {
+            /* Copy the data from AFX->BUFFER to BUF.  */
            for(; n < size && afx->buffer_pos < afx->buffer_len; n++ )
                buf[n++] = afx->buffer[afx->buffer_pos++];
            if( afx->buffer_pos >= afx->buffer_len )
                afx->buffer_len = 0;
        }
+        /* If there is still space in BUF, read directly into it.  */
        for(; n < size; n++ ) {
            if( (c=iobuf_get(a)) == -1 )
                break;
            buf[n] = c & 0xff;
        }
        if( !n )
+            /* We didn't get any data.  EOF.  */
            rc = -1;
        *ret_len = n;
     }
@@ -1179,43 +1426,13 @@ armor_filter( void *opaque, int control,
            afx->status++;
            afx->idx = 0;
            afx->idx2 = 0;
-           afx->crc = CRCINIT;
-
-       }
-       crc = afx->crc;
-       idx = afx->idx;
-       idx2 = afx->idx2;
-       for(i=0; i < idx; i++ )
-           radbuf[i] = afx->radbuf[i];
-
-       for(i=0; i < size; i++ )
-           crc = (crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ buf[i]];
-       crc &= 0x00ffffff;
-
-       for( ; size; buf++, size-- ) {
-           radbuf[idx++] = *buf;
-           if( idx > 2 ) {
-               idx = 0;
-               c = bintoasc[(*radbuf >> 2) & 077];
-               iobuf_put(a, c);
-               c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
-               iobuf_put(a, c);
-               c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
-               iobuf_put(a, c);
-               c = bintoasc[radbuf[2]&077];
-               iobuf_put(a, c);
-               if( ++idx2 >= (64/4) )
-                 { /* pgp doesn't like 72 here */
-                   iobuf_writestr(a,afx->eol);
-                   idx2=0;
-                 }
-           }
+           gcry_md_reset (afx->crc_md);
        }
-       for(i=0; i < idx; i++ )
-           afx->radbuf[i] = radbuf[i];
-       afx->idx = idx;
-       afx->idx2 = idx2;
-       afx->crc  = crc;
+
+       if( size ) {
+           gcry_md_write (afx->crc_md, buf, size);
+           armor_output_buf_as_radix64 (afx, a, buf, size);
+        }
     }
     else if( control == IOBUFCTRL_INIT )
       {
@@ -1241,7 +1458,8 @@ armor_filter( void *opaque, int control,
        if( afx->cancel )
            ;
        else if( afx->status ) { /* pad, write cecksum, and bottom line */
-           crc = afx->crc;
+           gcry_md_final (afx->crc_md);
+           crc = get_afx_crc (afx);
            idx = afx->idx;
            idx2 = afx->idx2;
            if( idx ) {
@@ -1284,7 +1502,7 @@ armor_filter( void *opaque, int control,
            c = bintoasc[radbuf[2]&077];
            iobuf_put(a, c);
            iobuf_writestr(a,afx->eol);
-           /* and the the trailer */
+           /* and the trailer */
            if( afx->what >= DIM(tail_strings) )
                log_bug("afx->what=%d", afx->what);
            iobuf_writestr(a, "-----");
@@ -1341,220 +1559,3 @@ make_radix64_string( const byte *data, size_t len )
     *p = 0;
     return buffer;
 }
-
-
-/***********************************************
- *  For the pipemode command we can't use the armor filter for various
- *  reasons, so we use this new unarmor_pump stuff to remove the armor
- */
-
-enum unarmor_state_e {
-    STA_init = 0,
-    STA_bypass,
-    STA_wait_newline,
-    STA_wait_dash,
-    STA_first_dash,
-    STA_compare_header,
-    STA_found_header_wait_newline,
-    STA_skip_header_lines,
-    STA_skip_header_lines_non_ws,
-    STA_read_data,
-    STA_wait_crc,
-    STA_read_crc,
-    STA_ready
-};
-
-struct unarmor_pump_s {
-    enum unarmor_state_e state;
-    byte val;
-    int checkcrc;
-    int pos;   /* counts from 0..3 */
-    u32 crc;
-    u32 mycrc; /* the one store in the data */
-};
-
-
-
-UnarmorPump
-unarmor_pump_new (void)
-{
-    UnarmorPump x;
-
-    if( !is_initialized )
-        initialize();
-    x = xmalloc_clear (sizeof *x);
-    return x;
-}
-
-void
-unarmor_pump_release (UnarmorPump x)
-{
-    xfree (x);
-}
-
-/*
- * Get the next character from the ascii armor taken from the IOBUF
- * created earlier by unarmor_pump_new().
- * Return:  c = Character
- *        256 = ignore this value
- *         -1 = End of current armor
- *         -2 = Premature EOF (not used)
- *         -3 = Invalid armor
- */
-int
-unarmor_pump (UnarmorPump x, int c)
-{
-    int rval = 256; /* default is to ignore the return value */
-
-    switch (x->state) {
-      case STA_init:
-        {
-            byte tmp[1];
-            tmp[0] = c;
-            if ( is_armored (tmp) )
-                x->state = c == '-'? STA_first_dash : STA_wait_newline;
-            else {
-                x->state = STA_bypass;
-                return c;
-            }
-        }
-        break;
-      case STA_bypass:
-        return c; /* return here to avoid crc calculation */
-      case STA_wait_newline:
-        if (c == '\n')
-            x->state = STA_wait_dash;
-        break;
-      case STA_wait_dash:
-        x->state = c == '-'? STA_first_dash : STA_wait_newline;
-        break;
-      case STA_first_dash: /* just need for initalization */
-        x->pos = 0;
-        x->state = STA_compare_header;
-      case STA_compare_header:
-        if ( "-----BEGIN PGP SIGNATURE-----"[++x->pos] == c ) {
-            if ( x->pos == 28 )
-                x->state = STA_found_header_wait_newline;
-        }
-        else
-            x->state = c == '\n'? STA_wait_dash : STA_wait_newline;
-        break;
-      case STA_found_header_wait_newline:
-        /* to make CR,LF issues easier we simply allow for white space
-           behind the 5 dashes */
-        if ( c == '\n' )
-            x->state = STA_skip_header_lines;
-        else if ( c != '\r' && c != ' ' && c != '\t' )
-            x->state = STA_wait_dash; /* garbage after the header line */
-        break;
-      case STA_skip_header_lines:
-        /* i.e. wait for one empty line */
-        if ( c == '\n' ) {
-            x->state = STA_read_data;
-            x->crc = CRCINIT;
-            x->val = 0;
-            x->pos = 0;
-        }
-        else if ( c != '\r' && c != ' ' && c != '\t' )
-            x->state = STA_skip_header_lines_non_ws;
-        break;
-      case STA_skip_header_lines_non_ws:
-        /* like above but we already encountered non white space */
-        if ( c == '\n' )
-            x->state = STA_skip_header_lines;
-        break;
-      case STA_read_data:
-        /* fixme: we don't check for the trailing dash lines but rely
-         * on the armor stop characters */
-        if( c == '\n' || c == ' ' || c == '\r' || c == '\t' )
-            break; /* skip all kind of white space */
-
-        if( c == '=' ) { /* pad character: stop */
-            if( x->pos == 1 ) /* in this case val has some value */
-                rval = x->val;
-            x->state = STA_wait_crc;
-            break;
-        }
-
-        {
-            int c2;
-            if( (c = asctobin[(c2=c)]) == 255 ) {
-                log_error(_("invalid radix64 character %02X skipped\n"), c2);
-                break;
-            }
-        }
-
-        switch(x->pos) {
-          case 0:
-            x->val = c << 2;
-            break;
-          case 1:
-            x->val |= (c>>4)&3;
-            rval = x->val;
-            x->val = (c<<4)&0xf0;
-            break;
-          case 2:
-            x->val |= (c>>2)&15;
-            rval = x->val;
-            x->val = (c<<6)&0xc0;
-            break;
-          case 3:
-            x->val |= c&0x3f;
-            rval = x->val;
-            break;
-        }
-        x->pos = (x->pos+1) % 4;
-        break;
-      case STA_wait_crc:
-        if( c == '\n' || c == ' ' || c == '\r' || c == '\t' || c == '=' )
-            break; /* skip ws and pad characters */
-        /* assume that we are at the next line */
-        x->state = STA_read_crc;
-        x->pos = 0;
-        x->mycrc = 0;
-      case STA_read_crc:
-        if( (c = asctobin[c]) == 255 ) {
-            rval = -1; /* ready */
-            if( x->crc != x->mycrc ) {
-                log_info (_("CRC error; %06lX - %06lX\n"),
-                          (ulong)x->crc, (ulong)x->mycrc);
-                if ( invalid_crc() )
-                    rval = -3;
-            }
-            x->state = STA_ready; /* not sure whether this is correct */
-            break;
-        }
-
-        switch(x->pos) {
-          case 0:
-            x->val = c << 2;
-            break;
-          case 1:
-            x->val |= (c>>4)&3;
-            x->mycrc |= x->val << 16;
-            x->val = (c<<4)&0xf0;
-            break;
-          case 2:
-            x->val |= (c>>2)&15;
-            x->mycrc |= x->val << 8;
-            x->val = (c<<6)&0xc0;
-            break;
-          case 3:
-            x->val |= c&0x3f;
-            x->mycrc |= x->val;
-            break;
-        }
-        x->pos = (x->pos+1) % 4;
-        break;
-      case STA_ready:
-        rval = -1;
-        break;
-    }
-
-    if ( !(rval & ~255) ) { /* compute the CRC */
-        x->crc = (x->crc << 8) ^ crc_table[((x->crc >> 16)&0xff) ^ rval];
-        x->crc &= 0x00ffffff;
-    }
-
-    return rval;
-}