]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Update.
authorSimon Josefsson <simon@josefsson.org>
Sat, 12 May 2007 13:18:45 +0000 (13:18 +0000)
committerSimon Josefsson <simon@josefsson.org>
Sat, 12 May 2007 13:18:45 +0000 (13:18 +0000)
20 files changed:
lgl/m4/vasnprintf.m4
lgl/vasnprintf.c
libextra/opencdk/armor.c
libextra/opencdk/cipher.c
libextra/opencdk/compress.c
libextra/opencdk/context.h
libextra/opencdk/filters.h
libextra/opencdk/kbnode.c
libextra/opencdk/keydb.c
libextra/opencdk/literal.c
libextra/opencdk/main.c
libextra/opencdk/main.h
libextra/opencdk/misc.c
libextra/opencdk/opencdk.h
libextra/opencdk/pubkey.c
libextra/opencdk/read-packet.c
libextra/opencdk/sig-check.c
libextra/opencdk/stream.c
libextra/opencdk/verify.c
libextra/opencdk/write-packet.c

index 79886e75f4ac0c26214fbebc349c62cb619b849a..41a5ce1800bdfd911bc3924b4201d8e603a813e4 100644 (file)
@@ -1,4 +1,4 @@
-# vasnprintf.m4 serial 13
+# vasnprintf.m4 serial 15
 dnl Copyright (C) 2002-2004, 2006-2007 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -90,6 +90,36 @@ AC_DEFUN([gl_PREREQ_VASNPRINTF_DIRECTIVE_F],
   esac
 ])
 
+# Extra prerequisites of lib/vasnprintf.c for supporting the ' flag.
+AC_DEFUN([gl_PREREQ_VASNPRINTF_FLAG_GROUPING],
+[
+  AC_REQUIRE([gl_PRINTF_FLAG_GROUPING])
+  case "$gl_cv_func_printf_flag_grouping" in
+    *yes)
+      ;;
+    *)
+      AC_DEFINE([NEED_PRINTF_FLAG_GROUPING], 1,
+        [Define if the vasnprintf implementation needs special code for the
+         ' flag.])
+      ;;
+  esac
+])
+
+# Extra prerequisites of lib/vasnprintf.c for supporting the 0 flag.
+AC_DEFUN([gl_PREREQ_VASNPRINTF_FLAG_ZERO],
+[
+  AC_REQUIRE([gl_PRINTF_FLAG_ZERO])
+  case "$gl_cv_func_printf_flag_zero" in
+    *yes)
+      ;;
+    *)
+      AC_DEFINE([NEED_PRINTF_FLAG_ZERO], 1,
+        [Define if the vasnprintf implementation needs special code for the
+         0 flag.])
+      ;;
+  esac
+])
+
 # Prerequisites of lib/asnprintf.c.
 AC_DEFUN([gl_PREREQ_ASNPRINTF],
 [
index f30f29f368aa3ceaba7553c9b4746df2024682c4..aa26280c9256ca8217b0adf44fe3f905ff55d34c 100644 (file)
@@ -756,42 +756,65 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar
            else
              {
                arg_type type = a.arg[dp->arg_index].type;
-               CHAR_T *p;
+               int flags = dp->flags;
+#if !USE_SNPRINTF || NEED_PRINTF_FLAG_ZERO
+               int has_width;
+               size_t width;
+#endif
+#if NEED_PRINTF_FLAG_ZERO
+               int pad_ourselves;
+#else
+#              define pad_ourselves 0
+#endif
+               CHAR_T *fbp;
                unsigned int prefix_count;
                int prefixes[2];
 #if !USE_SNPRINTF
                size_t tmp_length;
                CHAR_T tmpbuf[700];
                CHAR_T *tmp;
+#endif
+
+#if !USE_SNPRINTF || NEED_PRINTF_FLAG_ZERO
+               has_width = 0;
+               width = 0;
+               if (dp->width_start != dp->width_end)
+                 {
+                   if (dp->width_arg_index != ARG_NONE)
+                     {
+                       int arg;
+
+                       if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
+                         abort ();
+                       arg = a.arg[dp->width_arg_index].a.a_int;
+                       if (arg < 0)
+                         {
+                           /* "A negative field width is taken as a '-' flag
+                               followed by a positive field width."  */
+                           flags |= FLAG_LEFT;
+                           width = (unsigned int) (-arg);
+                         }
+                       else
+                         width = arg;
+                     }
+                   else
+                     {
+                       const CHAR_T *digitp = dp->width_start;
+
+                       do
+                         width = xsum (xtimes (width, 10), *digitp++ - '0');
+                       while (digitp != dp->width_end);
+                     }
+                   has_width = 1;
+                 }
+#endif
 
+#if !USE_SNPRINTF
                /* Allocate a temporary buffer of sufficient size for calling
                   sprintf.  */
                {
-                 size_t width;
                  size_t precision;
 
-                 width = 0;
-                 if (dp->width_start != dp->width_end)
-                   {
-                     if (dp->width_arg_index != ARG_NONE)
-                       {
-                         int arg;
-
-                         if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
-                           abort ();
-                         arg = a.arg[dp->width_arg_index].a.a_int;
-                         width = (arg < 0 ? (unsigned int) (-arg) : arg);
-                       }
-                     else
-                       {
-                         const CHAR_T *digitp = dp->width_start;
-
-                         do
-                           width = xsum (xtimes (width, 10), *digitp++ - '0');
-                         while (digitp != dp->width_end);
-                       }
-                   }
-
                  precision = 6;
                  if (dp->precision_start != dp->precision_end)
                    {
@@ -1008,33 +1031,56 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar
                  }
 #endif
 
+               /* Decide whether to perform the padding ourselves.  */
+#if NEED_PRINTF_FLAG_ZERO
+               switch (dp->conversion)
+                 {
+                 case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
+                 case 'a': case 'A':
+                   pad_ourselves = 1;
+                   break;
+                 default:
+                   pad_ourselves = 0;
+                   break;
+                 }
+#endif
+
                /* Construct the format string for calling snprintf or
                   sprintf.  */
-               p = buf;
-               *p++ = '%';
-               if (dp->flags & FLAG_GROUP)
-                 *p++ = '\'';
-               if (dp->flags & FLAG_LEFT)
-                 *p++ = '-';
-               if (dp->flags & FLAG_SHOWSIGN)
-                 *p++ = '+';
-               if (dp->flags & FLAG_SPACE)
-                 *p++ = ' ';
-               if (dp->flags & FLAG_ALT)
-                 *p++ = '#';
-               if (dp->flags & FLAG_ZERO)
-                 *p++ = '0';
-               if (dp->width_start != dp->width_end)
+               fbp = buf;
+               *fbp++ = '%';
+#if NEED_PRINTF_FLAG_GROUPING
+               /* The underlying implementation doesn't support the ' flag.
+                  Produce no grouping characters in this case; this is
+                  acceptable because the grouping is locale dependent.  */
+#else
+               if (flags & FLAG_GROUP)
+                 *fbp++ = '\'';
+#endif
+               if (flags & FLAG_LEFT)
+                 *fbp++ = '-';
+               if (flags & FLAG_SHOWSIGN)
+                 *fbp++ = '+';
+               if (flags & FLAG_SPACE)
+                 *fbp++ = ' ';
+               if (flags & FLAG_ALT)
+                 *fbp++ = '#';
+               if (!pad_ourselves)
                  {
-                   size_t n = dp->width_end - dp->width_start;
-                   memcpy (p, dp->width_start, n * sizeof (CHAR_T));
-                   p += n;
+                   if (flags & FLAG_ZERO)
+                     *fbp++ = '0';
+                   if (dp->width_start != dp->width_end)
+                     {
+                       size_t n = dp->width_end - dp->width_start;
+                       memcpy (fbp, dp->width_start, n * sizeof (CHAR_T));
+                       fbp += n;
+                     }
                  }
                if (dp->precision_start != dp->precision_end)
                  {
                    size_t n = dp->precision_end - dp->precision_start;
-                   memcpy (p, dp->precision_start, n * sizeof (CHAR_T));
-                   p += n;
+                   memcpy (fbp, dp->precision_start, n * sizeof (CHAR_T));
+                   fbp += n;
                  }
 
                switch (type)
@@ -1042,7 +1088,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar
 #if HAVE_LONG_LONG_INT
                  case TYPE_LONGLONGINT:
                  case TYPE_ULONGLONGINT:
-                   *p++ = 'l';
+                   *fbp++ = 'l';
                    /*FALLTHROUGH*/
 #endif
                  case TYPE_LONGINT:
@@ -1053,31 +1099,31 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar
 #if HAVE_WCHAR_T
                  case TYPE_WIDE_STRING:
 #endif
-                   *p++ = 'l';
+                   *fbp++ = 'l';
                    break;
                  case TYPE_LONGDOUBLE:
-                   *p++ = 'L';
+                   *fbp++ = 'L';
                    break;
                  default:
                    break;
                  }
 #if NEED_PRINTF_DIRECTIVE_F
                if (dp->conversion == 'F')
-                 *p = 'f';
+                 *fbp = 'f';
                else
 #endif
-                 *p = dp->conversion;
+                 *fbp = dp->conversion;
 #if USE_SNPRINTF
-               p[1] = '%';
-               p[2] = 'n';
-               p[3] = '\0';
+               fbp[1] = '%';
+               fbp[2] = 'n';
+               fbp[3] = '\0';
 #else
-               p[1] = '\0';
+               fbp[1] = '\0';
 #endif
 
                /* Construct the arguments for calling snprintf or sprintf.  */
                prefix_count = 0;
-               if (dp->width_arg_index != ARG_NONE)
+               if (!pad_ourselves && dp->width_arg_index != ARG_NONE)
                  {
                    if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
                      abort ();
@@ -1282,11 +1328,11 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar
                      {
                        /* snprintf() doesn't understand the '%n'
                           directive.  */
-                       if (p[1] != '\0')
+                       if (fbp[1] != '\0')
                          {
                            /* Don't use the '%n' directive; instead, look
                               at the snprintf() return value.  */
-                           p[1] = '\0';
+                           fbp[1] = '\0';
                            continue;
                          }
                        else
@@ -1322,6 +1368,77 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar
                        return NULL;
                      }
 
+                   /* Perform padding.  */
+#if NEED_PRINTF_FLAG_ZERO
+                   if (pad_ourselves && has_width && count < width)
+                     {
+# if USE_SNPRINTF
+                       /* Make room for the result.  */
+                       if (width >= maxlen)
+                         {
+                           /* Need at least width bytes.  But allocate
+                              proportionally, to avoid looping eternally if
+                              snprintf() reports a too small count.  */
+                           size_t n =
+                             xmax (xsum (length, width),
+                                   xtimes (allocated, 2));
+
+                           length += count;
+                           ENSURE_ALLOCATION (n);
+                           length -= count;
+                           maxlen = allocated - length; /* >= width */
+                         }
+# endif
+                       {
+# if USE_SNPRINTF
+                         CHAR_T * const rp = result + length;
+# else
+                         CHAR_T * const rp = tmp;
+# endif
+                         CHAR_T *p = rp + count;
+                         size_t pad = width - count;
+                         CHAR_T *end = p + pad;
+                         CHAR_T *pad_ptr = (*rp == '-' ? rp + 1 : rp);
+                         /* No zero-padding of "inf" and "nan".  */
+                         if ((*pad_ptr >= 'A' && *pad_ptr <= 'Z')
+                             || (*pad_ptr >= 'a' && *pad_ptr <= 'z'))
+                           pad_ptr = NULL;
+                         /* The generated string now extends from rp to p,
+                            with the zero padding insertion point being at
+                            pad_ptr.  */
+
+                         if (flags & FLAG_LEFT)
+                           {
+                             /* Pad with spaces on the right.  */
+                             for (; pad > 0; pad--)
+                               *p++ = ' ';
+                           }
+                         else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
+                           {
+                             /* Pad with zeroes.  */
+                             CHAR_T *q = end;
+
+                             while (p > pad_ptr)
+                               *--q = *--p;
+                             for (; pad > 0; pad--)
+                               *p++ = '0';
+                           }
+                         else
+                           {
+                             /* Pad with spaces on the left.  */
+                             CHAR_T *q = end;
+
+                             while (p > rp)
+                               *--q = *--p;
+                             for (; pad > 0; pad--)
+                               *p++ = ' ';
+                           }
+
+                         count = width; /* = count + pad = end - rp */
+                       }
+                     }
+#endif
+
 #if !USE_SNPRINTF
                    if (count >= tmp_length)
                      /* tmp_length was incorrectly calculated - fix the
index 48164f2e77018a8e3b37a0beb75397c691b2f3bd..07d3b39134cbbca799daae94d7b17afc13487b5f 100644 (file)
@@ -659,6 +659,8 @@ cdk_armor_encode_buffer (const byte *inbuf, size_t inlen,
   char tempout[128];
   size_t pos, off, len, rest;
   
+  if (!inbuf || !nwritten)
+    return CDK_Inv_Value;
   if (type > CDK_ARMOR_SIGNATURE)
     return CDK_Inv_Mode;
   
@@ -706,6 +708,8 @@ cdk_armor_encode_buffer (const byte *inbuf, size_t inlen,
       memcpy (outbuf+pos, tempout, strlen (tempout)); pos += strlen (tempout);
       memcpy (outbuf+pos, le, strlen (le)); pos += strlen (le);
     }
+  
+  /* FIXME: We do not generate a CRC for the data, which is legal. */
   memcpy (outbuf+pos, "-----", 5); pos += 5;
   memcpy (outbuf+pos, tail, strlen (tail)); pos += strlen (tail);
   memcpy (outbuf+pos, "-----", 5); pos += 5;
index 90ddce6d843ac58cfd20cd084ff8c87bd2b6816a..3fb7f94e55d5fc9927600c4a410d0a965fa2d4d1 100644 (file)
 #include "filters.h"
 
 
-/* FIXME: We cannot use a static progress callback because the library
-          might be MT. We need a progress cb per context. */
-
-
 static off_t
 fp_get_length (FILE *fp)
 {
   struct stat statbuf;
     
-  if (fstatfileno (fp), &statbuf))
+  if (fstat (fileno (fp), &statbuf))
     return (off_t)-1;
   return statbuf.st_size;
 }
@@ -52,7 +48,7 @@ hash_encode (void *opaque, FILE *in, FILE *out)
   if (!mfx)
     return CDK_Inv_Value;
   
-  _cdk_log_debug( "hash filter: encode (algo=%d)\n", mfx->digest_algo );
+  _cdk_log_debug ("hash filter: encode (algo=%d)\n", mfx->digest_algo);
   
   if (!mfx->md)
     {
@@ -106,13 +102,15 @@ write_header (cipher_filter_t *cfx, FILE *out)
   cdk_error_t rc = 0;
   gcry_error_t err;
   
-  blocksize = gcry_cipher_get_algo_blklen( dek->algo );
+  blocksize = gcry_cipher_get_algo_blklen (dek->algo);
   if (blocksize < 8 || blocksize > 16)
     return CDK_Inv_Algo;
   
+  /* It might be possible the receiver does not understand the MDC
+     output and thus we offer to supress the MDC packet. */
   use_mdc = dek->use_mdc;
-  if (blocksize != 8)
-    use_mdc = 1; /* Enabled by default for all 128-bit block cipher */
+  if (blocksize == 8)
+    use_mdc = 0; /* Enabled by default for all 128-bit block cipher */
   
   if (use_mdc && cfx->datalen)
     cfx->datalen += 22;
@@ -125,7 +123,7 @@ write_header (cipher_filter_t *cfx, FILE *out)
       ed->extralen = blocksize + 2;
     }
   else
-    cfx->blkmode.nleft = BUFSIZE;
+    cfx->blkmode.nleft = DEF_BLOCKSIZE;
   
   if (use_mdc)
     {
@@ -135,7 +133,12 @@ write_header (cipher_filter_t *cfx, FILE *out)
        return map_gcry_error (err);
     }
   
-  pkt->old_ctb = cfx->dek->rfc1991 && !cfx->blkmode.on? 1 : 0;
+  /* When we use partial bodies, the MDC feature or a blocksize
+     larger than 8, we force the use of the new packet format. */
+  if (cfx->blkmode.on || use_mdc || blocksize != 8)
+    pkt->old_ctb = 0;
+  else
+    pkt->old_ctb = 1;
   pkt->pkttype = use_mdc? CDK_PKT_ENCRYPTED_MDC : CDK_PKT_ENCRYPTED;
   rc = _cdk_pkt_write_fp (out, pkt);
   cdk_pkt_release (pkt);
@@ -163,9 +166,9 @@ write_header (cipher_filter_t *cfx, FILE *out)
   fwrite (temp, 1, nprefix+2, out);
   if (cfx->blkmode.on) 
     {
-      cfx->blkmode.nleft -= (blocksize+2);
+      cfx->blkmode.nleft -= (nprefix+2);
       if (use_mdc)
-       cfx->blkmode.nleft -= (22+1); /* 22 mdc packet, 1 byte version */
+       cfx->blkmode.nleft--; /* 1 byte version */
     }
   return rc;
 }
@@ -183,7 +186,7 @@ write_mdc_packet (FILE *out, cipher_filter_t *cfx)
     return CDK_Inv_Algo;
   
   /* We must hash the prefix of the MDC packet here */
-  pktdata[0] = 0xd3;
+  pktdata[0] = 0xD3;
   pktdata[1] = 0x14;
   gcry_md_write (cfx->mdc, pktdata, 2);
   gcry_md_final (cfx->mdc);
@@ -200,87 +203,91 @@ num2bits (size_t n)
 {
   size_t i;
   
-  if (!n)
-    return -1;
   for (i = 0; n > 1; i++)
     n >>= 1;
   return i;
 }
 
 
-static __inline__ size_t
-pow2 (size_t y)
-{
-  size_t x = 1, i;
-  for (i = 0; i < y; i++)
-    x <<= 1;
-  return x; 
-}
-
-
 static cdk_error_t
 write_partial_block (FILE *in, FILE *out, off_t *r_len,
-                     cipher_filter_t *cfx )
+                     cipher_filter_t *cfx)
 {
-    byte buf[BUFSIZE+1];
-    size_t n;
-    int nread;
-    cdk_error_t rc;
-
-    if( !out || !cfx )
-        return CDK_Inv_Value;
+  byte buf[DEF_BLOCKSIZE];
+  size_t n;
+  int nread;
+  gcry_error_t err;
+  
+  if (!out || !cfx)
+    return CDK_Inv_Value;
 
-    if( !cfx->blkmode.nleft ) {
-        if( *r_len > BUFSIZE ) {
-            fputc( (0xE0|DEF_BLOCKBITS), out );
-            cfx->blkmode.nleft = BUFSIZE;
-            (*r_len) -= BUFSIZE;
-        }
-        else if( *r_len > 512 ) {
-            n = num2bits( *r_len );
-            cfx->blkmode.nleft = pow2( n );
-            fputc( (0xE0|n), out );
-            (*r_len) -= cfx->blkmode.nleft ;
+  if (!cfx->blkmode.nleft && *r_len > 0)
+    {
+      if (*r_len > DEF_BLOCKSIZE)
+       {
+         /*_cdk_log_debug ("write_partial_block: size %lu block %d\n",
+                         *r_len, DEF_BLOCKSIZE);*/
+         fputc ((0xE0|DEF_BLOCKBITS), out);
+         cfx->blkmode.nleft = DEF_BLOCKSIZE;
+         (*r_len) -= DEF_BLOCKSIZE;
+       }
+      else if (*r_len > 512)
+       {
+         n = num2bits (*r_len);
+         cfx->blkmode.nleft = (1 << n);
+         /*_cdk_log_debug ("write_partial_block: size %lu bits %d block %d\n",
+                         *r_len, n, (1<<n));*/
+         fputc ((0xE0|n), out);
+         (*r_len) -= cfx->blkmode.nleft;
         }
-        else {
-            size_t pktlen = *r_len;
-            if( pktlen < 192 )
-                fputc( pktlen, out );
-            else if( pktlen < 8384 ) {
-                pktlen -= 192;
-                fputc( (pktlen/256) + 192, out );
-                fputc( (pktlen % 256), out );
-            }
-            cfx->blkmode.nleft = pktlen;
-            (*r_len) -= pktlen;
+      else 
+       {
+         size_t pktlen = *r_len;
+         
+         /* If we use the MDC mode, we need to increase the final
+            partial body length to hold the mdc packet itself. */
+         if (cfx->mdc)
+           pktlen += 22;
+
+         if (pktlen < 192)
+           fputc (pktlen, out);
+         else if (pktlen < 8384)
+           {
+             pktlen -= 192;
+             fputc ((pktlen/256) + 192, out);
+             fputc ((pktlen % 256), out);
+           }
+         cfx->blkmode.nleft = pktlen;
+         /*_cdk_log_debug ("write_partial_block: end %d block\n", pktlen);*/
+         (*r_len) -= pktlen;     
         }
     }
-    else
-        (*r_len) -= cfx->blkmode.nleft;
-
-    n = cfx->blkmode.nleft < DIM (buf)? cfx->blkmode.nleft : DIM (buf);
-    nread = fread( buf, 1, n, in );
-    if( !nread )
-        return CDK_EOF;
-    if( cfx->mdc )
-        gcry_md_write( cfx->mdc, buf, nread );
-    rc = gcry_cipher_encrypt (cfx->hd, buf, nread, NULL, 0);
-    if( !rc ) {
-        fwrite( buf, 1, nread, out );
-        cfx->blkmode.nleft -= nread;
-    }
-    return rc;
+  else
+    (*r_len) -= cfx->blkmode.nleft;
+  
+  n = cfx->blkmode.nleft < DIM (buf)? cfx->blkmode.nleft : DIM (buf);
+  nread = fread (buf, 1, n, in);
+  if (!nread)
+    return CDK_EOF;
+  if (cfx->mdc)
+    gcry_md_write (cfx->mdc, buf, nread);
+  err = gcry_cipher_encrypt (cfx->hd, buf, nread, NULL, 0);
+  if (err)
+    return map_gcry_error (err);
+  fwrite (buf, 1, nread, out);
+  cfx->blkmode.nleft -= nread;
+  return 0;
 }
 
 
 static cdk_error_t
-cipher_encode_file( void * opaque, FILE * in, FILE * out )
+cipher_encode_file (void *opaque, FILE *in, FILE *out)
 {
-  cipher_filter_t * cfx = opaque;
+  cipher_filter_t *cfx = opaque;
   byte buf[BUFSIZE];
   off_t len, len2;
   int nread;
-  cdk_error_t rc = 0;
+  cdk_error_t rc;
 
   if (!cfx || !in || !out)
     return CDK_Inv_Value;
@@ -293,8 +300,13 @@ cipher_encode_file( void * opaque, FILE * in, FILE * out )
       if (cfx->blkmode.on)
        {
          rc = write_partial_block (in, out, &len2, cfx);
-         if (rc)
+         if (rc == CDK_EOF)
            break;
+         if (rc)
+           {
+             wipemem (buf, sizeof (buf));
+             return rc;
+           }     
          continue;
         }
       nread = fread (buf, 1, DIM (buf), in);
@@ -305,12 +317,12 @@ cipher_encode_file( void * opaque, FILE * in, FILE * out )
       gcry_cipher_encrypt (cfx->hd, buf, nread, NULL, 0);
       fwrite (buf, 1, nread, out);
     }
+  if (cfx->mdc)
+    rc = write_mdc_packet (out, cfx);
+  else
+    rc = 0;
+  
   wipemem (buf, sizeof (buf));
-  if (!rc) 
-    {
-      if (cfx->mdc)
-       rc = write_mdc_packet (out, cfx);
-    }
   return rc;
 }
 
@@ -367,10 +379,7 @@ read_header (cipher_filter_t * cfx, FILE * in)
   if (cfx->mdc)
     gcry_md_write (cfx->mdc, temp, nprefix + 2);
   if (cfx->blkmode.on)
-    {
-      cfx->blkmode.size -= (nprefix + 2);
-      /* FIXME: to sub the MDC packet len (23) here seems to be wrong. */
-    }
+    cfx->blkmode.size -= (nprefix + 2);
   return 0;
 }
 
@@ -456,7 +465,7 @@ cipher_decode( void * opaque, FILE * in, FILE * out )
     cipher_filter_t * cfx = opaque;
     cdk_error_t rc;
 
-    _cdk_log_debug( "cipher filter: decode\n" );
+    _cdk_log_debug ("cipher filter: decode\n");
   
     if( !cfx || !in || !out )
         return CDK_Inv_Value;
@@ -469,23 +478,23 @@ cipher_decode( void * opaque, FILE * in, FILE * out )
     
 
 static cdk_error_t
-cipher_encode( void * opaque, FILE * in, FILE * out )
+cipher_encode (void *opaque, FILE *in, FILE *out)
 {
-    cipher_filter_t * cfx = opaque;
-    cdk_error_t rc;
-
-    _cdk_log_debug( "cipher filter: encode\n" );
+  cipher_filter_t * cfx = opaque;
+  cdk_error_t rc;
   
-    if( !cfx || !in || !out )
-        return CDK_Inv_Value;
-
-    cfx->datalen = fp_get_length (in);
-    if (cfx->datalen < BUFSIZE && cfx->blkmode.on)
-        cfx->blkmode.on = 0;
-    rc = write_header (cfx, out);
-    if( !rc )
-        rc = cipher_encode_file (cfx, in, out);
-    return rc;
+  _cdk_log_debug ("cipher filter: encode\n");
+  
+  if (!cfx || !in || !out)
+    return CDK_Inv_Value;
+  
+  cfx->datalen = fp_get_length (in);
+  if (cfx->datalen < BUFSIZE && cfx->blkmode.on)
+    cfx->blkmode.on = 0;
+  rc = write_header (cfx, out);
+  if (!rc)
+    rc = cipher_encode_file (cfx, in, out);
+  return rc;
 }
 
 
index 91d605830cebecf5923a286e7cfaca9deb3ddc5b..b67bffdd435a8db41d2306171d759ea00d7fcdce 100644 (file)
 static int
 compress_data (z_stream *zs, int flush, byte *inbuf, size_t insize, FILE *out)
 {
-    int nbytes, zrc;
-    byte buf[4096];
+  int nbytes, zrc;
+  byte buf[4096];
   
-    zs->next_in = inbuf;
-    zs->avail_in = insize;
-
-    do {
-        zs->next_out = buf;
-        zs->avail_out = DIM (buf);
+  zs->next_in = inbuf;
+  zs->avail_in = insize;
+  
+  do 
+    {    
+      zs->next_out = buf;
+      zs->avail_out = DIM (buf);
       
-        zrc = deflate (zs, flush);
-        if (zrc == Z_STREAM_END && flush == Z_FINISH)
-            ;
-        else if (zrc != Z_OK)
-            break;
-        nbytes = DIM (buf) - zs->avail_out;
-        fwrite (buf, 1, nbytes, out);
+      zrc = deflate (zs, flush);
+      if (zrc == Z_STREAM_END && flush == Z_FINISH)
+       ;
+      else if (zrc != Z_OK)
+       break;
+      nbytes = DIM (buf) - zs->avail_out;
+      fwrite (buf, 1, nbytes, out);
     }
-    while (zs->avail_out == 0 || (flush == Z_FINISH && zrc != Z_STREAM_END));
-    return zrc;
+  while (zs->avail_out == 0 || (flush == Z_FINISH && zrc != Z_STREAM_END));
+  return zrc;
 }
 
 
@@ -58,169 +59,180 @@ static int
 decompress_data (compress_filter_t *zfx, z_stream *zs, 
                 FILE *in, size_t *ret_len)
 {
-    int nread, nold;
-    int rc, zrc;
-
-    rc = 0;
-    nread = 0;
-    while (zs->avail_out != 0) {
-        if (!zs->avail_in) {
-            nread = fread (zfx->inbuf, 1, zfx->inbufsize, in);
-            zs->next_in = zfx->inbuf;
-            zs->avail_in = nread;
+  int nread, nold;
+  int rc, zrc;
+  
+  rc = 0;
+  nread = 0;
+  while (zs->avail_out != 0) 
+    {
+      if (!zs->avail_in) 
+       {      
+         nread = fread (zfx->inbuf, 1, zfx->inbufsize, in);
+         zs->next_in = zfx->inbuf;
+         zs->avail_in = nread;
         }
-        nold = zs->avail_out;
-        zrc = inflate (zs, Z_SYNC_FLUSH);
-        if (zrc != Z_OK && zrc != Z_STREAM_END) {
-            rc = CDK_Zlib_Error;
-            break;
+      nold = zs->avail_out;
+      zrc = inflate (zs, Z_SYNC_FLUSH);
+      if (zrc != Z_OK && zrc != Z_STREAM_END) 
+       {
+         rc = CDK_Zlib_Error;
+         break;
         }
-        *ret_len = zfx->outbufsize - zs->avail_out;
-        if (nold == zs->avail_out)
-            break;
-        if (zrc == Z_STREAM_END) {
-            rc = EOF; /* eof */
-            break;
+      *ret_len = zfx->outbufsize - zs->avail_out;
+      if (nold == zs->avail_out)
+       break;
+      if (zrc == Z_STREAM_END) 
+       {
+         rc = EOF; /* eof */
+         break;
         }
     }
-    if (!nread && feof (in))
-        rc = -1;
-    return rc;
+  if (!nread && feof (in))
+    rc = -1;
+  return rc;
 }
 
 
 static cdk_error_t
 compress_decode (void *opaque, FILE *in, FILE *out)
 {
-    compress_filter_t *zfx = opaque;
-    z_stream * zs;
-    size_t nbytes;
-    int zrc;
-    cdk_error_t rc = 0;
-
-    _cdk_log_debug ("compress filter: decode (algo=%d)\n", zfx->algo);
+  compress_filter_t *zfx = opaque;
+  z_stream * zs;
+  size_t nbytes;
+  int zrc;
+  cdk_error_t rc = 0;
   
-    if (!zfx || !in || !out)
-        return CDK_Inv_Value;
+  _cdk_log_debug ("compress filter: decode (algo=%d)\n", zfx->algo);
   
-    zs = cdk_calloc (1, sizeof *zs);
-    if (!zs)
-        return CDK_Out_Of_Core;
-    if (zfx->algo == CDK_COMPRESS_ZIP)
-        zrc = inflateInit2 (zs, -13);
-    else
-        zrc = inflateInit (zs);
-    if (zrc != Z_OK)
-        return CDK_Zlib_Error;
-
-    zfx->outbufsize = 8192;
-    zfx->inbufsize = 2048;
-    memset (zfx->inbuf, 0, sizeof zfx->inbuf);
-    zs->avail_in = 0;
-
-    nbytes = 0;
-    while (rc != -1) {
-        zs->next_out = zfx->outbuf;
-        zs->avail_out = 8192;
-        rc = decompress_data (zfx, zs, in, &nbytes);
-        fwrite (zfx->outbuf, 1, nbytes, out);
+  if (!zfx || !in || !out)
+    return CDK_Inv_Value;
+  
+  zs = cdk_calloc (1, sizeof *zs);
+  if (!zs)
+    return CDK_Out_Of_Core;
+  if (zfx->algo == CDK_COMPRESS_ZIP)
+    zrc = inflateInit2 (zs, -13);
+  else
+    zrc = inflateInit (zs);
+  if (zrc != Z_OK)
+    return CDK_Zlib_Error;
+  
+  zfx->outbufsize = 8192;
+  zfx->inbufsize = 2048;
+  memset (zfx->inbuf, 0, sizeof zfx->inbuf);
+  zs->avail_in = 0;
+  
+  nbytes = 0;
+  while (rc != -1) 
+    {
+      zs->next_out = zfx->outbuf;
+      zs->avail_out = 8192;
+      rc = decompress_data (zfx, zs, in, &nbytes);
+      fwrite (zfx->outbuf, 1, nbytes, out);
     }
-    inflateEnd (zs);
-    cdk_free (zs);
-    if (rc == CDK_EOF)
-        rc = 0;
-    return rc;
+  inflateEnd (zs);
+  cdk_free (zs);
+  if (rc == CDK_EOF)
+    rc = 0;
+  return rc;
 }
 
 
 static cdk_error_t
 compress_encode(void *opaque, FILE *in, FILE *out)
 {
-    compress_filter_t *zfx = opaque;
-    z_stream *zs;
-    struct cdk_pkt_compressed_s cd;
-    struct cdk_packet_s pkt;
-    int zrc, nread;
-    cdk_error_t rc = 0;
-
-    _cdk_log_debug ("compress filter: encode\n");
+  compress_filter_t *zfx = opaque;
+  z_stream *zs;
+  struct cdk_pkt_compressed_s cd;
+  struct cdk_packet_s pkt;
+  int zrc, nread;
+  cdk_error_t rc;
   
-    if (!zfx || !in || !out)
-        return CDK_Inv_Value;
-
-    if (!zfx->algo)
-        zfx->algo = CDK_COMPRESS_ZIP;
-
-    memset (&cd, 0, sizeof (cd));
-    cd.len = 0;
-    cd.algorithm = zfx->algo;
-    pkt.pkttype = CDK_PKT_COMPRESSED;
-    pkt.pkt.compressed = &cd;
-    rc = _cdk_pkt_write_fp (out, &pkt);
-    if (rc)
-        return rc;
-
-    zs = cdk_calloc (1, sizeof *zs);
-    if (!zs)
-        return CDK_Out_Of_Core;
-    if (zfx->algo == CDK_COMPRESS_ZIP)
-        rc = deflateInit2 (zs, zfx->level, Z_DEFLATED, -13, 8,
-                           Z_DEFAULT_STRATEGY);
-    else
-        rc = deflateInit (zs, zfx->level);
-    if (rc != Z_OK) {
-        cdk_free (zs);
-        return CDK_Zlib_Error;
+  _cdk_log_debug ("compress filter: encode\n");
+  
+  if (!zfx || !in || !out)
+    return CDK_Inv_Value;
+  
+  if (!zfx->algo)
+    zfx->algo = CDK_COMPRESS_ZIP;
+  
+  memset (&cd, 0, sizeof (cd));
+  cd.len = 0;
+  cd.algorithm = zfx->algo;
+  pkt.pkttype = CDK_PKT_COMPRESSED;
+  pkt.pkt.compressed = &cd;
+  rc = _cdk_pkt_write_fp (out, &pkt);
+  if (rc)
+    return rc;
+  
+  zs = cdk_calloc (1, sizeof *zs);
+  if (!zs)
+    return CDK_Out_Of_Core;
+  if (zfx->algo == CDK_COMPRESS_ZIP)
+    rc = deflateInit2 (zs, zfx->level, Z_DEFLATED, -13, 8,
+                      Z_DEFAULT_STRATEGY);
+  else
+    rc = deflateInit (zs, zfx->level);
+  if (rc != Z_OK) 
+    {
+      cdk_free (zs);
+      return CDK_Zlib_Error;
     }
-    zfx->outbufsize = 8192;
-    memset (zfx->outbuf, 0, sizeof zfx->outbuf);
-
-    while (!feof (in)) {
-        nread = fread (zfx->outbuf, 1, zfx->outbufsize, in);
-        if (!nread)
-            break;
-        zrc = compress_data (zs, Z_NO_FLUSH, zfx->outbuf, nread, out);
-        if (zrc) {
-            rc = CDK_Zlib_Error;
-            break;
+  zfx->outbufsize = 8192;
+  memset (zfx->outbuf, 0, sizeof zfx->outbuf);
+  
+  while (!feof (in)) 
+    {
+      nread = fread (zfx->outbuf, 1, zfx->outbufsize, in);
+      if (!nread)
+       break;
+      zrc = compress_data (zs, Z_NO_FLUSH, zfx->outbuf, nread, out);
+      if (zrc) 
+       {
+         rc = CDK_Zlib_Error;
+         break;
         }
     }
-    if (!rc) {
-        nread = 0;
-        zrc = compress_data (zs, Z_FINISH, zfx->outbuf, nread, out);
-        if (zrc != Z_STREAM_END)
-            rc = CDK_Zlib_Error;
+  if (!rc) 
+    {
+      nread = 0;
+      zrc = compress_data (zs, Z_FINISH, zfx->outbuf, nread, out);
+      if (zrc != Z_STREAM_END)
+       rc = CDK_Zlib_Error;
     }
-    deflateEnd (zs);
-    cdk_free (zs);
-    return rc;
+  deflateEnd (zs);
+  cdk_free (zs);
+  return rc;
 }
 
 
 cdk_error_t
 _cdk_filter_compress (void *opaque, int ctl, FILE *in, FILE *out)
 {
-    if (ctl == STREAMCTL_READ)
-        return compress_decode (opaque, in, out);
-    else if (ctl == STREAMCTL_WRITE)
-        return compress_encode (opaque, in, out);
-    else if (ctl == STREAMCTL_FREE) {
-        compress_filter_t * zfx = opaque;
-        if (zfx) {
-            _cdk_log_debug ("free compress filter\n");
-            zfx->level = 0;
-            zfx->algo = 0;
+  if (ctl == STREAMCTL_READ)
+    return compress_decode (opaque, in, out);
+  else if (ctl == STREAMCTL_WRITE)
+    return compress_encode (opaque, in, out);
+  else if (ctl == STREAMCTL_FREE) 
+    {
+      compress_filter_t * zfx = opaque;
+      if (zfx) 
+       {
+         _cdk_log_debug ("free compress filter\n");
+         zfx->level = 0;
+         zfx->algo = 0;
         }
-       return 0;
+      return 0;
     }
-    return CDK_Inv_Mode;
+  return CDK_Inv_Mode;
 }
 
 #else
 cdk_error_t
 _cdk_filter_compress (void *opaque, int ctl, FILE *in, FILE *out)
 {
-    return CDK_Not_Implemented;    
+  return CDK_Not_Implemented;    
 }
 #endif /* HAVE_LIBZ */
 
index 32b274469be630726cf4cb6aff99df364d4490d9..7ff2a9c401435a940f523fb7a8c589718f294747 100644 (file)
@@ -54,8 +54,6 @@ struct cdk_ctx_s {
     unsigned textmode:1;
     unsigned compress:1;
     unsigned mdc:1;
-    unsigned compat:1;
-    unsigned rfc1991:1;
     unsigned overwrite;
     unsigned force_digest:1;
   } opt;
@@ -95,12 +93,6 @@ struct cdk_subpkt_s {
   byte d[1];  
 };
 
-struct key_idx_s {
-  off_t offset;
-  u32 keyid[2];
-  byte fpr[KEY_FPR_LEN];
-};
-
 
 struct cdk_dbsearch_s {
   union {
@@ -152,7 +144,6 @@ struct cdk_dek_s {
   int algo;
   int keylen;
   int use_mdc;
-  unsigned rfc1991:1;
   byte key[32]; /* 256-bit */
 };
 
index f7c4627ec430acd7467df36241b1ef1a4ef77dde..2c1b2014e0270ab95c31d1ff3b8fb71c088135e2 100644 (file)
@@ -23,50 +23,50 @@ enum {
 };
 
 typedef struct {
-    gcry_cipher_hd_t hd;
-    gcry_md_hd_t mdc;
-    int mdc_method;
-    cdk_dek_t dek;
-    u32 datalen;
-    struct {
-      size_t on;
-      off_t size;
-      off_t nleft;
-    } blkmode;
-    cdk_stream_t s;
+  gcry_cipher_hd_t hd;
+  gcry_md_hd_t mdc;
+  int mdc_method;
+  cdk_dek_t dek;
+  u32 datalen;
+  struct {
+    size_t on;
+    off_t size;
+    off_t nleft;
+  } blkmode;
+  cdk_stream_t s;
 } cipher_filter_t;
 
 typedef struct {
-    int digest_algo;
-    gcry_md_hd_t md;
+  int digest_algo;
+  gcry_md_hd_t md;
 } md_filter_t;
 
 typedef struct {
-    const char * le; /* line endings */
-    const char * hdrlines;
-    u32 crc;
-    int crc_okay;
-    int idx, idx2;
+  const char *le; /* line endings */
+  const char *hdrlines;
+  u32 crc;
+  int crc_okay;
+  int idx, idx2;
 } armor_filter_t;
 
 typedef struct {
-    int mode;
-    unsigned rfc1991:1;
-    char * filename;
-    gcry_md_hd_t md;
-    struct {
-      size_t on;
-      off_t size;
-    } blkmode;
+  int mode;
+  char *orig_filename; /* This original name of the input file. */
+  char *filename;
+  gcry_md_hd_t md;
+  struct {
+    size_t on;
+    off_t size;
+  } blkmode;
 } literal_filter_t;
 
 typedef struct {
-    size_t inbufsize;
-    byte inbuf[8192];
-    size_t outbufsize;
-    byte outbuf[8192];
-    int algo; /* compress algo */
-    int level;
+  size_t inbufsize;
+  byte inbuf[8192];
+  size_t outbufsize;
+  byte outbuf[8192];
+  int algo; /* compress algo */
+  int level;
 } compress_filter_t;
 
 typedef struct {
index 5d9b13fce127538701f9ed4a1075561bfc5f81b9..4595f18b2b7867b3f0e1261ea03eb3ca4d4ec579 100644 (file)
@@ -396,7 +396,7 @@ cdk_kbnode_read_from_mem (cdk_kbnode_t *ret_node,
   cdk_stream_t inp;
   cdk_error_t rc;
   
-  if (!buflen || !ret_node)
+  if (!buflen || !ret_node || !buf)
     return CDK_Inv_Value;
   
   *ret_node = NULL;
@@ -428,7 +428,10 @@ cdk_kbnode_write_to_mem_alloc (cdk_kbnode_t node,
   
   if (!node)
     return CDK_Inv_Value;
-
+  
+  *r_buf = NULL;
+  *r_buflen = 0;
+  
   rc = cdk_stream_tmp_new (&s);
   if (rc)
     return rc;
@@ -436,13 +439,13 @@ cdk_kbnode_write_to_mem_alloc (cdk_kbnode_t node,
   for (n = node; n; n = n->next)
     {
       /* Skip all packets which cannot occur in a key composition. */
-      if (n->pkt->pkttype != CDK_PKT_PUBLIC_KEY
-         && n->pkt->pkttype != CDK_PKT_PUBLIC_SUBKEY
-         && n->pkt->pkttype != CDK_PKT_SECRET_KEY
-         && n->pkt->pkttype != CDK_PKT_SECRET_SUBKEY
-         && n->pkt->pkttype != CDK_PKT_SIGNATURE
-         && n->pkt->pkttype != CDK_PKT_USER_ID
-         && n->pkt->pkttype != CDK_PKT_ATTRIBUTE)
+      if (n->pkt->pkttype != CDK_PKT_PUBLIC_KEY &&
+         n->pkt->pkttype != CDK_PKT_PUBLIC_SUBKEY &&
+         n->pkt->pkttype != CDK_PKT_SECRET_KEY &&
+         n->pkt->pkttype != CDK_PKT_SECRET_SUBKEY &&
+         n->pkt->pkttype != CDK_PKT_SIGNATURE &&
+         n->pkt->pkttype != CDK_PKT_USER_ID &&
+         n->pkt->pkttype != CDK_PKT_ATTRIBUTE)
        continue;
       rc = cdk_pkt_write (s, n->pkt);
       if (rc)
@@ -457,7 +460,7 @@ cdk_kbnode_write_to_mem_alloc (cdk_kbnode_t node,
   *r_buf = cdk_calloc (1, len);
   *r_buflen = cdk_stream_read (s, *r_buf, len);
   cdk_stream_close (s);
-  return rc;
+  return 0;
 }
   
   
@@ -480,7 +483,6 @@ cdk_kbnode_write_to_mem (cdk_kbnode_t node, byte *buf, size_t *r_nbytes)
   size_t len;
   cdk_error_t rc;
   
-  /* FIXME: Mark the function as deprecated!. */
   if (!node)
     return CDK_Inv_Value;
   
@@ -491,13 +493,13 @@ cdk_kbnode_write_to_mem (cdk_kbnode_t node, byte *buf, size_t *r_nbytes)
   for (n = node; n; n = n->next)
     {
       /* Skip all packets which cannot occur in a key composition. */
-      if (n->pkt->pkttype != CDK_PKT_PUBLIC_KEY
-         && n->pkt->pkttype != CDK_PKT_PUBLIC_SUBKEY
-         && n->pkt->pkttype != CDK_PKT_SECRET_KEY
-         && n->pkt->pkttype != CDK_PKT_SECRET_SUBKEY
-         && n->pkt->pkttype != CDK_PKT_SIGNATURE
-         && n->pkt->pkttype != CDK_PKT_USER_ID
-         && n->pkt->pkttype != CDK_PKT_ATTRIBUTE)
+      if (n->pkt->pkttype != CDK_PKT_PUBLIC_KEY &&
+         n->pkt->pkttype != CDK_PKT_PUBLIC_SUBKEY &&
+         n->pkt->pkttype != CDK_PKT_SECRET_KEY &&
+         n->pkt->pkttype != CDK_PKT_SECRET_SUBKEY &&
+         n->pkt->pkttype != CDK_PKT_SIGNATURE &&
+         n->pkt->pkttype != CDK_PKT_USER_ID &&
+         n->pkt->pkttype != CDK_PKT_ATTRIBUTE)
        continue;
       rc = cdk_pkt_write (s, n->pkt);
       if (rc)
@@ -511,10 +513,8 @@ cdk_kbnode_write_to_mem (cdk_kbnode_t node, byte *buf, size_t *r_nbytes)
   len = cdk_stream_get_length (s);
   if (!buf) 
     {
-      *r_nbytes = len; /* only return the length of the buffer */
+      *r_nbytes = len; /* Only return the length of the buffer */
       cdk_stream_close (s);
-      /* FIXME: A patch from the nmav-0-5-x has set the return
-         to CDK_Too_Short which is clerly wrong! */
       return 0;
     }
   if (*r_nbytes < len)
index 1b676040b02187225cc2ff895dd92f8f0ee44b5e..26bc6dd1a7f985ef58b586256bc52df803fa4be9 100644 (file)
 #define KEYDB_CACHE_ENTRIES 8
 
 typedef struct key_table_s *key_table_t;
+
+struct key_idx_s 
+{
+  off_t offset;
+  u32 keyid[2];
+  byte fpr[KEY_FPR_LEN];
+};
 typedef struct key_idx_s *key_idx_t;
 
 
@@ -47,12 +54,13 @@ static cdk_kbnode_t find_selfsig_node (cdk_kbnode_t key, cdk_pkt_pubkey_t pk);
 static char*
 keydb_idx_mkname (const char *file)
 {
-  char *fname;
+  char *fname, *fmt;
     
-  fname = cdk_calloc (1, strlen (file) + 4 + 1);
+  fmt = "%s.idx";
+  fname = cdk_calloc (1, strlen (file) + strlen (fmt) + 1);
   if (!fname)
     return NULL;
-  sprintf (fname, "%s.idx", file);
+  sprintf (fname, fmt, file);
   return fname;
 }
 
@@ -63,7 +71,7 @@ keydb_idx_mkname (const char *file)
    --------
     4 octets offset of the packet
     8 octets keyid
-   KEY_FPR_LEN (=20) octets fingerprint
+   20 octets fingerprint
    --------
    We store the keyid and the fingerprint due to the fact we can't get
    the keyid from a v3 fingerprint directly.
@@ -73,9 +81,8 @@ keydb_idx_build (const char *file)
 {
   cdk_packet_t pkt;
   cdk_stream_t inp, out = NULL;
-  byte buf[8], fpr[KEY_FPR_LEN];
-  char *fname;
-  off_t pos;
+  byte buf[4+8+KEY_FPR_LEN];
+  char *idx_name;
   u32 keyid[2];
   cdk_error_t rc;
   
@@ -86,43 +93,47 @@ keydb_idx_build (const char *file)
   if (rc)
     return rc;
   
-  fname = keydb_idx_mkname (file);
-  if (!fname)
+  idx_name = keydb_idx_mkname (file);
+  if (!idx_name)
     {
       cdk_stream_close (inp);
       return CDK_Out_Of_Core;
     }  
-  rc = cdk_stream_create (fname, &out);
-  cdk_free (fname);
+  rc = cdk_stream_create (idx_name, &out);
+  cdk_free (idx_name);
   if (rc)
     goto leave;
-  
+
   cdk_pkt_new (&pkt);
   while (!cdk_stream_eof (inp)) 
     {
-      pos = cdk_stream_tell (inp);
+      off_t pos = cdk_stream_tell (inp);
+      
       rc = cdk_pkt_read (inp, pkt);
       if (rc)
-       break;
+       {
+         _cdk_log_debug ("index build failed packet off=%lu\n", pos);
+         /* FIXME: The index is incomplete */
+         break;
+       }     
       if (pkt->pkttype == CDK_PKT_PUBLIC_KEY ||
          pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY)
        {
          _cdk_u32tobuf (pos, buf);
-         cdk_stream_write (out, buf, 4);
          cdk_pk_get_keyid (pkt->pkt.public_key, keyid);
-         _cdk_u32tobuf (keyid[0], buf + 0);
-         _cdk_u32tobuf (keyid[1], buf + 4);
-         cdk_stream_write (out, buf, 8);
-         cdk_pk_get_fingerprint (pkt->pkt.public_key, fpr);
-         cdk_stream_write (out, fpr, KEY_FPR_LEN);
+         _cdk_u32tobuf (keyid[0], buf + 4);
+         _cdk_u32tobuf (keyid[1], buf + 8);
+         cdk_pk_get_fingerprint (pkt->pkt.public_key, buf+12);
+         cdk_stream_write (out, buf, 4+8+KEY_FPR_LEN);
         }
       cdk_pkt_free (pkt);
     }
-
+  
+  cdk_pkt_release (pkt);
+  
   leave:
   cdk_stream_close (out);
   cdk_stream_close (inp);
-  cdk_pkt_release (pkt);
   return rc;
 }
 
@@ -176,9 +187,8 @@ keydb_idx_parse (cdk_stream_t inp, key_idx_t *r_idx)
 {
   key_idx_t idx;
   byte buf[4];
-  int i;
   
-  if( !inp || !r_idx )
+  if (!inp || !r_idx)
     return CDK_Inv_Value;
   
   idx = cdk_calloc (1, sizeof *idx);
@@ -187,8 +197,7 @@ keydb_idx_parse (cdk_stream_t inp, key_idx_t *r_idx)
   
   while (!cdk_stream_eof (inp)) 
     {
-      i = cdk_stream_read (inp, buf, 4);
-      if (i == CDK_EOF)
+      if (cdk_stream_read (inp, buf, 4) == CDK_EOF)
        break;
       idx->offset = _cdk_buftou32 (buf);
       cdk_stream_read (inp, buf, 4);
@@ -204,8 +213,7 @@ keydb_idx_parse (cdk_stream_t inp, key_idx_t *r_idx)
 
 
 static int
-keydb_idx_search (cdk_stream_t inp, u32 *keyid,
-                  const byte *fpr, off_t *r_off)
+keydb_idx_search (cdk_stream_t inp, u32 *keyid, const byte *fpr, off_t *r_off)
 {
   key_idx_t idx;
 
@@ -214,6 +222,9 @@ keydb_idx_search (cdk_stream_t inp, u32 *keyid,
   if ((keyid && fpr) || (!keyid && !fpr))
     return CDK_Inv_Mode;
 
+  /* We need an initialize the offset var with a value
+     because it might be possible the returned offset will
+     be 0 and then we cannot differ between the begin and an EOF. */
   *r_off = 0xFFFFFFFF;
   cdk_stream_seek (inp, 0);
   while (keydb_idx_parse (inp, &idx) != CDK_EOF) 
@@ -449,7 +460,7 @@ _cdk_keydb_open (cdk_keydb_hd_t hd, cdk_stream_t *ret_kr)
                  /* This is no real error, it just means we can't create
                     the index at the given directory. maybe we've no write
                     access. in this case, we simply disable the index. */
-                 _cdk_log_debug ("disable key index table\n");
+                 _cdk_log_debug ("disable key index table err=%d\n", rc);
                  rc = 0;
                  hd->no_cache = 1;
                }
@@ -837,43 +848,45 @@ keydb_pos_from_cache (cdk_keydb_hd_t hd, cdk_dbsearch_t ks,
                       int *r_cache_hit, off_t *r_off)
 {
   key_table_t c;
-  off_t off;
-  int cache_hit;
 
   if (!hd || !r_cache_hit || !r_off)
     return CDK_Inv_Value;
   
-  /* Reset */
-  off = 0;
-  cache_hit = 0;
+  /* Reset the values. */
+  *r_cache_hit = 0;
+  *r_off = 0;
   
   c = keydb_cache_find (hd->cache, ks);
   if (c != NULL)
     {      
       _cdk_log_debug ("Cache: found entry in cache.\n");
-      cache_hit = 1;
-      off = c->offset;
+      *r_cache_hit = 1;
+      *r_off = c->offset;
+      return 0;
     }
   
-  if (hd->idx && !c)
+  /* No index cache available so we just return here. */
+  if (!hd->idx)
+    return 0;
+  
+  if (hd->idx)
     {
       if (ks->type == CDK_DBSEARCH_KEYID)
        {
-         if (keydb_idx_search (hd->idx, ks->u.keyid, NULL, &off))
+         if (keydb_idx_search (hd->idx, ks->u.keyid, NULL, r_off))
            return CDK_Error_No_Key;
          _cdk_log_debug ("Cache: found keyid entry in idx table.\n");
-         cache_hit = 1;
+         *r_cache_hit = 1;
         }
       else if (ks->type == CDK_DBSEARCH_FPR)
        {
-         if (keydb_idx_search (hd->idx, NULL, ks->u.fpr, &off))
+         if (keydb_idx_search (hd->idx, NULL, ks->u.fpr, r_off))
            return CDK_Error_No_Key;
          _cdk_log_debug ("Cache: found fpr entry in idx table.\n");
-         cache_hit = 1;
+         *r_cache_hit = 1;
        }
     }
-  *r_off = off;
-  *r_cache_hit = cache_hit;
+
   return 0;
 }
 
@@ -907,12 +920,15 @@ cdk_keydb_search (cdk_keydb_hd_t hd, cdk_kbnode_t *ret_key)
     return rc;
   
   if (!hd->no_cache)
-    {     
-      /* FIXME: pubkey offset seems wrong */
+    {
+      /* It is possible the index is not up-to-date and thus we do
+         not find the requesed key. In this case, we reset cache hit
+         and continue our normal search procedure. */
       rc = keydb_pos_from_cache (hd, hd->dbs, &cache_hit, &off);
       if (rc)
-        return rc;
+       cache_hit = 0;
     }
+  
   ks = hd->dbs;
   while (!key_found && !rc)
     {
@@ -1270,15 +1286,15 @@ cdk_keydb_get_pk (cdk_keydb_hd_t hd, u32 *keyid, cdk_pkt_pubkey_t *r_pk)
 
 
 cdk_error_t
-cdk_keydb_get_sk (cdk_keydb_hd_t hd, u32 *keyid, cdk_pkt_seckey_t *ret_sk)
+cdk_keydb_get_sk (cdk_keydb_hd_t hd, u32 *keyid, cdk_seckey_t *ret_sk)
 {
   cdk_kbnode_t snode, node;
-  cdk_pkt_seckey_t sk;
+  cdk_seckey_t sk;
   cdk_error_t rc;
 
   if (!keyid || !ret_sk)
     return CDK_Inv_Value;
-  if (!hd )
+  if (!hd)
     return CDK_Error_No_Keyring;
 
   *ret_sk = NULL;
@@ -1445,7 +1461,7 @@ keydb_merge_selfsig (cdk_kbnode_t key, u32 *keyid)
       if (key_expire)
        {
          pk->expiredate = pk->timestamp + key_expire;
-         pk->has_expired = pk->expiredate> _cdk_timestamp ()?0 :1;
+         pk->has_expired = pk->expiredate> (u32)time (NULL)?0 :1;
        }
       
       if (key_usage)
@@ -1464,7 +1480,7 @@ keydb_parse_allsigs (cdk_kbnode_t knode, cdk_keydb_hd_t hd, int check)
   cdk_pkt_signature_t sig;
   cdk_pkt_pubkey_t pk;
   cdk_subpkt_t s=NULL;
-  u32 expiredate = 0, curtime = _cdk_timestamp ();
+  u32 expiredate = 0, curtime = (u32)time (NULL);
   u32 keyid[2];
 
   if (!knode)
index 28cae67df08dc04a64e1f7dc909e1ab5926d2c46..5fae806f021fa15fb75c49c6796f40d6154fc5c8 100644 (file)
 # include <config.h>
 #endif
 #include <stdio.h>
+#include <time.h>
 
 #include "opencdk.h"
 #include "main.h"
 #include "filters.h"
 
 
+/* Duplicate the string @s but strip of possible
+   relative folder names of it. */
+static char*
+dup_trim_filename (const char *s)
+{
+  char *p = NULL;
+  
+  p = strrchr (s, '/');
+  if (!p)
+    p = strrchr (s, '\\');
+  if (!p)
+    return cdk_strdup (s);
+  return cdk_strdup (p + 1);
+}
+
+  
 static cdk_error_t
-literal_decode (void * opaque, FILE * in, FILE * out)
+literal_decode (void *opaque, FILE *in, FILE *out)
 {
   literal_filter_t *pfx = opaque;
   cdk_stream_t si, so;
@@ -35,7 +52,7 @@ literal_decode (void * opaque, FILE * in, FILE * out)
   int bufsize;
   cdk_error_t rc;
 
-  _cdk_log_debug( "literal filter: decode\n" );
+  _cdk_log_debug ("literal filter: decode\n");
   
   if (!pfx || !in || !out)
     return CDK_Inv_Value;
@@ -68,21 +85,43 @@ literal_decode (void * opaque, FILE * in, FILE * out)
   
   pt = pkt->pkt.literal;
   pfx->mode = pt->mode;
-  pfx->filename = cdk_strdup (pt->name? pt->name : " ");
-  if (!pfx->filename)
+
+  if (pfx->filename && pt->namelen > 0)
     {
-      /* FIXME: release streams. */
-      cdk_pkt_release (pkt);
-      return CDK_Out_Of_Core;
+      /* The name in the literal packet is more authorative. */
+      cdk_free (pfx->filename);
+      pfx->filename = dup_trim_filename (pt->name);
+    }
+  else if (!pfx->filename && pt->namelen > 0)
+    pfx->filename = dup_trim_filename (pt->name);
+  else if (!pt->namelen && !pfx->filename && pfx->orig_filename)
+    {
+      /* In this case, we need to derrive the output file name
+         from the original name and cut off the OpenPGP extension.
+         If this is not possible, we return an error. */
+      if (!stristr (pfx->orig_filename, ".gpg") &&
+         !stristr (pfx->orig_filename, ".pgp") &&
+         !stristr (pfx->orig_filename, ".asc"))
+       {
+         cdk_pkt_release (pkt);
+         cdk_stream_close (si);
+         cdk_stream_close (so);
+         _cdk_log_debug ("literal filter: no file name and no PGP extension\n");
+         return CDK_Inv_Mode;
+       }
+      _cdk_log_debug ("literal filter: derrive file name from original\n");
+      pfx->filename = dup_trim_filename (pfx->orig_filename);
+      pfx->filename[strlen (pfx->filename)-4] = '\0';
     }
+  
   while (!feof (in))
     {    
-      /*_cdk_log_debug( "partial on=%d size=%lu\n",
-         pfx->blkmode.on, pfx->blkmode.size );*/
+      _cdk_log_debug ("literal_decode: part on %d size %lu\n",
+                     pfx->blkmode.on, pfx->blkmode.size);
       if (pfx->blkmode.on)
        bufsize = pfx->blkmode.size;
       else
-       bufsize = pt->len < DIM (buf)-1? pt->len : DIM (buf)-1;
+       bufsize = pt->len < DIM (buf)? pt->len : DIM (buf);
       nread = cdk_stream_read (pt->buf, buf, bufsize);
       if (nread == EOF) 
        {
@@ -128,7 +167,7 @@ literal_encode (void *opaque, FILE *in, FILE *out)
     {
       pfx->filename = cdk_strdup ("_CONSOLE");
       if (!pfx->filename)
-      return CDK_Out_Of_Core;
+       return CDK_Out_Of_Core;
   }
 
   rc = _cdk_stream_fpopen (in, STREAMCTL_READ, &si);
@@ -147,11 +186,11 @@ literal_encode (void *opaque, FILE *in, FILE *out)
   memcpy (pt->name, pfx->filename, filelen);
   pt->namelen = filelen;
   pt->name[pt->namelen] = '\0';
-  pt->timestamp = _cdk_timestamp ();
+  pt->timestamp = (u32)time (NULL);
   pt->mode = pfx->mode ? 't' : 'b';
   pt->len = cdk_stream_get_length (si);
   pt->buf = si;
-  pkt->old_ctb = pfx->rfc1991? 1 : 0;
+  pkt->old_ctb = 1;
   pkt->pkttype = CDK_PKT_LITERAL;
   pkt->pkt.literal = pt;
   rc = _cdk_pkt_write_fp (out, pkt);
@@ -163,21 +202,25 @@ literal_encode (void *opaque, FILE *in, FILE *out)
 
 
 int
-_cdk_filter_literal( void * opaque, int ctl, FILE * in, FILE * out )
+_cdk_filter_literal (void * opaque, int ctl, FILE * in, FILE * out)
 {
-    if( ctl == STREAMCTL_READ )
-        return literal_decode( opaque, in, out );
-    else if( ctl == STREAMCTL_WRITE )
-        return literal_encode( opaque, in, out );
-    else if( ctl == STREAMCTL_FREE ) {
-        literal_filter_t * pfx = opaque;
-        if( pfx ) {
-            _cdk_log_debug( "free literal filter\n" );
-            cdk_free( pfx->filename );
-            pfx->filename = NULL;
-        }
+  if (ctl == STREAMCTL_READ)
+    return literal_decode( opaque, in, out );
+  else if (ctl == STREAMCTL_WRITE)
+    return literal_encode (opaque, in, out);
+  else if (ctl == STREAMCTL_FREE)
+    {
+      literal_filter_t *pfx = opaque;
+      if (pfx)
+       {
+         _cdk_log_debug ("free literal filter\n");
+         cdk_free (pfx->filename);
+         pfx->filename = NULL;
+         cdk_free (pfx->orig_filename);
+         pfx->orig_filename = NULL;
+       }
     }
-    return CDK_Inv_Mode;
+  return CDK_Inv_Mode;
 }
 
 
@@ -185,11 +228,12 @@ static int
 text_encode (void *opaque, FILE *in, FILE *out)
 {
   const char *s;
-  char buf[1024];
+  char buf[2048];
   
   if (!in || !out)
     return CDK_Inv_Value;
   
+  /* FIXME: This code does not work for very long lines. */
   while (!feof (in)) 
     {
       s = fgets (buf, DIM (buf)-1, in);
@@ -204,41 +248,44 @@ text_encode (void *opaque, FILE *in, FILE *out)
 
       
 static int
-text_decode( void * opaque, FILE * in, FILE * out )
+text_decode (void * opaque, FILE * in, FILE * out)
 {
-    text_filter_t * tfx = opaque;
-    const char * s;
-    char buf[1024];
-
-    if( !tfx || !in || !out )
-        return CDK_Inv_Value;
-
-    while( !feof( in ) ) {
-        s = fgets( buf, DIM (buf)-1, in );
-        if( !s )
-            break;
-        _cdk_trim_string( buf, 0 );
-        fwrite( buf, 1, strlen( buf ), out );
-        fwrite( tfx->lf, 1, strlen( tfx->lf ), out );
+  text_filter_t *tfx = opaque;
+  const char *s;
+  char buf[2048];
+  
+  if (!tfx || !in || !out)
+    return CDK_Inv_Value;
+  
+  while (!feof (in)) 
+    {
+      s = fgets (buf, DIM (buf)-1, in);
+      if (!s)
+       break;
+      _cdk_trim_string (buf, 0);
+      fwrite (buf, 1, strlen (buf), out);
+      fwrite (tfx->lf, 1, strlen (tfx->lf), out);
     }
-    
-    return 0;
+  
+  return 0;
 }
 
 
 int
-_cdk_filter_text( void * opaque, int ctl, FILE * in, FILE * out )
+_cdk_filter_text (void *opaque, int ctl, FILE *in, FILE *out)
 {
-    if( ctl == STREAMCTL_READ )
-        return text_encode( opaque, in, out );
-    else if( ctl == STREAMCTL_WRITE )
-        return text_decode( opaque, in, out );
-    else if( ctl == STREAMCTL_FREE ) {
-        text_filter_t * tfx = opaque;
-        if( tfx ) {
-            _cdk_log_debug( "free text filter\n" );
-            tfx->lf = NULL;
-        }
+  if (ctl == STREAMCTL_READ)
+    return text_encode (opaque, in, out);
+  else if (ctl == STREAMCTL_WRITE)
+    return text_decode (opaque, in, out);
+  else if (ctl == STREAMCTL_FREE)
+    {
+      text_filter_t * tfx = opaque;
+      if (tfx) 
+       {
+         _cdk_log_debug ("free text filter\n");
+         tfx->lf = NULL;
+       }
     }
-    return CDK_Inv_Mode;
+  return CDK_Inv_Mode;
 }
index 51f8d8be06689a494df197a5902c55507fae8ccd..3f863b6cec89fc4d2b9bb47f42b759741555f5ba 100644 (file)
@@ -95,6 +95,7 @@ cdk_strerror (int ec)
     case CDK_Too_Short:        return "Buffer or object is too short";
     case CDK_Unusable_Key:     return "Unusable public key";
     case CDK_No_Data:          return "No data";
+    case CDK_No_Passphrase:    return "No passphrase supplied";
     default:                   sprintf (buf, "ec=%d", ec); return buf;
     }
   return NULL;
@@ -191,8 +192,8 @@ _secmem_init (size_t size)
 static void
 _secmem_end (void)
 {
-    gcry_control (GCRYCTL_TERM_SECMEM);
-    secmem_init = 0;
+  gcry_control (GCRYCTL_TERM_SECMEM);
+  secmem_init = 0;
 }
 
 
@@ -434,25 +435,6 @@ handle_set_s2k (cdk_ctx_t hd, int mode, int digest, int cipher)
 }
 
 
-static void
-handle_set_compat (cdk_ctx_t hd, int val)
-{
-  if (!hd)
-    return;
-  hd->opt.compat = val;
-  if (!val)
-    return;
-  hd->opt.mdc = 0;
-  hd->opt.rfc1991 = val == -1? 1: 0;
-  hd->compress.algo = CDK_COMPRESS_ZIP;
-  hd->compress.level = -1;
-  hd->cipher_algo = val == -1? GCRY_CIPHER_IDEA : DEFAULT_CIPHER_ALGO;
-  hd->digest_algo = val == -1? GCRY_MD_MD5: DEFAULT_DIGEST_ALGO;
-  if (val == -1)
-    handle_set_s2k (hd, 0, hd->digest_algo, hd->cipher_algo);
-}
-
-
 static void
 handle_set_compress (cdk_ctx_t hd, int algo, int level)
 {
@@ -510,22 +492,15 @@ cdk_handle_control (cdk_ctx_t hd, int action, int cmd, ...)
       break;
       
     case CDK_CTL_DIGEST:
-      if( set )
+      if (set)
        handle_set_digest( hd, va_arg( arg_ptr, int ) );
       else
        val = hd->digest_algo;
       break;
       
-    case CDK_CTL_COMPAT:
-      if( set )
-       handle_set_compat( hd, va_arg( arg_ptr, int ) );
-      else
-       val = hd->opt.compat;
-      break;
-      
     case CDK_CTL_OVERWRITE:
       if (set)
-       hd->opt.overwrite = va_arg( arg_ptr, int );
+       hd->opt.overwrite = va_arg (arg_ptr, int);
       else
        val = hd->opt.overwrite;
       break;
@@ -552,21 +527,9 @@ cdk_handle_control (cdk_ctx_t hd, int action, int cmd, ...)
        val = hd->_s2k.mode;
       break;
       
-    case CDK_CTL_KEYCACHE_ON:
-      if (set)
-       hd->cache.on = va_arg (arg_ptr, int);
-      else
-       val = hd->cache.on;
-      break;
-      
-    case CDK_CTL_KEYCACHE_FREE:
-      cdk_sk_release (hd->cache.sk);
-      hd->cache.sk = NULL;
-      break;
-      
     case CDK_CTL_FORCE_DIGEST:
-      if( set )
-       hd->opt.force_digest = va_arg( arg_ptr, int );
+      if (set)
+       hd->opt.force_digest = va_arg (arg_ptr, int);
       else
        val = hd->opt.force_digest;
       break;
@@ -738,7 +701,6 @@ cdk_handle_free (cdk_ctx_t hd)
   if (!hd)
     return;
   _cdk_result_verify_free (hd->result.verify);
-  cdk_sk_release (hd->cache.sk);
 
   /* If cdk_handle_set_keyring() were used, we need to free the key db
      handles here because the handles are not controlled by the user. */
index e84f346b44ff58af3803c74213914fa75546181b..10ef55711aae3763b42296000afaf643f26e5ce3 100644 (file)
@@ -34,7 +34,7 @@
 #include "context.h"
 
 /* The maximal amount of bits a multi precsion integer can have. */
-#define MAX_MPI_BITS 8192
+#define MAX_MPI_BITS 16384
 #define MAX_MPI_BYTES (MAX_MPI_BITS/8)
 
 
  that SHA-512 is used and increase the buffer size of the digest. */
 #define MAX_DIGEST_LEN 64
 
+/* Helper to find out if the signature were made over a user ID
+   or if the signature revokes a previous user ID. */
 #define IS_UID_SIG(s) (((s)->sig_class & ~3) == 0x10)
 #define IS_UID_REV(s) ((s)->sig_class == 0x30)
 
 #define DEBUG_PKT (_cdk_get_log_level () == (CDK_LOG_DEBUG+1))
 
+/* Helper to find out if a key has the requested capability. */
 #define KEY_CAN_ENCRYPT(a) (_cdk_pk_algo_usage ((a)) & CDK_KEY_USG_ENCR)
 #define KEY_CAN_SIGN(a)    (_cdk_pk_algo_usage ((a)) & CDK_KEY_USG_SIGN)
 #define KEY_CAN_AUTH(a)    (_cdk_pk_algo_usage ((a)) & CDK_KEY_USG_AUTH)
@@ -72,12 +75,10 @@ void _cdk_log_debug (const char * fmt, ...);
 char * _cdk_passphrase_get (cdk_ctx_t hd, const char *prompt);
 
 /*-- misc.c --*/
-int _cdk_check_file( const char * file );
-u32 _cdk_timestamp( void );
-int _cdk_strcmp( const char * a, const char * b );
-u32 _cdk_buftou32( const byte * buf );
-void _cdk_u32tobuf( u32 u, byte * buf );
-const char * _cdk_memistr( const char * buf, size_t buflen, const char * sub );
+int _cdk_check_args( int overwrite, const char * in, const char * out );
+u32 _cdk_buftou32 (const byte * buf);
+void _cdk_u32tobuf (u32 u, byte * buf);
+const char *_cdk_memistr (const char * buf, size_t buflen, const char * sub);
 cdk_error_t map_gcry_error (gcry_error_t err);
 
 /* Helper to provide case insentensive strstr version. */
@@ -106,7 +107,7 @@ cdk_error_t _cdk_subpkt_copy (cdk_subpkt_t * r_dst, cdk_subpkt_t src);
 int _cdk_sig_check (cdk_pkt_pubkey_t pk, cdk_pkt_signature_t sig,
                     gcry_md_hd_t digest, int * r_expired);
 cdk_error_t _cdk_hash_sig_data (cdk_pkt_signature_t sig, gcry_md_hd_t hd);
-void _cdk_hash_useridcdk_pkt_userid_t uid, int sig_version, gcry_md_hd_t md);
+void _cdk_hash_userid (cdk_pkt_userid_t uid, int sig_version, gcry_md_hd_t md);
 int _cdk_hash_pubkey (cdk_pkt_pubkey_t pk, gcry_md_hd_t md, int use_fpr);
 cdk_error_t _cdk_pk_check_sig (cdk_keydb_hd_t hd,
                               cdk_kbnode_t knode, 
@@ -117,17 +118,17 @@ void _cdk_kbnode_add (cdk_kbnode_t root, cdk_kbnode_t node);
 void _cdk_kbnode_clone (cdk_kbnode_t node);
 
 /*-- sesskey.c --*/
-int _cdk_digest_encode_pkcs1byte ** r_md, size_t * r_mdlen, int pk_algo,
+int _cdk_digest_encode_pkcs1 (byte ** r_md, size_t * r_mdlen, int pk_algo,
                               const byte * md,
-                              int digest_algo, unsigned nbits );
-int _cdk_sk_unprotect_auto( cdk_ctx_t hd, cdk_pkt_seckey_t sk );
+                              int digest_algo, unsigned nbits);
+int _cdk_sk_unprotect_auto (cdk_ctx_t hd, cdk_pkt_seckey_t sk);
 
 /*-- keydb.c --*/
-int _cdk_keydb_get_pk_byusagecdk_keydb_hd_t hd, const char * name,
-                               cdk_pkt_pubkey_t * ret_pk, int usage );
-int _cdk_keydb_get_sk_byusagecdk_keydb_hd_t hd, const char * name,
-                               cdk_pkt_seckey_t * ret_sk, int usage );
-int _cdk_keydb_check_userid( cdk_keydb_hd_t hd, u32 * keyid, const char * id );
+int _cdk_keydb_get_pk_byusage (cdk_keydb_hd_t hd, const char * name,
+                               cdk_pkt_pubkey_t * ret_pk, int usage);
+int _cdk_keydb_get_sk_byusage (cdk_keydb_hd_t hd, const char * name,
+                               cdk_pkt_seckey_t * ret_sk, int usage);
+int _cdk_keydb_check_userid (cdk_keydb_hd_t hd, u32 * keyid, const char * id);
 
 /*-- sign.c --*/
 int _cdk_sig_create( cdk_pkt_pubkey_t pk, cdk_pkt_signature_t sig );
@@ -156,8 +157,6 @@ cdk_error_t _cdk_stream_fpopen (FILE * fp, unsigned write_mode,
 void _cdk_result_verify_free (cdk_verify_result_t res);
 cdk_verify_result_t _cdk_result_verify_new (void);
 
-/*-- encrypt.c --*/
-int _cdk_check_args( int overwrite, const char * in, const char * out );
 
 /*-- read-packet.c --*/
 size_t _cdk_pkt_read_len (FILE * inp, size_t *ret_partial);
index 3164bf1ca0b6668a98cddb9ca065dd9a0535e2fe..85a567fef036708671f22031aee64e56acac6db4 100644 (file)
 #include <stdio.h>
 #include <string.h>
 #include <ctype.h>
-#include <time.h>
+#include <sys/stat.h>
 
 #include "opencdk.h"
 #include "main.h"
 
 
-/* Return 0 if the file exists. otherwise 1 */
-int
-_cdk_check_file (const char *file)
-{
-  FILE *fp;
-  int check;
-  
-  if (!file)
-    return 1;
-  fp = fopen (file, "r");
-  check = fp? 0 : 1;
-  if (fp)
-    fclose (fp);
-  return check;
-}
-
-
-u32
-_cdk_timestamp (void)
-{
-  return (u32)time (NULL);
-}
-
-
 u32
 _cdk_buftou32 (const byte *buf)
 {
@@ -77,19 +53,6 @@ _cdk_u32tobuf (u32 u, byte *buf)
 }
 
 
-int
-_cdk_strcmp (const char *a, const char *b)
-{
-  int alen, blen;
-  
-  alen = strlen( a );
-  blen = strlen( b );
-  if( alen != blen )
-    return alen > blen? 1 : -1;
-  return strcmp( a, b );
-}
-    
-
 static const char *
 parse_version_number( const char *s, int *number )
 {
@@ -168,11 +131,12 @@ cdk_check_version (const char *req_version)
 void
 cdk_strlist_free (cdk_strlist_t sl)
 {
-    cdk_strlist_t sl2;
-
-    for(; sl; sl = sl2 ) {
-        sl2 = sl->next;
-        cdk_free (sl);
+  cdk_strlist_t sl2;
+  
+  for(; sl; sl = sl2 ) 
+    {
+      sl2 = sl->next;
+      cdk_free (sl);
     }
 }
 
@@ -180,87 +144,97 @@ cdk_strlist_free (cdk_strlist_t sl)
 cdk_strlist_t
 cdk_strlist_add (cdk_strlist_t *list, const char *string)
 {
-    cdk_strlist_t sl;
-
-    if (!string)
-        return NULL;
+  cdk_strlist_t sl;
   
-    sl = cdk_calloc (1, sizeof *sl + strlen (string) + 1);
-    if (!sl)
-        return NULL;
-    strcpy (sl->d, string);
-    sl->next = *list;
-    *list = sl;
-    return sl;
+  if (!string)
+    return NULL;
+  
+  sl = cdk_calloc (1, sizeof *sl + strlen (string) + 1);
+  if (!sl)
+    return NULL;
+  strcpy (sl->d, string);
+  sl->next = *list;
+  *list = sl;
+  return sl;
 }
 
 
-const char *
-cdk_strlist_walk (cdk_strlist_t root, cdk_strlist_t * context)
+/**
+ * cdk_strlist_next:
+ * @root: the opaque string list.
+ * @r_str: optional argument to store the string data.
+ * 
+ * Return the next string list node from @root. The optional
+ * argument @r_str return the data of the current (!) node.
+ **/
+cdk_strlist_t
+cdk_strlist_next (cdk_strlist_t root, const char **r_str)
 {
-    cdk_strlist_t n;
-  
-    if( ! *context ) {
-        *context = root;
-        n = root;
-    }
-    else {
-        n = (*context)->next;
-        *context = n;
-    }
+  cdk_strlist_t node;
+
+  if (root && r_str)
+    *r_str = root->d;
+  for (node = root->next; node; node = node->next)
+    return node;
 
-    return n? n->d : NULL;
+  return NULL;
 }
 
 
-const char *
+const char*
 _cdk_memistr (const char *buf, size_t buflen, const char *sub)
 {
-    const byte *t, *s;
-    size_t n;
-
-    for (t = (byte*)buf, n = buflen, s = (byte*)sub ; n ; t++, n--) {
-        if (toupper (*t) == toupper (*s)) {
-            for (buf = t++, buflen = n--, s++;
-                 n && toupper (*t) == toupper ((byte)*s); t++, s++, n--)
-                ;
-            if (!*s)
-                return buf;
-            t = (byte*)buf;
-            n = buflen;
-            s = (byte*)sub;   
+  const byte *t, *s;
+  size_t n;
+  
+  for (t = (byte*)buf, n = buflen, s = (byte*)sub ; n ; t++, n--) 
+    {
+      if (toupper (*t) == toupper (*s)) 
+       {
+         for (buf = t++, buflen = n--, s++;
+              n && toupper (*t) == toupper ((byte)*s); t++, s++, n--)
+           ;
+         if (!*s)
+           return buf;
+         t = (byte*)buf;
+         n = buflen;
+         s = (byte*)sub;   
         }
     }
-
-    return NULL;
+  
+  return NULL;
 }
 
 
-char *
-cdk_utf8_encode (const char * string)
+char*
+cdk_utf8_encode (const char *string)
 {
-    const byte * s;
-    char * buffer;
-    byte * p;
-    size_t length = 0;
-
-    for (s = string; *s; s++) {
-        length++;
-        if (*s & 0x80)
-            length++;
+  const byte *s;
+  char *buffer;
+  byte *p;
+  size_t length;
+  
+  /* FIXME: We should use iconv if possible for utf8 issues. */
+  for (s = (const byte*)string, length = 0; *s; s++) 
+    {
+      length++;
+      if (*s & 0x80)
+       length++;
     }
 
     buffer = cdk_calloc (1, length + 1);
-    for (p = buffer, s = string; *s; s++) {
-        if (*s & 0x80) {
-            *p++ = 0xc0 | ((*s >> 6) & 3);
-            *p++ = 0x80 | (*s & 0x3f);
+    for (p = (byte*)buffer, s = (byte*)string; *s; s++) 
+    {
+      if (*s & 0x80) 
+       {
+         *p++ = 0xc0 | ((*s >> 6) & 3);
+         *p++ = 0x80 | (*s & 0x3f);
         }
-        else
-            *p++ = *s;
+      else
+       *p++ = *s;
     }
-    *p = 0;
-    return buffer;
+  *p = 0;
+  return buffer;
 }
 
 
@@ -503,13 +477,59 @@ _cdk_trim_string (char *s, int canon)
 
 int
 _cdk_check_args (int overwrite, const char *in, const char *out)
-{  
+{
+  struct stat stbuf;
+  
   if (!in || !out)
     return CDK_Inv_Value;
-  if (!_cdk_strcmp (in, out))
+  if (strlen (in) == strlen (out) && strcmp (in, out))
     return CDK_Inv_Mode;
-  if (!overwrite && !_cdk_check_file (out))
+  if (!overwrite && !stat (out, &stbuf))
     return CDK_Inv_Mode;
   return 0;
 }
 
+#ifdef _WIN32
+#include <io.h>
+#include <fcntl.h>
+
+FILE *
+my_tmpfile (void)
+{
+  /* Because the tmpfile() version of wine is not really useful,
+     we implement our own version to avoid problems with 'make check'. */
+  static const char *letters = "abcdefghijklmnopqrstuvwxyz";
+  char buf[512], rnd[24];
+  FILE *fp;
+  int fd, i;
+  
+  gcry_create_nonce (rnd, DIM (rnd));
+  for (i=0; i < DIM (rnd)-1; i++)
+    {
+      char c = letters[(unsigned char)rnd[i] % 26];
+      rnd[i] = c;
+    }
+  rnd[DIM (rnd)-1]=0;
+  if (!GetTempPath (464, buf))
+    return NULL;
+  strcat (buf, "_cdk_");
+  strcat (buf, rnd);
+  
+  /* We need to make sure the file will be deleted when it is closed. */
+  fd = _open (buf, _O_CREAT | _O_EXCL | _O_TEMPORARY |
+             _O_RDWR | _O_BINARY, _S_IREAD | _S_IWRITE);
+  if (fd == -1)
+    return NULL;
+  fp = fdopen (fd, "w+b");
+  if (fp != NULL)
+    return fp;
+  _close (fd);
+  return NULL;
+}
+#else
+FILE*
+my_tmpfile (void)
+{
+  return tmpfile ();
+}
+#endif
index d47f335f9c1dbecbae9d26566e808e7594599d4f..d7ff7bbb274605db9b2dc6c4e2d0e75b739a65d9 100644 (file)
 #include <gcrypt.h>
 
 /* The OpenCDK version as a string. */
-#define OPENCDK_VERSION "0.6.0"
+#define OPENCDK_VERSION "0.6.1"
 
 /* The OpenCDK version as integer components major.minor.path */
 #define OPENCDK_VERSION_MAJOR 0
 #define OPENCDK_VERSION_MINOR 6
-#define OPENCDK_VERSION_PATCH 0
+#define OPENCDK_VERSION_PATCH 1
 
 #ifdef __cplusplus
 extern "C" {
@@ -123,7 +123,8 @@ typedef enum {
     CDK_Inv_Packet_Ver = 23,
     CDK_Too_Short = 24,
     CDK_Unusable_Key = 25,
-    CDK_No_Data = 26
+    CDK_No_Data = 26,
+    CDK_No_Passphrase = 27
 } cdk_error_t;
 
 
@@ -137,8 +138,6 @@ enum cdk_control_flags {
     CDK_CTL_COMPAT        = 14, /* Option to switch in compat mode. */
     CDK_CTL_OVERWRITE     = 15, /* Option to enable file overwritting. */
     CDK_CTL_S2K           = 16, /* Option to set S2K values. */
-    CDK_CTL_KEYCACHE_ON   = 17,
-    CDK_CTL_KEYCACHE_FREE = 18,
     CDK_CTL_FORCE_DIGEST  = 19, /* Force the use of a digest algorithm. */
     CDK_CTL_BLOCKMODE_ON  = 20  /* Enable partial body lengths */
 };
@@ -362,6 +361,14 @@ typedef enum {
     CDK_PKT_MDC           = 19
 } cdk_packet_type_t;
 
+/* Define the maximal number of multiprecion integers for
+   a public key. */
+#define MAX_CDK_PK_PARTS 4
+
+/* Define the maximal number of multiprecision integers for
+   a signature/encrypted blob issued by a secret key. */
+#define MAX_CDK_DATA_PARTS 2
+
 
 /* Helper macro to figure out if the packet is encrypted */
 #define CDK_PKT_IS_ENCRYPTED(pkttype) (\
@@ -382,7 +389,7 @@ struct cdk_pkt_signature_s {
     cdk_subpkt_t hashed;
     unsigned short unhashed_size;
     cdk_subpkt_t unhashed;
-    gcry_mpi_t mpi[2];
+    gcry_mpi_t mpi[MAX_CDK_DATA_PARTS];
     cdk_desig_revoker_t revkeys;
     struct {
         unsigned exportable:1;
@@ -422,7 +429,7 @@ struct cdk_pkt_pubkey_s {
     unsigned int main_keyid[2];
     unsigned int timestamp;
     unsigned int expiredate;
-    gcry_mpi_t mpi[4];
+    gcry_mpi_t mpi[MAX_CDK_PK_PARTS];
     unsigned is_revoked:1;
     unsigned is_invalid:1;
     unsigned has_expired:1;
@@ -454,7 +461,7 @@ struct cdk_pkt_seckey_s {
         unsigned char ivlen;
     } protect;
     unsigned short csum;
-    gcry_mpi_t mpi[4];
+    gcry_mpi_t mpi[MAX_CDK_PK_PARTS];
     unsigned char * encdata;
     size_t enclen;
     unsigned char is_protected;
@@ -484,7 +491,7 @@ struct cdk_pkt_pubkey_enc_s {
     unsigned int keyid[2];
     int throw_keyid;
     unsigned char pubkey_algo;
-    gcry_mpi_t mpi[2];
+    gcry_mpi_t mpi[MAX_CDK_DATA_PARTS];
 };
 typedef struct cdk_pkt_pubkey_enc_s * cdk_pkt_pubkey_enc_t;
 
@@ -561,12 +568,21 @@ typedef void (*cdk_log_fnc_t) (void *, int, const char *, va_list);
 void cdk_set_log_level (int lvl);
 void cdk_set_log_handler (cdk_log_fnc_t logfnc, void *opaque);
 const char* cdk_strerror (int ec);
+
+/* Allow the user to set custom hooks for memory allocation.
+   If this function is not used, the standard allocation functions
+   will be used. Extra care must be taken for the 'secure' alloc
+   function. */
 void cdk_set_malloc_hooks (void *(*new_alloc_func) (size_t n),
                            void *(*new_alloc_secure_func) (size_t n),
                            void *(*new_realloc_func) (void *p, size_t n),
                            void *(*new_calloc_func) (size_t m, size_t n),
                            void (*new_free_func) (void *));
+                          
+/* Return 1 if the malloc hooks were already set via the function above. */
 int cdk_malloc_hook_initialized (void);
+
+/* Standard memory wrapper. */
 void *cdk_malloc (size_t size);
 void *cdk_calloc (size_t n, size_t m);
 void *cdk_realloc (void * ptr, size_t size);
@@ -584,8 +600,8 @@ void cdk_lib_startup (void);
    to allow the lib to cleanup its internal structures. */
 void cdk_lib_shutdown (void);
 
-/* session handle routines */
-cdk_error_t cdk_handle_new( cdk_ctx_t * r_ctx );
+/* Session handle routines */
+cdk_error_t cdk_handle_new (cdk_ctx_t *r_ctx);
 void cdk_handle_free (cdk_ctx_t c);
 
 /* Set the key database handle for the given session handle.
@@ -609,12 +625,18 @@ void cdk_handle_set_passphrase_cb (cdk_ctx_t hd,
                                    void *cb_value);
 
 /* shortcuts for some controls */
+
+/* Enable or disable armor output. */
 #define cdk_handle_set_armor(a, val) \
   cdk_handle_control ((a), CDK_CTLF_SET, CDK_CTL_ARMOR, (val))
 
-#define cdk_handle_set_compress (a, algo, level) \
+/* Set the compression algorithm and level. 0 means disable compression. */
+#define cdk_handle_set_compress(a, algo, level) \
   cdk_handle_control ((a), CDK_CTLF_SET, CDK_CTL_COMPRESS, (algo), (level))
 
+/* Activate partial bodies for the output. This is needed if the length
+   of the data is not known in advance or for the use with sockets 
+   or pipes. */
 #define cdk_handle_set_blockmode(a, val) \
   cdk_handle_control ((a), CDK_CTLF_SET, CDK_CTL_BLOCKMODE_ON, (val))
 
@@ -652,6 +674,8 @@ typedef struct cdk_verify_result_s *cdk_verify_result_t;
 cdk_verify_result_t cdk_handle_verify_get_result (cdk_ctx_t hd);
 
 /* Raw packet routines. */
+
+/* Allocate a new packet or a new packet with the given packet type. */
 cdk_error_t cdk_pkt_new (cdk_packet_t *r_pkt);
 cdk_error_t cdk_pkt_alloc (cdk_packet_t *r_pkt, int pkttype);
 
@@ -690,25 +714,42 @@ const unsigned char* cdk_key_desig_revoker_walk (cdk_desig_revoker_t root,
 #define is_ELG(a) ((a) == CDK_PK_ELG_E)
 #define is_DSA(a) ((a) == CDK_PK_DSA)
 
+/* Encrypt the given session key @SK with the public key @PK
+   and write the contents into the packet @PKE. */
 cdk_error_t cdk_pk_encrypt (cdk_pubkey_t pk, cdk_pkt_pubkey_enc_t pke,
-                           gcry_mpi_t esk);
+                           gcry_mpi_t sk);
+                           
+/* Decrypt the given encrypted session key in @PKE with the secret key
+   @SK and store it in @R_SK. */
 cdk_error_t cdk_pk_decrypt (cdk_seckey_t sk, cdk_pkt_pubkey_enc_t pke,
                             gcry_mpi_t *r_sk);
+                           
+/* Sign the given message digest @MD with the secret key @SK and
+   store the signature in the packet @SIG. */
 cdk_error_t cdk_pk_sign (cdk_seckey_t sk, cdk_pkt_signature_t sig,
-                         const unsigned char * md);
+                         const unsigned char *md);
+                        
+/* Verify the given signature in @SIG with the public key @PK
+   and compare it against the message digest @MD. */
 cdk_error_t cdk_pk_verify (cdk_pubkey_t pk, cdk_pkt_signature_t sig,
-                          const unsigned char * md);
+                          const unsigned char *md);
                           
 /* Use cdk_pk_get_npkey() and cdk_pk_get_nskey to find out how much
    multiprecision integers a key consists of. */
+   
+/* Return a multi precision integer of the public key with the index @IDX
+   in the buffer @BUF. @R_NWRITTEN will contain the length in octets.
+   Optional @R_NBITS may contain the size in bits. */
 cdk_error_t cdk_pk_get_mpi (cdk_pubkey_t pk, size_t idx,
                            unsigned char *buf, size_t buflen,
                            size_t *r_nwritten, size_t *r_nbits);
+
+/* Same as the function above but of the secret key. */
 cdk_error_t cdk_sk_get_mpi (cdk_seckey_t sk, size_t idx,
                            unsigned char * buf, size_t buflen,
                            size_t *r_nwritten, size_t *r_nbits);
                            
-/* Helper to get the exact number of multiprecision integers 
+/* Helper to get the exact number of multi precision integers 
    for the given object. */
 int cdk_pk_get_nbits (cdk_pubkey_t pk);
 int cdk_pk_get_npkey (int algo);
@@ -724,7 +765,7 @@ unsigned int cdk_pk_fingerprint_get_keyid (const unsigned char *fpr,
 unsigned int cdk_pk_get_keyid (cdk_pubkey_t pk, unsigned int *keyid);
 unsigned int cdk_sk_get_keyid (cdk_seckey_t sk, unsigned int *keyid);
 unsigned int cdk_sig_get_keyid (cdk_pkt_signature_t sig,
-                                 unsigned int * keyid);
+                                unsigned int *keyid);
                                 
 /* Key release functions. */
 void cdk_pk_release (cdk_pubkey_t pk);
@@ -732,7 +773,9 @@ void cdk_sk_release (cdk_seckey_t sk);
                                 
 /* Secret key related functions. */                             
 cdk_error_t cdk_sk_unprotect (cdk_seckey_t sk, const char *pw);
-cdk_error_t cdk_sk_protect( cdk_seckey_t sk, const char *pw);
+cdk_error_t cdk_sk_protect (cdk_seckey_t sk, const char *pw);
+
+/* Create a public key with the data from the secret key @SK. */
 cdk_error_t cdk_pk_from_secret_key (cdk_seckey_t sk,
                                     cdk_pubkey_t *ret_pk);
 
@@ -838,9 +881,12 @@ int cdk_stream_peek (cdk_stream_t inp, unsigned char *buf, size_t buflen);
    functions should be preferred. */
 cdk_error_t cdk_keydb_new (cdk_keydb_hd_t *r_hd, int type, void *data,
                            size_t count);
-                          
+
+/* Create a new key db handle from a memory buffer. */
 cdk_error_t cdk_keydb_new_from_mem (cdk_keydb_hd_t *r_hd, int secret,
                                    const void *data, size_t datlen);
+
+/* Create a new key db which uses an existing file. */
 cdk_error_t cdk_keydb_new_from_file (cdk_keydb_hd_t *r_hd, int secret,
                                     const char *fname);
                                     
@@ -853,31 +899,60 @@ cdk_error_t cdk_keydb_new_from_stream (cdk_keydb_hd_t *r_hd, int secret,
 /* Check that a secret key with the given key ID is available. */
 cdk_error_t cdk_keydb_check_sk (cdk_keydb_hd_t hd, unsigned int *keyid);
 
+/* Prepare the key db search. */
 cdk_error_t cdk_keydb_search_start (cdk_keydb_hd_t hd, int type, void *desc);
+
+/* Return a key which matches a valid description given in 
+   cdk_keydb_search_start(). */
 cdk_error_t cdk_keydb_search (cdk_keydb_hd_t hd, cdk_kbnode_t *ret_key);
-void cdk_keydb_free( cdk_keydb_hd_t hd );
-cdk_error_t cdk_keydb_get_bykeyid( cdk_keydb_hd_t hd, unsigned int * keyid,
-                                   cdk_kbnode_t * ret_pk );
-cdk_error_t cdk_keydb_get_byfpr( cdk_keydb_hd_t hd, const unsigned char * fpr,
-                                 cdk_kbnode_t * ret_pk );
-cdk_error_t cdk_keydb_get_bypattern( cdk_keydb_hd_t hd, const char * patt,
-                                     cdk_kbnode_t * ret_pk );
-cdk_error_t cdk_keydb_get_pk( cdk_keydb_hd_t khd, unsigned int * keyid,
-                      cdk_pubkey_t* ret_pk );
-cdk_error_t cdk_keydb_get_sk( cdk_keydb_hd_t khd, unsigned int * keyid,
-                              cdk_seckey_t* ret_sk );
+
+/* Release the key db handle and all its resources. */
+void cdk_keydb_free (cdk_keydb_hd_t hd);
+
+/* The following functions will try to find a key in the given key
+   db handle either by keyid, by fingerprint or by some pattern. */
+cdk_error_t cdk_keydb_get_bykeyid (cdk_keydb_hd_t hd, unsigned int *keyid,
+                                   cdk_kbnode_t *ret_pk);
+cdk_error_t cdk_keydb_get_byfpr (cdk_keydb_hd_t hd, const unsigned char *fpr,
+                                 cdk_kbnode_t *ret_pk);
+cdk_error_t cdk_keydb_get_bypattern (cdk_keydb_hd_t hd, const char *patt,
+                                     cdk_kbnode_t *ret_pk);
+
+/* These function, in contrast to most other key db functions, only
+   return the public or secret key packet without the additional
+   signatures and user IDs. */
+cdk_error_t cdk_keydb_get_pk (cdk_keydb_hd_t khd, unsigned int * keyid,
+                             cdk_pubkey_t *ret_pk);
+cdk_error_t cdk_keydb_get_sk (cdk_keydb_hd_t khd, unsigned int * keyid,
+                              cdk_seckey_t *ret_sk);
+                             
+/* Try to read the next key block from the given input stream.
+   The key will be returned in @RET_KEY on success. */
 cdk_error_t cdk_keydb_get_keyblock (cdk_stream_t inp, cdk_kbnode_t * ret_key);
+
+/* Rebuild the key db index if possible. */
 cdk_error_t cdk_keydb_idx_rebuild (cdk_keydb_hd_t hd);
+
+/* Export one or more keys from the given key db handle into
+   the stream @OUT. The export is done by substring search and
+   uses the string list @REMUSR for the pattern. */
 cdk_error_t cdk_keydb_export (cdk_keydb_hd_t hd, cdk_stream_t out,
                               cdk_strlist_t remusr);
+
+/* Import the given key node @knode into the key db. */
 cdk_error_t cdk_keydb_import (cdk_keydb_hd_t hd, cdk_kbnode_t knode);
 
 
-/* listing keys */
-cdk_error_t cdk_listkey_start( cdk_listkey_t * r_ctx, cdk_keydb_hd_t db,
-                               const char * patt, cdk_strlist_t fpatt );
-void cdk_listkey_close( cdk_listkey_t ctx );
-cdk_error_t cdk_listkey_next( cdk_listkey_t ctx, cdk_kbnode_t * ret_key );
+/* List or enumerate keys from a given key db handle. */
+
+/* Start the key list process. Either use @PATT for a pattern search
+   or @FPATT for a list of pattern. */
+cdk_error_t cdk_listkey_start (cdk_listkey_t *r_ctx, cdk_keydb_hd_t db,
+                               const char *patt, cdk_strlist_t fpatt);
+void cdk_listkey_close (cdk_listkey_t ctx);
+
+/* Return the next key which matches the pattern. */
+cdk_error_t cdk_listkey_next (cdk_listkey_t ctx, cdk_kbnode_t *ret_key);
 
 /*-- kbnode.c --*/
 cdk_kbnode_t cdk_kbnode_new (cdk_packet_t pkt);
@@ -912,6 +987,8 @@ cdk_error_t cdk_pk_check_sigs (cdk_kbnode_t knode, cdk_keydb_hd_t hd,
 cdk_error_t cdk_pk_check_self_sig (cdk_kbnode_t knode, int *r_status);
 
 /*-- keylist.c --*/
+/* Return a matching  algorithm from the given public key list. 
+   @PREFTYPE can be either sym-cipher/compress/digest. */
 int cdk_pklist_select_algo (cdk_keylist_t pkl, int preftype);
 int cdk_pklist_use_mdc (cdk_keylist_t pkl);
 cdk_error_t cdk_pklist_build (cdk_keylist_t *ret_pkl, cdk_keydb_hd_t hd,
@@ -920,7 +997,7 @@ void cdk_pklist_release (cdk_keylist_t pkl);
 cdk_error_t cdk_pklist_encrypt (cdk_keylist_t pkl, cdk_dek_t dek,
                                 cdk_stream_t out);
                                
-/* secret key list */
+/* Secret key lists */
 cdk_error_t cdk_sklist_build (cdk_keylist_t * ret_skl,
                               cdk_keydb_hd_t db, cdk_ctx_t hd,
                               cdk_strlist_t locusr,
@@ -933,15 +1010,27 @@ cdk_error_t cdk_sklist_write_onepass (cdk_keylist_t skl, cdk_stream_t outp,
                                       int sigclass, int mdalgo);
 
 /*-- encrypt.c --*/
+
+/* Encrypt the given stream @INP with the recipients given in @REMUSR.
+   If @REMUSR is NULL, symmetric encryption will be used. The output
+   will be written to @OUT. */
 cdk_error_t cdk_stream_encrypt (cdk_ctx_t hd, cdk_strlist_t remusr,
                                 cdk_stream_t inp, cdk_stream_t out);
+                               
+/* Decrypt the @INP stream into @OUT. */
 cdk_error_t cdk_stream_decrypt (cdk_ctx_t hd, cdk_stream_t inp, 
                                cdk_stream_t out);
-    
+
+/* Same as the function above but it works on files. */
 cdk_error_t cdk_file_encrypt (cdk_ctx_t hd, cdk_strlist_t remusr,
-                             const char * file, const char * output);
+                             const char *file, const char *output);
 cdk_error_t cdk_file_decrypt (cdk_ctx_t hd, const char * file,
-                              const char * output);
+                              const char *output);
+                             
+/* Generic function to transform data. The mode can be either sign,
+   verify, encrypt, decrypt, import or export. The meanings of the
+   parameters are similar to the functions above.
+   @OUTBUF will contain the output and @OUTSIZE the length of it. */
 cdk_error_t cdk_data_transform (cdk_ctx_t hd, enum cdk_crypto_mode_t mode,
                                 cdk_strlist_t locusr, cdk_strlist_t remusr,
                                 const void * inbuf, size_t insize,
@@ -949,18 +1038,28 @@ cdk_error_t cdk_data_transform (cdk_ctx_t hd, enum cdk_crypto_mode_t mode,
                                 int modval);
 
 /*-- sign.c --*/
+/* Sign the stream @INP. Optionally, the output will be encrypted
+   if @REMUSR is not NULL and the @ENCRYPTFLAG is set. 
+   The output will be written to @OUT.
+   @LOCUSR contains one ore more pattern for the secret key(s) to use. */
 cdk_error_t cdk_stream_sign (cdk_ctx_t hd, cdk_stream_t inp, cdk_stream_t out,
                              cdk_strlist_t locusr, cdk_strlist_t remusr,
-                             int encryptflag, int sigmode );
+                             int encryptflag, int sigmode);
+
+/* Same as the function above but it works on files. */
 cdk_error_t cdk_file_sign (cdk_ctx_t hd, cdk_strlist_t locusr,
                            cdk_strlist_t remusr,
-                           const char * file, const char * output,
+                           const char *file, const char *output,
                            int sigmode, int encryptflag);
 
 /*-- verify.c --*/
 cdk_error_t cdk_stream_verify (cdk_ctx_t hd, cdk_stream_t inp,
                               cdk_stream_t data,
                                cdk_stream_t out);
+                              
+/* Verify the given file @FILE. For a detached signature, @DATA_FILE
+   contains the actual file data and @FILE is only the signature.
+   If the @OUTPUT is not NULL, the plaintext will be written to this file. */
 cdk_error_t cdk_file_verify (cdk_ctx_t hd, const char *file,
                             const char *data_file, const char *output);
 
@@ -968,28 +1067,30 @@ cdk_error_t cdk_file_verify (cdk_ctx_t hd, const char *file,
 int cdk_trustdb_get_validity (cdk_stream_t inp, cdk_pkt_userid_t id,
                               int *r_val);
 int cdk_trustdb_get_ownertrust (cdk_stream_t inp, cdk_pubkey_t pk,
-                                int * r_val, int * r_flags);
+                                int *r_val, int *r_flags);
 
 /*-- misc.c --*/
 void cdk_strlist_free (cdk_strlist_t sl);
 cdk_strlist_t cdk_strlist_add (cdk_strlist_t * list, const char * string);
-const char * cdk_strlist_walk (cdk_strlist_t root, cdk_strlist_t * context);
+cdk_strlist_t cdk_strlist_next (cdk_strlist_t root, const char **r_str);
 const char * cdk_check_version (const char * req_version);
 /* UTF8 */
 char* cdk_utf8_encode (const char * string);
 char* cdk_utf8_decode (const char * string, size_t length, int delim);
 
 /*-- keyserver.c --*/
-cdk_error_t cdk_keyserver_recv_key (const char * host, int port,
-                                    const unsigned char * keyid, int kid_type,
-                                    cdk_kbnode_t * r_key);
+/* Try to receive the key, which has the key ID @KEYID, from the
+   keyserver host @HOST and the port @PORT. */
+cdk_error_t cdk_keyserver_recv_key (const char *host, int port,
+                                    const unsigned char *keyid, int kid_type,
+                                    cdk_kbnode_t *r_key);
 
 /*-- keygen.c --*/
 cdk_error_t cdk_keygen_new (cdk_keygen_ctx_t * r_hd);
 void cdk_keygen_free (cdk_keygen_ctx_t hd);
-cdk_error_t cdk_keygen_set_prefscdk_keygen_ctx_t hd,
+cdk_error_t cdk_keygen_set_prefs (cdk_keygen_ctx_t hd,
                                   enum cdk_pref_type_t type,
-                                  const unsigned char * array, size_t n );
+                                  const unsigned char * array, size_t n);
 cdk_error_t cdk_keygen_set_algo_info( cdk_keygen_ctx_t hd, int type,
                                      int usage, enum cdk_pubkey_algo_t algo, 
                                      unsigned int bits );
index 77eec0020e19519ff78822e539c999f0d484e9cb..d8c23bbb6394d59125bb334b724cd4f5f121e07a 100644 (file)
@@ -298,7 +298,8 @@ cdk_pk_encrypt (cdk_pubkey_t pk, cdk_pkt_pubkey_enc_t pke,
                 gcry_mpi_t esk)
 {
   gcry_sexp_t s_data = NULL, s_pkey = NULL, s_ciph = NULL;
-  int rc;
+  gcry_error_t err;
+  cdk_error_t rc;
   
   if (!pk || !esk || !pke)
     return CDK_Inv_Value;
@@ -310,7 +311,11 @@ cdk_pk_encrypt (cdk_pubkey_t pk, cdk_pkt_pubkey_enc_t pke,
   if (!rc)
     rc = pubkey_to_sexp (&s_pkey, pk);
   if (!rc)
-    rc = gcry_pk_encrypt (&s_ciph, s_data, s_pkey);
+    {     
+      err = gcry_pk_encrypt (&s_ciph, s_data, s_pkey);
+      if (err)
+       return map_gcry_error (err);
+    }
   if (!rc)
     rc = sexp_to_pubenc (pke, s_ciph);
   
@@ -595,7 +600,7 @@ mpi_to_buffer (gcry_mpi_t a, byte *buf, size_t buflen,
 
   
 cdk_error_t
-cdk_pk_get_mpi (cdk_pkt_pubkey_t pk, size_t idx,
+cdk_pk_get_mpi (cdk_pubkey_t pk, size_t idx,
                 byte *buf, size_t buflen, size_t *r_nwritten, size_t *r_nbits)
 {
   if (!pk || !r_nwritten)
@@ -859,7 +864,7 @@ cdk_sk_protect (cdk_pkt_seckey_t sk, const char *pass)
  * Create a new public key from a secret key.
  **/
 cdk_error_t
-cdk_pk_from_secret_key (cdk_pkt_seckey_t sk, cdk_pkt_pubkey_t *ret_pk)
+cdk_pk_from_secret_key (cdk_pkt_seckey_t sk, cdk_pubkey_t *ret_pk)
 {
   if (!sk)
     return CDK_Inv_Value;
@@ -939,7 +944,7 @@ _cdk_sk_get_csum (cdk_pkt_seckey_t sk)
 
 
 cdk_error_t
-cdk_pk_get_fingerprint (cdk_pkt_pubkey_t pk, byte *fpr)
+cdk_pk_get_fingerprint (cdk_pubkey_t pk, byte *fpr)
 {
   gcry_md_hd_t hd;
   int md_algo;
@@ -989,7 +994,7 @@ cdk_pk_fingerprint_get_keyid (const byte *fpr, size_t fprlen, u32 *keyid)
 
 
 u32
-cdk_pk_get_keyid (cdk_pkt_pubkey_t pk, u32 *keyid)
+cdk_pk_get_keyid (cdk_pubkey_t pk, u32 *keyid)
 {
   u32 lowbits = 0;
   byte buf[24];
@@ -1120,7 +1125,7 @@ _cdk_pkt_get_fingerprint (cdk_packet_t pkt, byte *fpr)
  * (GCRYSEXP_FMT_CANON).
  **/
 cdk_error_t
-cdk_pubkey_to_sexp (cdk_pkt_pubkey_t pk, char **sexp, size_t * len)
+cdk_pubkey_to_sexp (cdk_pubkey_t pk, char **sexp, size_t * len)
 {
   char *buf;
   size_t sexp_len;
index 5242278251af0320723102ea0499b4160cc430e2..992d84ab9661c02d72d77b9dffe6f23499d0d42b 100644 (file)
  * GNU General Public License for more details. 
  */
 #ifdef HAVE_CONFIG_H
-# include <config.h>
+#include <config.h>
 #endif
 #include <string.h>
 #include <stdio.h>
+#include <time.h>
 #include <assert.h>
 
 #include "opencdk.h"
@@ -44,7 +45,7 @@ read_32 (cdk_stream_t s)
   byte buf[4];
   size_t nread;
   
-  assert (buf != NULL);
+  assert (s != NULL);
 
   stream_read (s, buf, 4, &nread);
   if (nread != 4)
@@ -73,15 +74,13 @@ static int
 read_s2k (cdk_stream_t inp, cdk_s2k_t s2k)
 {
   size_t nread;
-  cdk_error_t rc;
 
   if (!inp || !s2k)
     return CDK_Inv_Value;
 
   if (DEBUG_PKT)
-    _cdk_log_debug ("** read S2K part\n");
+    _cdk_log_debug ("read_s2k:\n");
 
-  rc = 0;
   s2k->mode = cdk_stream_getc (inp);
   if (cdk_stream_eof (inp))
     return CDK_Inv_Packet;
@@ -94,11 +93,10 @@ read_s2k (cdk_stream_t inp, cdk_s2k_t s2k)
   else if (s2k->mode == CDK_S2K_SALTED || 
           s2k->mode == CDK_S2K_ITERSALTED)
     {
-      rc = stream_read (inp, s2k->salt, DIM (s2k->salt), &nread);
-      if (rc)
+      if (stream_read (inp, s2k->salt, DIM (s2k->salt), &nread))
        return CDK_Inv_Packet;
       if (nread != DIM (s2k->salt))
-       return CDK_Too_Short;
+       return CDK_Inv_Packet;
       if (s2k->mode == CDK_S2K_ITERSALTED)
        {
          s2k->count = cdk_stream_getc (inp);
@@ -108,34 +106,38 @@ read_s2k (cdk_stream_t inp, cdk_s2k_t s2k)
     }
   else
     return CDK_Inv_Mode;
-  return rc;
+  return 0;
 }
 
 
 static cdk_error_t
-read_mpi (cdk_stream_t inp, gcry_mpi_t * ret_m, int secure)
+read_mpi (cdk_stream_t inp, gcry_mpi_t *ret_m, int secure)
 {
   gcry_mpi_t m;
+  gcry_error_t err;
   byte buf[MAX_MPI_BYTES+2];
   size_t nread, nbits;
   cdk_error_t rc;
-  gcry_error_t err;
   
   if (!inp || !ret_m)
     return CDK_Inv_Value;
   
-  if (DEBUG_PKT)
-    _cdk_log_debug ("** read MPI part\n");
-  
   *ret_m = NULL;
   nbits = read_16 (inp);
   nread = (nbits+7)/8;
+  
   if (nbits > MAX_MPI_BITS || nbits == 0)
-    return CDK_MPI_Error; /* Sanity check */
+    {
+      _cdk_log_debug ("read_mpi: too large %d bits\n", nbits);
+      return CDK_MPI_Error; /* Sanity check */
+    }  
   
   rc = stream_read (inp, buf+2, nread, &nread);
   if (!rc && nread != ((nbits+7)/8))
-    return CDK_MPI_Error;
+    {
+      _cdk_log_debug ("read_mpi: too short %d < %d\n", nread, (nbits+7)/8);
+      return CDK_MPI_Error;
+    }  
   
   buf[0] = nbits >> 8;
   buf[1] = nbits >> 0;
@@ -148,6 +150,7 @@ read_mpi (cdk_stream_t inp, gcry_mpi_t * ret_m, int secure)
   return rc;
 }
 
+
 /* Read the encoded packet length directly from the file 
    object INP and return it. Reset RET_PARTIAL if this is
    the last packet in block mode. */
@@ -186,13 +189,13 @@ _cdk_pkt_read_len (FILE *inp, size_t *ret_partial)
 
 static cdk_error_t
 read_encrypted (cdk_stream_t inp, size_t pktlen, cdk_pkt_encrypted_t enc,
-               int partial, int is_mdc)
+               int is_partial, int is_mdc)
 {
   if (!inp || !enc)
     return CDK_Inv_Value;
 
   if (DEBUG_PKT)
-    _cdk_log_debug ("** read encrypted packet %d bytes\n", pktlen);
+    _cdk_log_debug ("read_encrypted: %d octets\n", pktlen);
   
   if (is_mdc) 
     {
@@ -205,7 +208,7 @@ read_encrypted (cdk_stream_t inp, size_t pktlen, cdk_pkt_encrypted_t enc,
   /* The packet must at least contain blocksize + 2 octets. */
   if (pktlen < 10)
     return CDK_Inv_Packet;
-  if (partial)
+  if (is_partial)
     _cdk_stream_set_blockmode (inp, pktlen);
   enc->len = pktlen;
   enc->buf = inp;
@@ -217,14 +220,14 @@ static cdk_error_t
 read_symkey_enc (cdk_stream_t inp, size_t pktlen, cdk_pkt_symkey_enc_t ske)
 {
   cdk_s2k_t s2k;
-  size_t nread, minlen;
-  cdk_error_t rc;
+  size_t minlen;
+  size_t nread, nleft;
   
   if (!inp || !ske)
     return CDK_Inv_Value;
   
   if (DEBUG_PKT)
-    _cdk_log_debug ("** read symmetric key encrypted packet\n");
+    _cdk_log_debug ("read_symkey_enc: %d octets\n", pktlen);
   
   ske->version = cdk_stream_getc (inp);
   if (ske->version != 4 || cdk_stream_eof (inp))
@@ -250,11 +253,10 @@ read_symkey_enc (cdk_stream_t inp, size_t pktlen, cdk_pkt_symkey_enc_t ske)
   s2k->hash_algo = cdk_stream_getc (inp);
   if (s2k->mode == CDK_S2K_SALTED || s2k->mode == CDK_S2K_ITERSALTED)
     {
-      rc = stream_read (inp, s2k->salt, DIM (s2k->salt), &nread);
-      if (rc)
+      if (stream_read (inp, s2k->salt, DIM (s2k->salt), &nread))
        return CDK_Inv_Packet;
       if (nread != DIM (s2k->salt))
-       return CDK_Too_Short;
+       return CDK_Inv_Packet;
       
       if (s2k->mode == CDK_S2K_ITERSALTED)
        s2k->count = cdk_stream_getc (inp);
@@ -265,11 +267,12 @@ read_symkey_enc (cdk_stream_t inp, size_t pktlen, cdk_pkt_symkey_enc_t ske)
      the buffer. The maximal key length is 256-bit. */
   if (ske->seskeylen > DIM (ske->seskey))
     return CDK_Inv_Packet;
+  nleft = ske->seskeylen;
   for (nread = 0; nread < ske->seskeylen; nread++)
     {
       ske->seskey[nread] = cdk_stream_getc (inp);
-      if (cdk_stream_eof (inp))
-       return CDK_Too_Short;
+      if (cdk_stream_eof (inp) && --nleft > 0)
+       return CDK_Inv_Packet;
     }
   
   return 0;
@@ -280,13 +283,12 @@ static cdk_error_t
 read_pubkey_enc (cdk_stream_t inp, size_t pktlen, cdk_pkt_pubkey_enc_t pke)
 {
   size_t i, nenc;
-  cdk_error_t rc;
 
   if (!inp || !pke)
     return CDK_Inv_Value;
   
   if (DEBUG_PKT)
-    _cdk_log_debug ("** read public key encrypted packet\n");
+    _cdk_log_debug ("read_pubkey_enc: %d octets\n", pktlen);
   
   if (pktlen < 12)
     return CDK_Inv_Packet;
@@ -303,7 +305,7 @@ read_pubkey_enc (cdk_stream_t inp, size_t pktlen, cdk_pkt_pubkey_enc_t pke)
     return CDK_Inv_Algo;
   for (i = 0; i < nenc; i++) 
     {
-      rc = read_mpi (inp, &pke->mpi[i], 0);
+      cdk_error_t rc = read_mpi (inp, &pke->mpi[i], 0);
       if (rc)
        return rc;
     }
@@ -312,6 +314,7 @@ read_pubkey_enc (cdk_stream_t inp, size_t pktlen, cdk_pkt_pubkey_enc_t pke)
 }
 
 
+
 static cdk_error_t
 read_mdc (cdk_stream_t inp, cdk_pkt_mdc_t mdc)
 {
@@ -322,7 +325,7 @@ read_mdc (cdk_stream_t inp, cdk_pkt_mdc_t mdc)
     return CDK_Inv_Value;
   
   if (DEBUG_PKT)
-    _cdk_log_debug ("** read MDC packet\n");
+    _cdk_log_debug ("read_mdc:\n");
   
   rc = stream_read (inp, mdc->hash, 20, &n);
   if (rc)
@@ -339,7 +342,7 @@ read_compressed (cdk_stream_t inp, size_t pktlen, cdk_pkt_compressed_t c)
     return CDK_Inv_Value;
   
   if (DEBUG_PKT)
-    _cdk_log_debug ("** read compressed packet\n");
+    _cdk_log_debug ("read_compressed: %d octets\n", pktlen);
   
   c->algorithm = cdk_stream_getc (inp);
   if (c->algorithm > 3)
@@ -358,16 +361,15 @@ read_compressed (cdk_stream_t inp, size_t pktlen, cdk_pkt_compressed_t c)
 
 
 static cdk_error_t
-read_public_key (cdk_stream_t inp, cdk_pkt_pubkey_t pk)
+read_public_key (cdk_stream_t inp, size_t pktlen, cdk_pkt_pubkey_t pk)
 {
-  cdk_error_t rc;
   size_t i, ndays, npkey;
   
   if (!inp || !pk)
     return CDK_Inv_Value;
   
   if (DEBUG_PKT)
-    _cdk_log_debug( "** read public key packet\n" );
+    _cdk_log_debug ("read_public_key: %d octets\n", pktlen);
   
   pk->is_invalid = 1; /* default to detect missing self signatures */
   pk->is_revoked = 0;
@@ -387,28 +389,30 @@ read_public_key (cdk_stream_t inp, cdk_pkt_pubkey_t pk)
   pk->pubkey_algo = cdk_stream_getc (inp);
   npkey = cdk_pk_get_npkey (pk->pubkey_algo);
   if (!npkey)
-    return CDK_Inv_Algo;
-  rc = 0;
+    {
+      _cdk_log_debug ("invalid public key algorithm %d\n", pk->pubkey_algo);
+      return CDK_Inv_Algo;
+    }  
   for (i = 0; i < npkey; i++)
     {
-      rc = read_mpi (inp, &pk->mpi[i], 0);
+      cdk_error_t rc = read_mpi (inp, &pk->mpi[i], 0);
       if (rc)
-       break;
+       return rc;
     }
   
   /* These values are just for the first run and should be
      replaced with the actual key flags from the self signature. */
   pk->pubkey_usage = _cdk_pk_algo_usage (pk->pubkey_algo);
-  return rc;
+  return 0;
 }
 
 
 static cdk_error_t
-read_public_subkey (cdk_stream_t inp, cdk_pkt_pubkey_t pk)
+read_public_subkey (cdk_stream_t inp, size_t pktlen, cdk_pkt_pubkey_t pk)
 {
   if (!inp || !pk)
     return CDK_Inv_Value;
-  return read_public_key (inp, pk);
+  return read_public_key (inp, pktlen, pk);
 }
 
 
@@ -423,10 +427,10 @@ read_secret_key (cdk_stream_t inp, size_t pktlen, cdk_pkt_seckey_t sk)
     return CDK_Inv_Value;
 
   if (DEBUG_PKT)
-    _cdk_log_debug ("** read secret key\n");
+    _cdk_log_debug ("read_secret_key: %d octets\n", pktlen);
 
   p1 = cdk_stream_tell (inp);
-  rc = read_public_key (inp, sk->pk);
+  rc = read_public_key (inp, pktlen, sk->pk);
   if (rc)
     return rc;
 
@@ -529,15 +533,17 @@ read_secret_subkey (cdk_stream_t inp, size_t pktlen, cdk_pkt_seckey_t sk)
 static cdk_error_t
 read_attribute (cdk_stream_t inp, size_t pktlen, cdk_pkt_userid_t attr)
 {
-  size_t nread;
-  byte *buf;
   const byte *p;
-  size_t len;
+  byte *buf;
+  size_t len, nread;
   cdk_error_t rc;
   
   if (!inp || !attr || !pktlen)
     return CDK_Inv_Value;
   
+  if (DEBUG_PKT)
+    _cdk_log_debug ("read_attribute: %d octets\n", pktlen);
+  
   strcpy (attr->name, "[attribute]");
   attr->len = strlen (attr->name);
   buf = cdk_calloc (1, pktlen);
@@ -550,12 +556,11 @@ read_attribute (cdk_stream_t inp, size_t pktlen, cdk_pkt_userid_t attr)
       return CDK_Inv_Packet;
     }
   p = buf;
-  len = *p++;
+  len = *p++; pktlen--;
   if (len == 255)
     {
       len = _cdk_buftou32 (p);
-      p += 4;
-      pktlen -= 4;
+      p += 4; pktlen -= 4;
     }
   else if (len >= 192)
     {
@@ -563,31 +568,26 @@ read_attribute (cdk_stream_t inp, size_t pktlen, cdk_pkt_userid_t attr)
        {
          cdk_free (buf);
          return CDK_Inv_Packet;
-       }
+       }      
       len = ((len - 192) << 8) + *p + 192;
-      p++;
-      pktlen--;
+      p++; pktlen--;
     }
-  if (*p != 1) 
-    { /* ATTRIBUTE IMAGE */
-      cdk_free (buf);
-      return CDK_Inv_Packet;
-    }
-  p++;
-
-  /* There is no maximum for the attribute data length
-     but even so we dissalow images larger than 100K. */
-  if (len > 100000)
+  
+  if (*p != 1) /* Currently only 1, meaning an image, is defined. */
     {
       cdk_free (buf);
       return CDK_Inv_Packet;
-    }  
+    }
+  p++; len--;
+  
+  if (pktlen - (len+1) > 0)
+    return CDK_Inv_Packet;
   attr->attrib_img = cdk_calloc (1, len);
   if (!attr->attrib_img)
     {
       cdk_free (buf);
       return CDK_Out_Of_Core;
-    }  
+    } 
   attr->attrib_len = len;
   memcpy (attr->attrib_img, p, len);
   cdk_free (buf);
@@ -607,7 +607,7 @@ read_user_id (cdk_stream_t inp, size_t pktlen, cdk_pkt_userid_t user_id)
     return CDK_Inv_Packet;
   
   if (DEBUG_PKT)
-    _cdk_log_debug ("** read user ID packet\n");
+    _cdk_log_debug ("read_user_id: %lu octets\n", pktlen);  
   
   user_id->len = pktlen;
   rc = stream_read (inp, user_id->name, pktlen, &nread);
@@ -632,7 +632,7 @@ read_subpkt( cdk_stream_t inp, cdk_subpkt_t * r_ctx, size_t * r_nbytes )
     return CDK_Inv_Value;
   
   if (DEBUG_PKT)
-    _cdk_log_debug ("** read sub packet");
+    _cdk_log_debug ("read_subpkt:\n");
   
   n = 0;
   *r_nbytes = 0;
@@ -657,13 +657,12 @@ read_subpkt( cdk_stream_t inp, cdk_subpkt_t * r_ctx, size_t * r_nbytes )
     return CDK_Inv_Packet;
   
   node = cdk_subpkt_new (size);
-  if (DEBUG_PKT)
-    _cdk_log_debug (" `%d' bytes\n", size);
-  
   if (!node)
-    return CDK_Out_Of_Core;
+    return CDK_Out_Of_Core;  
   node->size = size;
   node->type = cdk_stream_getc (inp);
+  if (DEBUG_PKT)
+    _cdk_log_debug (" %d octets %d type\n", node->size, node->type);
   n++;
   node->size--;
   rc = stream_read (inp, node->d, node->size, &nread);
@@ -686,7 +685,7 @@ read_onepass_sig (cdk_stream_t inp, size_t pktlen, cdk_pkt_onepass_sig_t sig)
     return CDK_Inv_Value;
   
   if (DEBUG_PKT)
-    _cdk_log_debug ("** read one pass signature packet\n");
+    _cdk_log_debug ("read_onepass_sig: %d octets\n", pktlen);
   
   if (pktlen != 13)
     return CDK_Inv_Packet;
@@ -709,7 +708,7 @@ parse_sig_subpackets (cdk_pkt_signature_t sig)
   cdk_subpkt_t node;
   
   /* Setup the standard packet entries, so we can use V4
-   signatures similar to V3. */
+     signatures similar to V3. */
   for (node = sig->unhashed; node; node = node->next)
     {
       if (node->type == CDK_SIGSUBPKT_ISSUER && node->size >= 8)
@@ -732,7 +731,7 @@ parse_sig_subpackets (cdk_pkt_signature_t sig)
        {
          sig->expiredate = _cdk_buftou32 (node->d);
          if (sig->expiredate > 0 &&
-             sig->expiredate < _cdk_timestamp ())
+             sig->expiredate < (u32)time (NULL))
            sig->flags.expired = 1;
        }
       else if (node->type == CDK_SIGSUBPKT_POLICY)
@@ -747,6 +746,7 @@ parse_sig_subpackets (cdk_pkt_signature_t sig)
   if (sig->sig_class == 0x1F)
     {
       cdk_desig_revoker_t r, rnode;
+      
       for (node = sig->hashed; node; node = node->next)
        {
          if (node->type == CDK_SIGSUBPKT_REV_KEY) 
@@ -774,6 +774,7 @@ parse_sig_subpackets (cdk_pkt_signature_t sig)
   return 0;
 }
 
+
 static cdk_error_t
 read_signature (cdk_stream_t inp, size_t pktlen, cdk_pkt_signature_t sig)
 {
@@ -785,9 +786,9 @@ read_signature (cdk_stream_t inp, size_t pktlen, cdk_pkt_signature_t sig)
     return CDK_Inv_Value;
   
   if (DEBUG_PKT)
-    _cdk_log_debug( "** read signature packet\n" );
+    _cdk_log_debug ("read_signature: %d octets\n", pktlen);
   
-  if (pktlen < 10)
+  if (pktlen < 16)
     return CDK_Inv_Packet;
   sig->version = cdk_stream_getc (inp);
   if (sig->version < 2 || sig->version > 4)
@@ -866,8 +867,8 @@ read_signature (cdk_stream_t inp, size_t pktlen, cdk_pkt_signature_t sig)
 
 
 static cdk_error_t
-read_literal (cdk_stream_t inp, size_t pktlen, cdk_pkt_literal_t *ret_pt,
-              int partial)
+read_literal (cdk_stream_t inp, size_t pktlen, 
+             cdk_pkt_literal_t *ret_pt, int is_partial)
 {
   cdk_pkt_literal_t pt = *ret_pt;
   size_t nread ;
@@ -877,7 +878,7 @@ read_literal (cdk_stream_t inp, size_t pktlen, cdk_pkt_literal_t *ret_pt,
     return CDK_Inv_Value;
   
   if (DEBUG_PKT)
-    _cdk_log_debug ("** read literal packet\n");
+    _cdk_log_debug ("read_literal: %d octets\n", pktlen);
   
   pt->mode = cdk_stream_getc (inp);
   if (pt->mode != 0x62 && pt->mode != 0x74)
@@ -886,7 +887,7 @@ read_literal (cdk_stream_t inp, size_t pktlen, cdk_pkt_literal_t *ret_pt,
     return CDK_Inv_Packet;
   
   pt->namelen = cdk_stream_getc (inp);
-  if (pt->namelen)
+  if (pt->namelen > 0)
     {
       *ret_pt = pt = cdk_realloc (pt, sizeof * pt + pt->namelen + 1);
       if (!pt)
@@ -898,9 +899,9 @@ read_literal (cdk_stream_t inp, size_t pktlen, cdk_pkt_literal_t *ret_pt,
        return CDK_Inv_Packet;
       pt->name[pt->namelen] = '\0';
     }
-    pt->timestamp = read_32 (inp);
+  pt->timestamp = read_32 (inp);
   pktlen = pktlen - 6 - pt->namelen;
-  if (partial)
+  if (is_partial)
     _cdk_stream_set_blockmode (inp, pktlen);
   pt->buf = inp;
   pt->len = pktlen;
@@ -956,7 +957,7 @@ read_new_length (cdk_stream_t inp,
     }
   else if (c == 255) 
     {
-      *r_len = read_32( inp );
+      *r_len = read_32 (inp);
       (*r_size) += 4; 
     }
   else 
@@ -967,7 +968,7 @@ read_new_length (cdk_stream_t inp,
 }
 
 
-/* Skip an unwanted packet. Use a large buffer to speed up the read process. */
+/* Skip the current packet body. */
 static void
 skip_packet (cdk_stream_t inp, size_t pktlen)
 {
@@ -1012,18 +1013,18 @@ cdk_pkt_read (cdk_stream_t inp, cdk_packet_t pkt)
   pktsize++;
   if (!(ctb & 0x80)) 
     {
-      _cdk_log_info ("no valid openpgp data found. "
+      _cdk_log_info ("cdk_pkt_read: no openpgp data found. "
                     "(ctb=%02X; fpos=%02X)\n",ctb, cdk_stream_tell (inp));
       return CDK_Inv_Packet;
   }
   
-  if (ctb & 0x40) 
-    { /* RFC2440 */
+  if (ctb & 0x40) /* RFC2440 packet format. */
+    {
       pkttype = ctb & 0x3f;
       is_newctb = 1;
     }
-    else 
-    { /* RFC1991 */
+    else /* the old RFC1991 packet format. */
+    {
       pkttype = ctb & 0x3f;
       pkttype >>= 2;
       is_newctb = 0;
@@ -1031,7 +1032,7 @@ cdk_pkt_read (cdk_stream_t inp, cdk_packet_t pkt)
   
   if (pkttype > 63)
     {
-      _cdk_log_info ("unknown packet type (%d)\n", pkttype);
+      _cdk_log_info ("cdk_pkt_read: unknown type %d\n", pkttype);
       return CDK_Inv_Packet;
     }
   
@@ -1050,11 +1051,11 @@ cdk_pkt_read (cdk_stream_t inp, cdk_packet_t pkt)
     {
     case CDK_PKT_ATTRIBUTE:
       pkt->pkt.user_id = cdk_calloc (1, sizeof *pkt->pkt.user_id
-                                    + pkt->pktlen);
+                                    + pkt->pktlen + 16 + 1);
       if (!pkt->pkt.user_id)
        return CDK_Out_Of_Core;
       rc = read_attribute (inp, pktlen, pkt->pkt.user_id);
-      pkt->pkttype = CDK_PKT_USER_ID; /* treated as an user id (??) */
+      pkt->pkttype = CDK_PKT_ATTRIBUTE;
       break;
       
     case CDK_PKT_USER_ID:
@@ -1069,14 +1070,14 @@ cdk_pkt_read (cdk_stream_t inp, cdk_packet_t pkt)
       pkt->pkt.public_key = cdk_calloc (1, sizeof *pkt->pkt.public_key);
       if (!pkt->pkt.public_key)
        return CDK_Out_Of_Core;
-      rc = read_public_key (inp, pkt->pkt.public_key);
+      rc = read_public_key (inp, pktlen, pkt->pkt.public_key);
       break;
       
     case CDK_PKT_PUBLIC_SUBKEY:
       pkt->pkt.public_key = cdk_calloc (1, sizeof *pkt->pkt.public_key);
       if (!pkt->pkt.public_key)
        return CDK_Out_Of_Core;
-      rc = read_public_subkey (inp, pkt->pkt.public_key);
+      rc = read_public_subkey (inp, pktlen,  pkt->pkt.public_key);
       break;
       
     case CDK_PKT_SECRET_KEY:
index 219891e1aae5f441a7b9c5e393f099edc27c5ea5..edd445e824716d8839fa92b6c5e2a9ec63b81037 100644 (file)
 #include "packet.h"
 
 
-/* Hash all multiprecision integers of the key PK with the given
+/* Hash all multi precision integers of the key PK with the given
    message digest context MD. */
 static int
-hash_mpibuf (cdk_pkt_pubkey_t pk, gcry_md_hd_t md, int usefpr)
+hash_mpibuf (cdk_pubkey_t pk, gcry_md_hd_t md, int usefpr)
 {
   byte buf[MAX_MPI_BYTES];
   size_t nbytes;
@@ -60,7 +60,7 @@ hash_mpibuf (cdk_pkt_pubkey_t pk, gcry_md_hd_t md, int usefpr)
    MD. The USEFPR param is only valid for version 3 keys because of
    the different way to calculate the fingerprint. */
 int
-_cdk_hash_pubkey (cdk_pkt_pubkey_t pk, gcry_md_hd_t md, int usefpr)
+_cdk_hash_pubkey (cdk_pubkey_t pk, gcry_md_hd_t md, int usefpr)
 {
   byte buf[12];
   u16 n;
@@ -188,26 +188,28 @@ _cdk_hash_sig_data (cdk_pkt_signature_t sig, gcry_md_hd_t md)
 static void
 cache_sig_result (cdk_pkt_signature_t sig, int res)
 {
-    sig->flags.checked = 0;
-    sig->flags.valid = 0;
-    if (!res) {
-        sig->flags.checked = 1;
-        sig->flags.valid = 1;
+  sig->flags.checked = 0;
+  sig->flags.valid = 0;
+  if (!res) 
+    {
+      sig->flags.checked = 1;
+      sig->flags.valid = 1;
     }
-    else if (res == CDK_Bad_Sig) {
-        sig->flags.checked = 1;
-        sig->flags.valid = 0;
+  else if (res == CDK_Bad_Sig) 
+    {
+      sig->flags.checked = 1;
+      sig->flags.valid = 0;
     }
 }
 
 
 cdk_error_t
-_cdk_sig_check (cdk_pkt_pubkey_t pk, cdk_pkt_signature_t sig,
+_cdk_sig_check (cdk_pubkey_t pk, cdk_pkt_signature_t sig,
                 gcry_md_hd_t digest, int *r_expired)
 {
   byte md[MAX_DIGEST_LEN];
-  time_t cur_time = _cdk_timestamp ();
-  int rc;
+  time_t cur_time = (u32)time (NULL);
+  cdk_error_t rc;
 
   if (!pk || !sig || !digest)
     return CDK_Inv_Value;
@@ -243,7 +245,7 @@ _cdk_pk_check_sig (cdk_keydb_hd_t keydb,
                   cdk_kbnode_t knode, cdk_kbnode_t snode, int *is_selfsig)
 {
   gcry_md_hd_t md;
-  cdk_pkt_pubkey_t pk;
+  cdk_pubkey_t pk;
   cdk_pkt_signature_t sig;
   cdk_kbnode_t node;
   int is_expired;
@@ -318,7 +320,7 @@ _cdk_pk_check_sig (cdk_keydb_hd_t keydb,
        }
       else if (keydb != NULL)
        {
-         cdk_pkt_pubkey_t sig_pk;
+         cdk_pubkey_t sig_pk;
          
          rc = cdk_keydb_get_pk (keydb, sig->keyid, &sig_pk);
          if (!rc)
index bfc0c5978ba38f2ddbb5f278538324986bcb74fd..40e31dd8c518754bbb7359d3d822be156efecc03 100644 (file)
@@ -39,6 +39,14 @@ static int stream_flush (cdk_stream_t s);
 static int stream_filter_write (cdk_stream_t s);
 static int stream_cache_flush (cdk_stream_t s, FILE *fp);
 
+/* Customized tmpfile() version from misc.c */
+FILE *my_tmpfile (void);
+    
+
+/* FIXME: The read/write/putc/getc function cannot directly
+          return an error code. It is stored in an error variable
+          inside the string. Right now there is no code to
+          return the error code or to reset it. */
 
 /**
  * cdk_stream_open:
@@ -104,7 +112,7 @@ cdk_stream_new_from_cbs (cdk_stream_cbs_t cbs, void *opa,
 {
   cdk_stream_t s;
 
-  if (!opa)
+  if (!cbs || !opa || !ret_s)
     return CDK_Inv_Value;
     
   *ret_s = NULL;
@@ -158,7 +166,7 @@ cdk_stream_new (const char *file, cdk_stream_t *ret_s)
          return CDK_Out_Of_Core;
        }
     }
-  s->fp = tmpfile ();
+  s->fp = my_tmpfile ();
   if (!s->fp) 
     {
       cdk_free (s->fname);
@@ -251,7 +259,7 @@ cdk_stream_tmp_from_mem (const void *buf, size_t buflen, cdk_stream_t *r_out)
   if (nwritten == EOF)
     {
       cdk_stream_close (s);
-      return CDK_File_Error;
+      return s->error;
     }
   cdk_stream_seek (s, 0);
   *r_out = s;
@@ -457,7 +465,11 @@ cdk_stream_eof (cdk_stream_t s)
 const char*
 _cdk_stream_get_fname (cdk_stream_t s)
 {
-  return s? s->fname : NULL;
+  if (!s)
+    return NULL;
+  if (s->flags.temp)
+    return NULL;
+  return s->fname? s->fname : NULL;
 }
 
 
@@ -664,41 +676,45 @@ stream_filter_write (cdk_stream_t s)
     if( s->flags.filtrated )
         return CDK_Inv_Value;
 
-    for( f = s->filters; f; f = f->next ) {
-        if( !f->flags.enabled )
-            continue;
-        /* if there is no next filter, create the final output file */
-        _cdk_log_debug( "filter [write]: last filter=%d fname=%s\n",
-                        f->next? 1 : 0, s->fname );
-        if( !f->next && s->fname )
-            f->tmp = fopen( s->fname, "w+b" );
-        else
-            f->tmp = tmpfile( );
-        if( !f->tmp ) {
-            rc = CDK_File_Error;
-            break;            
-        }
-        /* If there is no next filter, flush the cache. We also do this
-           when the next filter is the armor filter because this filter
-           is special and before it starts, all data should be written. */
-        if( (!f->next || f->next->type == fARMOR) && s->cache.size ) {
-            rc = stream_cache_flush( s, f->tmp );
-            if( rc )
-                break;
+    for( f = s->filters; f; f = f->next ) 
+    {
+      if (!f->flags.enabled)
+       continue;
+      /* if there is no next filter, create the final output file */
+      _cdk_log_debug( "filter [write]: last filter=%d fname=%s\n",
+                     f->next? 1 : 0, s->fname );
+      if (!f->next && s->fname)
+       f->tmp = fopen (s->fname, "w+b");
+      else
+       f->tmp = my_tmpfile ();
+      if (!f->tmp)
+       {
+         rc = CDK_File_Error;
+         break;            
         }
-        rc = f->fnct( f->opaque, f->ctl, s->fp, f->tmp );
-        _cdk_log_debug ("filter [write]: type=%d rc=%d\n", f->type, rc);
-        if( !rc )
-            rc = stream_fp_replace( s, &f->tmp );
-        if( !rc )
-            rc = cdk_stream_seek( s, 0 );
-        if( rc ) {
-           _cdk_log_debug ("filter [close]: fd=%d\n", fileno (f->tmp));
-            fclose( f->tmp );
-            break;
+      /* If there is no next filter, flush the cache. We also do this
+       when the next filter is the armor filter because this filter
+       is special and before it starts, all data should be written. */
+      if( (!f->next || f->next->type == fARMOR) && s->cache.size ) 
+       {
+         rc = stream_cache_flush (s, f->tmp);
+         if (rc)
+           break;
         }
+      rc = f->fnct( f->opaque, f->ctl, s->fp, f->tmp );
+      _cdk_log_debug ("filter [write]: type=%d rc=%d\n", f->type, rc);
+      if (!rc)
+       rc = stream_fp_replace (s, &f->tmp);
+      if (!rc)
+       rc = cdk_stream_seek (s, 0);
+      if (rc)
+       {
+         _cdk_log_debug ("filter [close]: fd=%d\n", fileno (f->tmp));
+         fclose (f->tmp);
+         break;
+      }
     }
-    return rc;
+  return rc;
 }
 
 
@@ -729,7 +745,7 @@ stream_filter_read (cdk_stream_t s)
          continue;
        }
      
-      f->tmp = tmpfile ();
+      f->tmp = my_tmpfile ();
       if (!f->tmp)
        {
          rc = CDK_File_Error;
@@ -801,23 +817,29 @@ _cdk_stream_get_opaque (cdk_stream_t s, int fid)
  * need to add the filters in reserved order.
  **/
 int
-cdk_stream_read (cdk_stream_t s, void * buf, size_t count)
+cdk_stream_read (cdk_stream_t s, void *buf, size_t buflen)
 {
   int nread;
   int rc;
   
   if (!s)
-    return EOF;
+    {
+      s->error = CDK_Inv_Value;
+      return EOF;
+    }  
   
   if (s->cbs_hd)
     {
       if (s->cbs.read)
-       return s->cbs.read (s->cbs_hd, buf, count);
+       return s->cbs.read (s->cbs_hd, buf, buflen);
       return 0;
     } 
     
   if (s->flags.write && !s->flags.temp)
-    return EOF; /* this is a write stream */
+    {
+      s->error = CDK_Inv_Mode;
+      return EOF; /* This is a write stream */
+    }  
   
   if (!s->flags.no_filter && !s->cache.on && !s->flags.filtrated)
     {
@@ -831,13 +853,16 @@ cdk_stream_read (cdk_stream_t s, void * buf, size_t count)
        }
       s->flags.filtrated = 1;
     }
-  if (!buf && !count)
+  if (!buf && !buflen)
     return 0;
-  nread = fread (buf, 1, count, s->fp);
+  nread = fread (buf, 1, buflen, s->fp);
   if (!nread)
     nread = EOF;
   if (feof (s->fp))
-    s->flags.eof = 1;
+    {
+      s->error = 0;
+      s->flags.eof = 1;
+    }  
   return nread;
 }
 
@@ -849,7 +874,10 @@ cdk_stream_getc (cdk_stream_t s)
   int nread;
   
   if (!s)
-    return EOF;  
+    {
+      s->error = CDK_Inv_Value;
+      return EOF;
+    }  
   nread = cdk_stream_read (s, buf, 1);
   if (nread == EOF) 
     {
@@ -876,7 +904,10 @@ cdk_stream_write (cdk_stream_t s, const void * buf, size_t count)
   int nwritten;
 
   if (!s)
-    return EOF;
+    {
+      s->error = CDK_Inv_Value;
+      return EOF;
+    }  
   
   if (s->cbs_hd)
     {
@@ -917,7 +948,10 @@ cdk_stream_putc (cdk_stream_t s, int c)
   int nwritten;
   
   if (!s)
-    return EOF;
+    {
+      s->error = CDK_Inv_Value;
+      return EOF;
+    }  
   buf[0] = c;
   nwritten = cdk_stream_write (s, buf, 1);
   if (nwritten == EOF) 
@@ -936,7 +970,7 @@ cdk_stream_tell (cdk_stream_t s)
 cdk_error_t
 cdk_stream_seek (cdk_stream_t s, off_t offset)
 {
-  cdk_error_t rc;
+  off_t len;
   
   if (!s)
     return CDK_Inv_Value;
@@ -947,13 +981,17 @@ cdk_stream_seek (cdk_stream_t s, off_t offset)
        return s->cbs.seek (s->cbs_hd, offset);
       return 0;
     }  
-    
-  if (offset < cdk_stream_get_length (s))
+  
+  /* Set or reset the EOF flag. */
+  len = cdk_stream_get_length (s);
+  if (len == offset)
+    s->flags.eof = 1;
+  else
     s->flags.eof = 0;
-  rc = fseek (s->fp, offset, SEEK_SET);
-  if (rc)
-    rc = CDK_File_Error;
-  return rc;
+  
+  if (fseek (s->fp, offset, SEEK_SET))
+    return CDK_File_Error;
+  return 0;
 }
 
 
@@ -985,19 +1023,25 @@ cdk_stream_set_armor_flag (cdk_stream_t s, int type)
 
 
 cdk_error_t
-cdk_stream_set_literal_flag( cdk_stream_t s, int mode, const char * fname )
+cdk_stream_set_literal_flag (cdk_stream_t s, int mode, const char *fname)
 {
-  struct stream_filter_s * f;
+  struct stream_filter_s *f;
+  const char *orig_fname;
+  
+  _cdk_log_debug ("stream: enable literal mode.\n");
   
   if (!s)
     return CDK_Inv_Value;
+
+  orig_fname = _cdk_stream_get_fname (s);
   f = filter_add (s, _cdk_filter_literal, fLITERAL);
   if (!f)
     return CDK_Out_Of_Core;
   f->u.pfx.mode = mode;
-  f->u.pfx.filename = fname? cdk_strdup( fname ) : NULL;
+  f->u.pfx.filename = fname? cdk_strdup (fname) : NULL;
+  f->u.pfx.orig_filename = orig_fname? cdk_strdup (orig_fname): NULL;
   f->ctl = stream_get_mode (s);
-  if (s->blkmode)
+  if (s->blkmode > 0)
     {
       f->u.pfx.blkmode.on = 1;
       f->u.pfx.blkmode.size = s->blkmode;
@@ -1007,20 +1051,21 @@ cdk_stream_set_literal_flag( cdk_stream_t s, int mode, const char * fname )
 
 
 cdk_error_t
-cdk_stream_set_cipher_flag( cdk_stream_t s, cdk_dek_t dek, int use_mdc )
+cdk_stream_set_cipher_flag (cdk_stream_t s, cdk_dek_t dek, int use_mdc)
 {
   struct stream_filter_s * f;
   
+  _cdk_log_debug ("stream: enable cipher mode\n");
   if (!s)
     return CDK_Inv_Value;
   f = filter_add (s, _cdk_filter_cipher, fCIPHER);
-  if( !f )
+  if (!f)
     return CDK_Out_Of_Core;
   dek->use_mdc = use_mdc;
   f->ctl = stream_get_mode (s);
   f->u.cfx.dek = dek;
   f->u.cfx.mdc_method = use_mdc? GCRY_MD_SHA1 : 0;
-  if (s->blkmode)
+  if (s->blkmode > 0)
     {
       f->u.cfx.blkmode.on = 1;
       f->u.cfx.blkmode.size = s->blkmode;
@@ -1056,16 +1101,16 @@ cdk_stream_set_text_flag (cdk_stream_t s, const char *lf)
   f = filter_add (s, _cdk_filter_text, fTEXT);
   if (!f)
     return CDK_Out_Of_Core;
-  f->ctl = stream_get_mode( s );
+  f->ctl = stream_get_mode (s);
   f->u.tfx.lf = lf;
   return 0;
 }
 
 
 cdk_error_t
-cdk_stream_set_hash_flag (cdk_stream_t s, int algo)
+cdk_stream_set_hash_flag (cdk_stream_t s, int digest_algo)
 {
-  struct stream_filter_s * f;
+  struct stream_filter_s *f;
   
   if (!s)
     return CDK_Inv_Value;    
@@ -1075,7 +1120,7 @@ cdk_stream_set_hash_flag (cdk_stream_t s, int algo)
   if (!f)
     return CDK_Out_Of_Core;
   f->ctl = stream_get_mode (s);
-  f->u.mfx.digest_algo = algo;
+  f->u.mfx.digest_algo = digest_algo;
   f->flags.rdonly = 1;
   return 0;
 }
@@ -1149,7 +1194,7 @@ cdk_stream_kick_off (cdk_stream_t inp, cdk_stream_t out)
        { /* In case of errors, we leave the loop. */
          rc = inp->error;
          break;
-       }      
+       }
     }
   
   wipemem (buf, sizeof (buf));
@@ -1225,18 +1270,18 @@ cdk_stream_mmap (cdk_stream_t inp, byte **buf, size_t *buflen)
  * the file pointer is moved to the old position after the bytes were read.
  **/
 int
-cdk_stream_peek (cdk_stream_t inp, byte *s, size_t count)
+cdk_stream_peek (cdk_stream_t inp, byte *buf, size_t buflen)
 {
   off_t off;
   int nbytes;
   
-  if (!inp || !s)
+  if (!inp || !buf)
     return 0;
   if (inp->cbs_hd)
     return 0;
   
   off = cdk_stream_tell (inp);
-  nbytes = _cdk_stream_gets (inp, (char*)s, count);
+  nbytes = cdk_stream_read (inp, buf, buflen);
   if (nbytes == -1)
     return 0;  
   if (cdk_stream_seek (inp, off))
index 3debeab8793eea2121557227e96d28ae8f4021bf..7bd388afe5882a4a8da87c05664fb181ddf58889 100644 (file)
@@ -19,6 +19,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <assert.h>
+#include <sys/stat.h>
 
 #include "opencdk.h"
 #include "main.h"
@@ -75,6 +76,7 @@ cdk_error_t
 cdk_file_verify (cdk_ctx_t hd, const char *file, const char *data_file,
                 const char *output)
 {
+  struct stat stbuf;
   cdk_stream_t inp, data;
   char buf[4096];
   int n;
@@ -82,7 +84,7 @@ cdk_file_verify (cdk_ctx_t hd, const char *file, const char *data_file,
   
   if (!hd || !file)
     return CDK_Inv_Value;
-  if (output && !hd->opt.overwrite && !_cdk_check_file (output))
+  if (output && !hd->opt.overwrite && !stat (output, &stbuf))
     return CDK_Inv_Mode;
   
   rc = cdk_stream_open (file, &inp);
index 12488bd422e78c30e4d21dda7737c3f811da9006..6b8f8eaecb94f4099eeee6e379e46cfc8ad64c25 100644 (file)
  * GNU General Public License for more details. 
  */
 #ifdef HAVE_CONFIG_H
-# include <config.h>
+#include <config.h>
 #endif
 #include <string.h>
 #include <stdio.h>
+#include <assert.h>
 
 #include "opencdk.h"
 #include "main.h"
@@ -39,12 +40,12 @@ static int
 stream_read (cdk_stream_t s, void *buf, size_t buflen, size_t *r_nread)
 {
   int nread;
-  
-  if (!r_nread)
-    return CDK_Inv_Value;
+
+  assert (r_nread);
+
   nread = cdk_stream_read (s, buf, buflen);
   if (nread == EOF)
-    return CDK_File_Error;
+    return _cdk_stream_get_errno (s);
   *r_nread = nread;
   return 0;
 }
@@ -55,7 +56,7 @@ stream_putc (cdk_stream_t s, int c)
 {
   int nwritten = cdk_stream_putc (s, c);
   if (nwritten == EOF)
-    return CDK_File_Error;
+    return _cdk_stream_get_errno (s);
   return 0;
 }
 
@@ -85,13 +86,13 @@ write_16 (cdk_stream_t out, u16 u)
 
 
 static size_t
-calc_mpisize (gcry_mpi_t mpi[4], size_t ncount)
+calc_mpisize (gcry_mpi_t mpi[MAX_CDK_PK_PARTS], size_t ncount)
 {
   size_t size, i;
   
-  size=0;
+  size = 0;
   for (i = 0; i < ncount; i++)
-    size += (gcry_mpi_get_nbits (mpi[i])+7)/8  + 2;
+    size += (gcry_mpi_get_nbits (mpi[i]) + 7) / 8 + 2;
   return size;
 }
 
@@ -116,7 +117,7 @@ write_mpi (cdk_stream_t out, gcry_mpi_t m)
 
 
 static cdk_error_t
-write_mpibuf (cdk_stream_t out, gcry_mpi_t mpi[4], size_t count)
+write_mpibuf (cdk_stream_t out, gcry_mpi_t mpi[MAX_CDK_PK_PARTS], size_t count)
 {
   size_t i;
   cdk_error_t rc;
@@ -136,8 +137,8 @@ pkt_encode_len (cdk_stream_t out, size_t pktlen)
 {
   cdk_error_t rc;
   
-  if (!out)
-    return CDK_Inv_Value;
+  assert (out);
+
   rc = 0;
   if (!pktlen)
     {
@@ -169,8 +170,8 @@ write_head_new (cdk_stream_t out, size_t size, int type)
 {
   cdk_error_t rc;
 
-  if (!out)
-    return CDK_Inv_Value;
+  assert (out);
+
   if (type < 0 || type > 63)
     return CDK_Inv_Packet;
   rc = stream_putc (out, (0xC0 | type));
@@ -186,8 +187,8 @@ write_head_old (cdk_stream_t out, size_t size, int type)
   cdk_error_t rc;
   int ctb;
 
-  if (!out)
-    return CDK_Inv_Value;
+  assert (out);
+
   if (type < 0 || type > 16)
     return CDK_Inv_Packet;
   ctb = 0x80 | (type << 2);
@@ -216,12 +217,14 @@ write_head_old (cdk_stream_t out, size_t size, int type)
 }
 
 
-/* write special PGP2 packet header. PGP2 (wrongly) uses two byte header
+/* Write special PGP2 packet header. PGP2 (wrongly) uses two byte header
    length for signatures and keys even if the size is < 256. */
 static cdk_error_t
 pkt_write_head2 (cdk_stream_t out, size_t size, int type)
 {
-  int rc = cdk_stream_putc (out, 0x80 | (type << 2) | 1);
+  cdk_error_t rc;
+  
+  rc = cdk_stream_putc (out, 0x80 | (type << 2) | 1);
   if (!rc)
     rc = cdk_stream_putc (out, size >> 8);
   if (!rc)
@@ -245,11 +248,11 @@ write_encrypted (cdk_stream_t out, cdk_pkt_encrypted_t enc, int old_ctb)
   size_t nbytes;
   cdk_error_t rc;
 
-  if (!out || !enc)
-    return CDK_Inv_Value;
+  assert (out);
+  assert (enc);
   
   if (DEBUG_PKT)
-    _cdk_log_debug ("** write encrypted packet %lu bytes\n", enc->len);
+    _cdk_log_debug ("write_encrypted: %lu bytes\n", enc->len);
   
   nbytes = enc->len ? (enc->len + enc->extralen) : 0;
   rc = pkt_write_head (out, old_ctb, nbytes, CDK_PKT_ENCRYPTED);
@@ -264,13 +267,14 @@ write_encrypted_mdc (cdk_stream_t out, cdk_pkt_encrypted_t enc)
   size_t nbytes;
   cdk_error_t rc;
 
-  if (!out || !enc)
-    return CDK_Inv_Value;
+  assert (out);
+  assert (enc);
+
   if (!enc->mdc_method)
     return CDK_Inv_Packet;
   
   if (DEBUG_PKT)
-    _cdk_log_debug ("** write encrypted mdc packet %lu bytes\n", enc->len);
+    _cdk_log_debug ("write_encrypted_mdc: %lu bytes\n", enc->len);
   
   nbytes = enc->len ? (enc->len + enc->extralen + 1) : 0;
   rc = pkt_write_head (out, 0, nbytes, CDK_PKT_ENCRYPTED_MDC);
@@ -288,13 +292,14 @@ write_symkey_enc (cdk_stream_t out, cdk_pkt_symkey_enc_t ske)
   size_t size = 0, s2k_size = 0;
   cdk_error_t rc;
 
-  if (!out || !ske)
-    return CDK_Inv_Value;
+  assert (out);
+  assert (ske);
+
   if (ske->version != 4)
     return CDK_Inv_Packet;
   
   if (DEBUG_PKT)
-    _cdk_log_debug ("** write symmetric key encrypted packet\n");
+    _cdk_log_debug ("write_symkey_enc:\n");
   
   s2k = ske->s2k;
   if (s2k->mode == CDK_S2K_SALTED || s2k->mode == CDK_S2K_ITERSALTED)
@@ -330,15 +335,16 @@ write_pubkey_enc (cdk_stream_t out, cdk_pkt_pubkey_enc_t pke, int old_ctb)
   size_t size;
   int rc, nenc;
 
-  if (!out || !pke)
-    return CDK_Inv_Value;
+  assert (out);
+  assert (pke);
+
   if (pke->version < 2 || pke->version > 3)
     return CDK_Inv_Packet;
   if (!KEY_CAN_ENCRYPT (pke->pubkey_algo))
     return CDK_Inv_Algo;
   
   if (DEBUG_PKT)
-    _cdk_log_debug ("** write public key encrypted packet\n");
+    _cdk_log_debug ("write_pubkey_enc:\n");
 
   nenc = cdk_pk_get_nenc (pke->pubkey_algo);
   size = 10 + calc_mpisize (pke->mpi, nenc);
@@ -364,11 +370,11 @@ write_mdc (cdk_stream_t out, cdk_pkt_mdc_t mdc)
 {
   cdk_error_t rc;
 
-  if (!out || !mdc)
-    return CDK_Inv_Value;
+  assert (mdc);
+  assert (out);
   
   if (DEBUG_PKT)
-    _cdk_log_debug ("** write_mdc packet\n");
+    _cdk_log_debug ("write_mdc:\n");
 
   /* This packet requires a fixed header encoding */
   rc = stream_putc (out, 0xD3); /* packet ID and 1 byte length */
@@ -391,6 +397,43 @@ calc_subpktsize (cdk_subpkt_t s)
 }
 
 
+static cdk_error_t
+write_v3_sig (cdk_stream_t out, cdk_pkt_signature_t sig, int nsig)
+{
+  size_t size;
+  cdk_error_t rc;
+  
+  size = 19 + calc_mpisize (sig->mpi, nsig);
+  if (is_RSA (sig->pubkey_algo))
+    rc = pkt_write_head2 (out, size, CDK_PKT_SIGNATURE);
+  else
+    rc = pkt_write_head (out, 1, size, CDK_PKT_SIGNATURE);
+  if (!rc)
+    rc = stream_putc (out, sig->version);
+  if (!rc)
+    rc = stream_putc (out, 5);
+  if (!rc)
+    rc = stream_putc (out, sig->sig_class);
+  if (!rc)
+    rc = write_32 (out, sig->timestamp);
+  if (!rc)
+    rc = write_32 (out, sig->keyid[0]);
+  if (!rc)
+    rc = write_32 (out, sig->keyid[1]);
+  if (!rc)
+    rc = stream_putc (out, sig->pubkey_algo);
+  if (!rc)
+    rc = stream_putc (out, sig->digest_algo);
+  if (!rc)
+    rc = stream_putc (out, sig->digest_start[0]);
+  if (!rc)
+    rc = stream_putc (out, sig->digest_start[1]);
+  if (!rc)
+    rc = write_mpibuf (out, sig->mpi, nsig);
+  return rc;
+}
+
+
 static cdk_error_t
 write_signature (cdk_stream_t out, cdk_pkt_signature_t sig, int old_ctb)
 {
@@ -398,273 +441,262 @@ write_signature (cdk_stream_t out, cdk_pkt_signature_t sig, int old_ctb)
   size_t nbytes, size, nsig;
   cdk_error_t rc;
 
-  if (!out || !sig)
-    return CDK_Inv_Value;
+  assert (out);
+  assert (sig);
   
-  if (!KEY_CAN_SIGNsig->pubkey_algo))
+  if (!KEY_CAN_SIGN (sig->pubkey_algo))
     return CDK_Inv_Algo;
   if (sig->version < 2 || sig->version > 4)
     return CDK_Inv_Packet;
 
   if (DEBUG_PKT)
-    _cdk_log_debug ("** write signature packet\n");
+    _cdk_log_debug ("write_signature:\n");
   
   nsig = cdk_pk_get_nsig (sig->pubkey_algo);
   if (!nsig)
     return CDK_Inv_Algo;
   if (sig->version < 4)
+    return write_v3_sig (out, sig, nsig);
+
+  size = 10 + calc_subpktsize (sig->hashed)
+       + calc_subpktsize (sig->unhashed)
+       + calc_mpisize (sig->mpi, nsig);
+  rc = pkt_write_head (out, 0, size, CDK_PKT_SIGNATURE);
+  if (!rc)
+    rc = stream_putc (out, 4);
+  if (!rc)
+    rc = stream_putc (out, sig->sig_class);
+  if (!rc)
+    rc = stream_putc (out, sig->pubkey_algo);
+  if (!rc)
+    rc = stream_putc (out, sig->digest_algo);
+  if (!rc)
+    rc = write_16 (out, sig->hashed_size);
+  if (!rc) 
     {
-      size = 19 + calc_mpisize( sig->mpi, nsig );
-      if (is_RSA (sig->pubkey_algo))
-       rc = pkt_write_head2 (out, size, CDK_PKT_SIGNATURE);
-      else
-       rc = pkt_write_head (out, old_ctb, size, CDK_PKT_SIGNATURE);
-      if (!rc)
-       rc = stream_putc (out, sig->version);
-      if (!rc)
-       rc = stream_putc (out, 5);
-      if (!rc)
-       rc = stream_putc (out, sig->sig_class);
-      if (!rc)
-       rc = write_32 (out, sig->timestamp);
-      if (!rc)
-       rc = write_32 (out, sig->keyid[0]);
-      if (!rc)
-       rc = write_32 (out, sig->keyid[1]);
-      if (!rc)
-       rc = stream_putc (out, sig->pubkey_algo);
-      if (!rc)
-       rc = stream_putc (out, sig->digest_algo);
-      if (!rc)
-       rc = stream_putc (out, sig->digest_start[0]);
-      if (!rc)
-       rc = stream_putc (out, sig->digest_start[1]);
+      buf = _cdk_subpkt_get_array (sig->hashed, 0, &nbytes);
+      if (!buf)
+       return CDK_Out_Of_Core;
+      rc = stream_write (out, buf, nbytes);
+      cdk_free (buf);
     }
-  else 
+  if (!rc)
+    rc = write_16 (out, sig->unhashed_size);
+  if (!rc)
     {
-      size = 10 + calc_subpktsize (sig->hashed)
-       + calc_subpktsize (sig->unhashed)
-       + calc_mpisize (sig->mpi, nsig);
-      rc = pkt_write_head (out, 0, size, CDK_PKT_SIGNATURE);
-      if( !rc)
-       rc = stream_putc (out, 4);
-      if (!rc)
-       rc = stream_putc (out, sig->sig_class);
-      if( !rc )
-       rc = stream_putc (out, sig->pubkey_algo);
-        if( !rc )
-       rc = stream_putc (out, sig->digest_algo);
-      if( !rc )
-       rc = write_16 (out, sig->hashed_size);
-      if( !rc ) {
-       buf = _cdk_subpkt_get_array (sig->hashed, 0, &nbytes);
-       if (!buf)
-         return CDK_Out_Of_Core;
-       rc = stream_write (out, buf, nbytes);
-       cdk_free (buf);
-      }
-      if (!rc)
-       rc = write_16 (out, sig->unhashed_size);
-      if (!rc)
-       {
-         buf = _cdk_subpkt_get_array (sig->unhashed, 0, &nbytes);
-         if (!buf)
-           return CDK_Out_Of_Core;
-         rc = stream_write (out, buf, nbytes);
-         cdk_free (buf);
-       }
-      if (!rc)
-       rc = stream_putc (out, sig->digest_start[0]);
-      if (!rc)
-       rc = stream_putc (out, sig->digest_start[1]);
+      buf = _cdk_subpkt_get_array (sig->unhashed, 0, &nbytes);
+      if (!buf)
+       return CDK_Out_Of_Core;
+      rc = stream_write (out, buf, nbytes);
+      cdk_free (buf);
     }
+  if (!rc)
+    rc = stream_putc (out, sig->digest_start[0]);
+  if (!rc)
+    rc = stream_putc (out, sig->digest_start[1]);
   if (!rc)
     rc = write_mpibuf (out, sig->mpi, nsig);
   return rc;
 }
 
 
-static int
-write_public_keycdk_stream_t out, cdk_pkt_pubkey_t pk,
-                  int is_subkey, int old_ctb )
+static cdk_error_t
+write_public_key (cdk_stream_t out, cdk_pkt_pubkey_t pk,
+                  int is_subkey, int old_ctb)
 {
-    int rc = 0;
-    int pkttype, ndays = 0;
-    size_t npkey = 0, size = 6;
-
-    if( !out || !pk )
-        return CDK_Inv_Value;
-    if( pk->version < 2 || pk->version > 4 )
-        return CDK_Inv_Packet;
-
-    if (DEBUG_PKT)
-        _cdk_log_debug ("** write public key packet\n");
-
-    pkttype = is_subkey? CDK_PKT_PUBLIC_SUBKEY : CDK_PKT_PUBLIC_KEY;
-    npkey = cdk_pk_get_npkey( pk->pubkey_algo );
-    if( !npkey )
-        return CDK_Inv_Algo;
-    if( pk->version < 4 )
-        size += 2; /* expire date */
-    if( is_subkey )
-        old_ctb = 0;
-    size += calc_mpisize( pk->mpi, npkey );
-    if( old_ctb )
-        rc = pkt_write_head2( out, size, pkttype );
-    else
-        rc = pkt_write_head( out, old_ctb, size, pkttype );
-    if( !rc )
-        rc = stream_putc( out, pk->version );
-    if( !rc )
-        rc = write_32( out, pk->timestamp );
-    if( !rc && pk->version < 4 ) {
-        if( pk->expiredate )
-            ndays = (u16) ((pk->expiredate - pk->timestamp) / 86400L);
-        rc = write_16( out, ndays );
+  int pkttype, ndays = 0;
+  size_t npkey = 0, size = 6;
+  cdk_error_t rc;
+  
+  assert (out);
+  assert (pk);
+  
+  if (pk->version < 2 || pk->version > 4)
+    return CDK_Inv_Packet;
+  
+  if (DEBUG_PKT)
+    _cdk_log_debug ("write_public_key: subkey=%d\n", is_subkey);
+
+  pkttype = is_subkey? CDK_PKT_PUBLIC_SUBKEY : CDK_PKT_PUBLIC_KEY;
+  npkey = cdk_pk_get_npkey (pk->pubkey_algo);
+  if (!npkey)
+    return CDK_Inv_Algo;
+  if (pk->version < 4)
+    size += 2; /* expire date */
+  if (is_subkey)
+    old_ctb = 0;
+  size += calc_mpisize (pk->mpi, npkey);
+  if (old_ctb)
+    rc = pkt_write_head2 (out, size, pkttype);
+  else
+    rc = pkt_write_head (out, old_ctb, size, pkttype);
+  if (!rc)
+    rc = stream_putc (out, pk->version);
+  if (!rc)
+    rc = write_32 (out, pk->timestamp);
+  if (!rc && pk->version < 4)
+    {    
+      if (pk->expiredate)
+       ndays = (u16) ((pk->expiredate - pk->timestamp) / 86400L);
+      rc = write_16 (out, ndays);
     }
-    if( !rc )
-        rc = stream_putc( out, pk->pubkey_algo );
-    if( !rc )
-        rc = write_mpibuf( out, pk->mpi, npkey );
-    return rc;
+  if (!rc)
+    rc = stream_putc (out, pk->pubkey_algo);
+  if (!rc)
+    rc = write_mpibuf (out, pk->mpi, npkey);
+  return rc;
 }
 
 
 static int
-calc_s2ksize( cdk_pkt_seckey_t sk )
+calc_s2ksize (cdk_pkt_seckey_t sk)
 {
-    size_t nbytes = 0;
-  
-    if( !sk->is_protected )
-        return 0;
-    switch( sk->protect.s2k->mode ) {
-      case CDK_S2K_SIMPLE    : nbytes =  2; break;
-      case CDK_S2K_SALTED    : nbytes = 10; break;
-      case CDK_S2K_ITERSALTED: nbytes = 11; break;
+  size_t nbytes = 0;
+  
+  if (!sk->is_protected)
+    return 0;
+  switch (sk->protect.s2k->mode)
+    {    
+    case CDK_S2K_SIMPLE    : nbytes =  2; break;
+    case CDK_S2K_SALTED    : nbytes = 10; break;
+    case CDK_S2K_ITERSALTED: nbytes = 11; break;
     }
-    nbytes += sk->protect.ivlen;
-    nbytes++; /* single cipher byte */
-    return nbytes;
+  nbytes += sk->protect.ivlen;
+  nbytes++; /* single cipher byte */
+  return nbytes;
 }
 
   
-static int
+static cdk_error_t
 write_secret_key( cdk_stream_t out, cdk_pkt_seckey_t sk,
                   int is_subkey, int old_ctb )
 {
-    cdk_pkt_pubkey_t pk = NULL;
-    size_t size = 6, npkey, nskey;
-    int pkttype, s2k_mode;
-    int rc = 0;
-
-    if( !out || !sk || !sk->pk )
-        return CDK_Inv_Value;
-
-    pk = sk->pk;
-    if( pk->version < 2 || pk->version > 4 )
-        return CDK_Inv_Packet;
-
-    if (DEBUG_PKT)
-        _cdk_log_debug ("** write secret key packet\n");
-
-    npkey = cdk_pk_get_npkey( pk->pubkey_algo );
-    nskey = cdk_pk_get_nskey( pk->pubkey_algo );
-    if( !npkey || !nskey )
-        return CDK_Inv_Algo;
-    if( pk->version < 4 )
-        size += 2;
-    /* if the key is unprotected, the 1 extra byte:
-       1 octet  - cipher algorithm byte (0x00)
+  cdk_pkt_pubkey_t pk = NULL;
+  size_t size = 6, npkey, nskey;
+  int pkttype, s2k_mode;
+  cdk_error_t rc;
+
+  assert (out);
+  assert (sk);
+  
+  if (!sk->pk)
+    return CDK_Inv_Value;
+  pk = sk->pk;
+  if (pk->version < 2 || pk->version > 4)
+    return CDK_Inv_Packet;
+  
+  if (DEBUG_PKT)
+    _cdk_log_debug ("write_secret_key:\n");
+  
+  npkey = cdk_pk_get_npkey (pk->pubkey_algo);
+  nskey = cdk_pk_get_nskey (pk->pubkey_algo);
+  if (!npkey || !nskey)
+    return CDK_Inv_Algo;
+  if (pk->version < 4)
+    size += 2;
+  /* If the key is unprotected, the 1 extra byte:
+     1 octet  - cipher algorithm byte (0x00)
        the other bytes depend on the mode:
-       a) simple checksum -  2 octets
-       b) sha-1 checksum  - 20 octets */
-    size = !sk->is_protected? size + 1 : size + 1 + calc_s2ksize( sk );
-    size += calc_mpisize( pk->mpi, npkey );
-    if( sk->version == 3 || !sk->is_protected ) {
-        if( sk->version == 3 ) {            
-            size += 2; /* force simple checksum */
-            sk->protect.sha1chk = 0;
-        }
-        else
-            size += sk->protect.sha1chk? 20 : 2;
-        size += calc_mpisize( sk->mpi, nskey );
+     a) simple checksum -  2 octets
+     b) sha-1 checksum  - 20 octets */
+  size = !sk->is_protected? size + 1 : size + 1 + calc_s2ksize (sk);
+  size += calc_mpisize (pk->mpi, npkey);
+  if (sk->version == 3 || !sk->is_protected) 
+    {
+      if (sk->version == 3) 
+       {
+         size += 2; /* force simple checksum */
+         sk->protect.sha1chk = 0;
+       }
+      else
+       size += sk->protect.sha1chk? 20 : 2;
+      size += calc_mpisize (sk->mpi, nskey);
     }
-    else /* we do not know anything about the encrypted mpi's so we
-            treat the data as opaque. */
-        size += sk->enclen;
-
-    pkttype = is_subkey? CDK_PKT_SECRET_SUBKEY : CDK_PKT_SECRET_KEY;
-    rc = pkt_write_head( out, old_ctb, size, pkttype );
-    if( !rc )
-        rc = stream_putc( out, pk->version );
-    if( !rc )
-        rc = write_32( out, pk->timestamp );
-    if( !rc && pk->version < 4 ) {
-        u16 ndays = 0;
-        if( pk->expiredate )
-            ndays = (u16) ((pk->expiredate - pk->timestamp) / 86400L);
-        rc = write_16( out, ndays );
+  else /* We do not know anything about the encrypted mpi's so we
+         treat the data as opaque. */
+    size += sk->enclen;
+
+  pkttype = is_subkey? CDK_PKT_SECRET_SUBKEY : CDK_PKT_SECRET_KEY;
+  rc = pkt_write_head (out, old_ctb, size, pkttype);
+  if (!rc)
+    rc = stream_putc (out, pk->version);
+  if (!rc)
+    rc = write_32 (out, pk->timestamp);
+  if (!rc && pk->version < 4)
+    {
+      u16 ndays = 0;
+      if (pk->expiredate)
+       ndays = (u16) ((pk->expiredate - pk->timestamp) / 86400L);
+      rc = write_16 (out, ndays);
     }
-    if( !rc )
-        rc = stream_putc( out, pk->pubkey_algo );
-    if( !rc )
-        rc = write_mpibuf( out, pk->mpi, npkey );
-    if( sk->is_protected == 0 )
-        rc = stream_putc( out, 0x00 );
-    else {
-        if( is_RSA( pk->pubkey_algo ) && pk->version < 4 )
-            stream_putc( out, sk->protect.algo );
-        else if( sk->protect.s2k ) {
-            s2k_mode = sk->protect.s2k->mode;
-            rc = stream_putc( out, sk->protect.sha1chk? 0xFE : 0xFF );
-            if( !rc )
-                rc = stream_putc( out, sk->protect.algo );
-            if( !rc )
-                rc = stream_putc( out, sk->protect.s2k->mode );
-            if( !rc )
-                rc = stream_putc( out, sk->protect.s2k->hash_algo );
-            if( !rc && (s2k_mode == 1 || s2k_mode == 3) ) {
-                rc = stream_write( out, sk->protect.s2k->salt, 8 );
-                if( !rc && s2k_mode == 3 )
-                    rc = stream_putc( out, sk->protect.s2k->count );
+  if (!rc)
+    rc = stream_putc (out, pk->pubkey_algo);
+  if( !rc )
+    rc = write_mpibuf (out, pk->mpi, npkey);
+  if (sk->is_protected == 0)
+    rc = stream_putc (out, 0x00);
+  else 
+    {
+      if (is_RSA (pk->pubkey_algo) && pk->version < 4)
+       stream_putc (out, sk->protect.algo);
+      else if (sk->protect.s2k)
+       {
+         s2k_mode = sk->protect.s2k->mode;
+         rc = stream_putc (out, sk->protect.sha1chk? 0xFE : 0xFF);
+         if (!rc)
+           rc = stream_putc (out, sk->protect.algo);
+         if (!rc)
+           rc = stream_putc (out, sk->protect.s2k->mode);
+         if (!rc)
+           rc = stream_putc( out, sk->protect.s2k->hash_algo);
+         if (!rc && (s2k_mode == 1 || s2k_mode == 3)) 
+           {
+             rc = stream_write (out, sk->protect.s2k->salt, 8);
+             if (!rc && s2k_mode == 3)
+               rc = stream_putc (out, sk->protect.s2k->count);
            }
        }
-        else
-            return CDK_Inv_Value;
-        rc = stream_write( out, sk->protect.iv, sk->protect.ivlen );
+      else
+       return CDK_Inv_Value;
+      rc = stream_write (out, sk->protect.iv, sk->protect.ivlen);
     }
-    if( !rc && sk->is_protected && pk->version == 4 ) {
-        if( sk->encdata && sk->enclen )
-            rc = stream_write( out, sk->encdata, sk->enclen );
+  if (!rc && sk->is_protected && pk->version == 4)
+    {
+      if (sk->encdata && sk->enclen)
+       rc = stream_write (out, sk->encdata, sk->enclen);
     }
-    else {
-        if( !rc )
-            rc = write_mpibuf( out, sk->mpi, nskey );
-        if( !rc ) {
-            if( !sk->csum )
-                sk->csum = _cdk_sk_get_csum( sk );
-            rc = write_16( out, sk->csum );
-        }
+  else 
+    {
+      if (!rc)
+       rc = write_mpibuf (out, sk->mpi, nskey);
+      if (!rc) 
+       {
+         if (!sk->csum)
+           sk->csum = _cdk_sk_get_csum (sk);
+         rc = write_16 (out, sk->csum);
+       }
     }
-    return rc;
+  
+  return rc;
 }
 
 
-static int
-write_compressedcdk_stream_t out, cdk_pkt_compressed_t cd )
+static cdk_error_t
+write_compressed (cdk_stream_t out, cdk_pkt_compressed_t cd )
 {
-    int rc;
-
-    if( !out || !cd )
-        return CDK_Inv_Value;
-
-    if (DEBUG_PKT)
-        _cdk_log_debug ("** write compressed packet\n");
+  cdk_error_t rc;
 
-    rc = pkt_write_head( out, 1, 0, CDK_PKT_COMPRESSED );
-    if( !rc )
-        rc = stream_putc( out, cd->algorithm );
-    return rc;
+  assert (out);
+  assert (cd);
+  
+  if (DEBUG_PKT)
+    _cdk_log_debug ("packet: write_compressed\n");
+  
+  /* Use an old (RFC1991) header for this packet. */
+  rc = pkt_write_head (out, 1, 0, CDK_PKT_COMPRESSED);
+  if (!rc)
+    rc = stream_putc (out, cd->algorithm);
+  return rc;
 }
 
 
@@ -675,15 +707,16 @@ write_literal (cdk_stream_t out, cdk_pkt_literal_t pt, int old_ctb)
   size_t size;
   cdk_error_t rc;
 
-  if (!out || !pt)
-    return CDK_Inv_Value;
+  assert (out);
+  assert (pt);
+
   /* We consider a packet without a body as an invalid packet.
      At least one octet must be present. */
   if (!pt->len)
     return CDK_Inv_Packet;
   
   if (DEBUG_PKT)
-    _cdk_log_debug ("** write literal packet\n");
+    _cdk_log_debug ("write_literal:\n");
 
   size = 6 + pt->namelen + pt->len;
   rc = pkt_write_head (out, old_ctb, size, CDK_PKT_LITERAL);
@@ -720,14 +753,15 @@ static cdk_error_t
 write_onepass_sig (cdk_stream_t out, cdk_pkt_onepass_sig_t sig)
 {
   cdk_error_t rc;
-  
-  if (!out || !sig)
-    return CDK_Inv_Value;
+
+  assert (out);
+  assert (sig);
+
   if (sig->version != 3)
     return CDK_Inv_Packet;
 
   if (DEBUG_PKT)
-    _cdk_log_debug ("** write one pass signature packet\n");
+    _cdk_log_debug ("write_onepass_sig:\n");
   
   rc = pkt_write_head (out, 0, 13, CDK_PKT_ONEPASS_SIG);
   if (!rc)
@@ -749,24 +783,36 @@ write_onepass_sig (cdk_stream_t out, cdk_pkt_onepass_sig_t sig)
 
 
 static cdk_error_t
-write_user_id (cdk_stream_t out, cdk_pkt_userid_t id, int old_ctb)
+write_user_id (cdk_stream_t out, cdk_pkt_userid_t id, int old_ctb, int pkttype)
 {
   cdk_error_t rc;
 
-  if (!out || !id || !id->name)
+  if (!out || !id)
     return CDK_Inv_Value;
   
-  if (id->attrib_img)
-    ; /* FIXME: Implement to store attribute packets. */
+  if (pkttype == CDK_PKT_ATTRIBUTE)
+    {
+      if (!id->attrib_img)
+       return CDK_Inv_Value;
+      rc = pkt_write_head (out, old_ctb, id->attrib_len+6, CDK_PKT_ATTRIBUTE);
+      if (rc)
+       return rc;
+      /* Write subpacket part. */
+      stream_putc (out, 255);
+      write_32 (out, id->attrib_len+1);
+      stream_putc (out, 1);
+      rc = stream_write (out, id->attrib_img, id->attrib_len);
+    }  
   else 
     {
+      if (!id->name)
+       return CDK_Inv_Value;
       rc = pkt_write_head (out, old_ctb, id->len, CDK_PKT_USER_ID);
       if (!rc)
-       rc = stream_write( out, id->name, id->len );
-      return rc;
+       rc = stream_write (out, id->name, id->len);
     }
-  
-  return CDK_Not_Implemented;
+      
+  return rc;
 }
 
 
@@ -829,13 +875,16 @@ cdk_pkt_write (cdk_stream_t out, cdk_packet_t pkt)
       rc = write_secret_key (out, pkt->pkt.secret_key, 1, pkt->old_ctb);
       break;
     case CDK_PKT_USER_ID:
-      rc = write_user_id (out, pkt->pkt.user_id, pkt->old_ctb);
+    case CDK_PKT_ATTRIBUTE:
+      rc = write_user_id (out, pkt->pkt.user_id, pkt->old_ctb, pkt->pkttype);
       break;
     default:
       rc = CDK_Inv_Packet;
       break;
     }
   
+  if (DEBUG_PKT)
+    _cdk_log_debug ("write_packet rc=%d pkttype=%d\n", rc, pkt->pkttype);
   return rc;
 }
 
@@ -888,5 +937,3 @@ _cdk_pkt_write_fp (FILE *out, cdk_packet_t pkt)
   cdk_stream_close (so);
   return rc;
 }
-
-