gpg: Limit keysize for unattended key generation to useful values.
[gnupg.git] / g10 / encode.c
index 1a6ca6d..88d0a69 100644 (file)
@@ -1,12 +1,12 @@
 /* encode.c - encode data
- * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003,
- *               2004 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+ *               2006, 2009 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
  * GnuPG is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation; either version 3 of the License, or
  * (at your option) any later version.
  *
  * GnuPG is distributed in the hope that it will be useful,
@@ -15,8 +15,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
 #include <errno.h>
 #include <assert.h>
 
+#include "gpg.h"
 #include "options.h"
 #include "packet.h"
-#include "errors.h"
+#include "status.h"
 #include "iobuf.h"
 #include "keydb.h"
-#include "memory.h"
 #include "util.h"
 #include "main.h"
 #include "filter.h"
 #include "trustdb.h"
 #include "i18n.h"
 #include "status.h"
+#include "pkglue.h"
+
 
 static int encode_simple( const char *filename, int mode, int use_seskey );
 static int write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out );
@@ -62,30 +63,36 @@ encode_store( const char *filename )
     return encode_simple( filename, 0, 0 );
 }
 
+
 static void
 encode_seskey( DEK *dek, DEK **seskey, byte *enckey )
 {
-    CIPHER_HANDLE hd;
+    gcry_cipher_hd_t hd;
     byte buf[33];
 
     assert ( dek->keylen <= 32 );
     if(!*seskey)
       {
-       *seskey=m_alloc_clear(sizeof(DEK));
+       *seskey=xmalloc_clear(sizeof(DEK));
        (*seskey)->keylen=dek->keylen;
        (*seskey)->algo=dek->algo;
        make_session_key(*seskey);
        /*log_hexdump( "thekey", c->key, c->keylen );*/
       }
 
+    /* The encrypted session key is prefixed with a one-octet algorithm id.  */
     buf[0] = (*seskey)->algo;
     memcpy( buf + 1, (*seskey)->key, (*seskey)->keylen );
-    
-    hd = cipher_open( dek->algo, CIPHER_MODE_CFB, 1 );
-    cipher_setkey( hd, dek->key, dek->keylen );
-    cipher_setiv( hd, NULL, 0 );
-    cipher_encrypt( hd, buf, buf, (*seskey)->keylen + 1 );
-    cipher_close( hd );
+
+    /* We only pass already checked values to the following fucntion,
+       thus we consider any failure as fatal.  */
+    if (openpgp_cipher_open (&hd, dek->algo, GCRY_CIPHER_MODE_CFB, 1))
+      BUG ();
+    if (gcry_cipher_setkey (hd, dek->key, dek->keylen))
+      BUG ();
+    gcry_cipher_setiv (hd, NULL, 0);
+    gcry_cipher_encrypt (hd, buf, (*seskey)->keylen + 1, NULL, 0);
+    gcry_cipher_close (hd);
 
     memcpy( enckey, buf, (*seskey)->keylen + 1 );
     wipememory( buf, sizeof buf ); /* burn key */
@@ -110,7 +117,7 @@ use_mdc(PK_LIST pk_list,int algo)
 
   if(select_mdc_from_pklist(pk_list))
     return 1;
-  
+
   /* The keys don't support MDC, so now we do a bit of a hack - if any
      of the AESes or TWOFISH are in the prefs, we assume that the user
      can handle a MDC.  This is valid for PGP 7, which can handle MDCs
@@ -135,9 +142,12 @@ use_mdc(PK_LIST pk_list,int algo)
 
   /* Last try.  Use MDC for the modern ciphers. */
 
-  if(cipher_get_blocksize(algo)!=8)
+  if (openpgp_cipher_get_algo_blklen (algo) != 8)
     return 1;
 
+  if (opt.verbose)
+    warn_missing_mdc_from_pklist (pk_list);
+
   return 0; /* No MDC */
 }
 
@@ -157,26 +167,37 @@ encode_simple( const char *filename, int mode, int use_seskey )
     int seskeylen = 0;
     u32 filesize;
     cipher_filter_context_t cfx;
-    armor_filter_context_t afx;
+    armor_filter_context_t  *afx = NULL;
     compress_filter_context_t zfx;
     text_filter_context_t tfx;
-    progress_filter_context_t pfx;
+    progress_filter_context_t *pfx;
     int do_compress = !RFC1991 && default_compress_algo();
 
+    pfx = new_progress_context ();
     memset( &cfx, 0, sizeof cfx);
-    memset( &afx, 0, sizeof afx);
     memset( &zfx, 0, sizeof zfx);
     memset( &tfx, 0, sizeof tfx);
     init_packet(&pkt);
-    
+
     /* prepare iobufs */
-    if( !(inp = iobuf_open(filename)) ) {
-       log_error(_("%s: can't open: %s\n"), filename? filename: "[stdin]",
-                                       strerror(errno) );
-       return G10ERR_OPEN_FILE;
+    inp = iobuf_open(filename);
+    if (inp)
+      iobuf_ioctl (inp,3,1,NULL); /* disable fd caching */
+    if (inp && is_secured_file (iobuf_get_fd (inp)))
+      {
+        iobuf_close (inp);
+        inp = NULL;
+        errno = EPERM;
+      }
+    if( !inp ) {
+        rc = gpg_error_from_syserror ();
+       log_error(_("can't open `%s': %s\n"), filename? filename: "[stdin]",
+                  strerror(errno) );
+        release_progress_context (pfx);
+       return rc;
     }
 
-    handle_progress (&pfx, inp, filename);
+    handle_progress (pfx, inp, filename);
 
     if( opt.textmode )
        iobuf_push_filter( inp, text_filter, &tfx );
@@ -186,21 +207,24 @@ encode_simple( const char *filename, int mode, int use_seskey )
        it has no S2K salt. RFC1991 always uses simple S2K. */
     if ( RFC1991 && use_seskey )
         use_seskey = 0;
-    
+
     cfx.dek = NULL;
     if( mode ) {
-       s2k = m_alloc_clear( sizeof *s2k );
+        int canceled;
+
+       s2k = xmalloc_clear( sizeof *s2k );
        s2k->mode = RFC1991? 0:opt.s2k_mode;
        s2k->hash_algo=S2K_DIGEST_ALGO;
        cfx.dek = passphrase_to_dek( NULL, 0,
-                                    default_cipher_algo(), s2k, 2,
-                                     NULL, NULL);
+                                    default_cipher_algo(), s2k, 4,
+                                     NULL, &canceled);
        if( !cfx.dek || !cfx.dek->keylen ) {
-           rc = G10ERR_PASSPHRASE;
-           m_free(cfx.dek);
-           m_free(s2k);
+           rc = gpg_error (canceled? GPG_ERR_CANCELED:GPG_ERR_INV_PASSPHRASE);
+           xfree(cfx.dek);
+           xfree(s2k);
            iobuf_close(inp);
-           log_error(_("error creating passphrase: %s\n"), g10_errstr(rc) );
+           log_error(_("error creating passphrase: %s\n"), gpg_strerror (rc));
+            release_progress_context (pfx);
            return rc;
        }
         if (use_seskey && s2k->mode != 1 && s2k->mode != 3) {
@@ -212,14 +236,15 @@ encode_simple( const char *filename, int mode, int use_seskey )
         if ( use_seskey )
          {
            DEK *dek = NULL;
-            seskeylen = cipher_get_keylen( default_cipher_algo() ) / 8;
+
+            seskeylen = openpgp_cipher_get_algo_keylen (default_cipher_algo ());
             encode_seskey( cfx.dek, &dek, enckey );
-            m_free( cfx.dek ); cfx.dek = dek;
+            xfree( cfx.dek ); cfx.dek = dek;
          }
 
        if(opt.verbose)
          log_info(_("using cipher %s\n"),
-                  cipher_algo_to_string(cfx.dek->algo));
+                  openpgp_cipher_algo_name (cfx.dek->algo));
 
        cfx.dek->use_mdc=use_mdc(NULL,cfx.dek->algo);
     }
@@ -229,28 +254,25 @@ encode_simple( const char *filename, int mode, int use_seskey )
       {
         if (opt.verbose)
           log_info(_("`%s' already compressed\n"), filename);
-        do_compress = 0;        
+        do_compress = 0;
       }
 
     if( rc || (rc = open_outfile( filename, opt.armor? 1:0, &out )) ) {
        iobuf_cancel(inp);
-       m_free(cfx.dek);
-       m_free(s2k);
+       xfree(cfx.dek);
+       xfree(s2k);
+        release_progress_context (pfx);
        return rc;
     }
 
-    if( opt.armor )
-       iobuf_push_filter( out, armor_filter, &afx );
-#ifdef ENABLE_COMMENT_PACKETS
-    else {
-       write_comment( out, "#created by GNUPG v" VERSION " ("
-                                           PRINTABLE_OS_NAME ")");
-       if( opt.comment_string )
-           write_comment( out, opt.comment_string );
-    }
-#endif
+    if ( opt.armor )
+      {
+        afx = new_armor_context ();
+       push_armor_filter (afx, out);
+      }
+
     if( s2k && !RFC1991 ) {
-       PKT_symkey_enc *enc = m_alloc_clear( sizeof *enc + seskeylen + 1 );
+       PKT_symkey_enc *enc = xmalloc_clear( sizeof *enc + seskeylen + 1 );
        enc->version = 4;
        enc->cipher_algo = cfx.dek->algo;
        enc->s2k = *s2k;
@@ -262,25 +284,11 @@ encode_simple( const char *filename, int mode, int use_seskey )
        pkt.pkt.symkey_enc = enc;
        if( (rc = build_packet( out, &pkt )) )
            log_error("build symkey packet failed: %s\n", g10_errstr(rc) );
-       m_free(enc);
+       xfree(enc);
     }
 
-    if (!opt.no_literal) {
-       /* setup the inner packet */
-       if( filename || opt.set_filename ) {
-           char *s = make_basename( opt.set_filename ? opt.set_filename
-                                                     : filename,
-                                    iobuf_get_real_fname( inp ) );
-           pt = m_alloc( sizeof *pt + strlen(s) - 1 );
-           pt->namelen = strlen(s);
-           memcpy(pt->name, s, pt->namelen );
-           m_free(s);
-       }
-       else { /* no filename */
-           pt = m_alloc( sizeof *pt - 1 );
-           pt->namelen = 0;
-       }
-    }
+    if (!opt.no_literal)
+      pt=setup_plaintext_name(filename,inp);
 
     /* Note that PGP 5 has problems decrypting symmetrically encrypted
        data if the file length is in the inner packet. It works when
@@ -293,12 +301,14 @@ encode_simple( const char *filename, int mode, int use_seskey )
        either partial length or fixed length with the new style
        messages. */
 
-    if ( !iobuf_is_pipe_filename (filename) && filename && *filename 
-         && !opt.textmode ) {
+    if ( !iobuf_is_pipe_filename (filename) && *filename && !opt.textmode )
+      {
         off_t tmpsize;
+        int overflow;
 
-       if ( !(tmpsize = iobuf_get_filelength(inp)) )
-          log_info(_("%s: WARNING: empty file\n"), filename );
+       if ( !(tmpsize = iobuf_get_filelength(inp, &overflow))
+             && !overflow && opt.verbose)
+          log_info(_("WARNING: `%s' is an empty file\n"), filename );
         /* We can't encode the length of very large files because
            OpenPGP uses only 32 bit for file sizes.  So if the the
            size of a file is larger than 2^32 minus some bytes for
@@ -307,9 +317,9 @@ encode_simple( const char *filename, int mode, int use_seskey )
           filesize = tmpsize;
         else
           filesize = 0;
-    }
+      }
     else
-       filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */
+      filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */
 
     if (!opt.no_literal) {
        pt->timestamp = make_timestamp();
@@ -350,9 +360,9 @@ encode_simple( const char *filename, int mode, int use_seskey )
        byte copy_buffer[4096];
        int  bytes_copied;
        while ((bytes_copied = iobuf_read(inp, copy_buffer, 4096)) != -1)
-           if (iobuf_write(out, copy_buffer, bytes_copied) == -1) {
-               rc = G10ERR_WRITE_FILE;
-               log_error("copying input to output failed: %s\n", g10_errstr(rc) );
+           if ( (rc=iobuf_write(out, copy_buffer, bytes_copied)) ) {
+               log_error ("copying input to output failed: %s\n",
+                           gpg_strerror (rc) );
                break;
            }
        wipememory(copy_buffer, 4096); /* burn buffer */
@@ -370,25 +380,29 @@ encode_simple( const char *filename, int mode, int use_seskey )
     if (pt)
        pt->buf = NULL;
     free_packet(&pkt);
-    m_free(cfx.dek);
-    m_free(s2k);
+    xfree(cfx.dek);
+    xfree(s2k);
+    release_armor_context (afx);
+    release_progress_context (pfx);
     return rc;
 }
 
 int
 setup_symkey(STRING2KEY **symkey_s2k,DEK **symkey_dek)
 {
-  *symkey_s2k=m_alloc_clear(sizeof(STRING2KEY));
+  int canceled;
+
+  *symkey_s2k=xmalloc_clear(sizeof(STRING2KEY));
   (*symkey_s2k)->mode = opt.s2k_mode;
   (*symkey_s2k)->hash_algo = S2K_DIGEST_ALGO;
 
   *symkey_dek=passphrase_to_dek(NULL,0,opt.s2k_cipher_algo,
-                               *symkey_s2k,2,NULL,NULL);
+                               *symkey_s2k, 4, NULL, &canceled);
   if(!*symkey_dek || !(*symkey_dek)->keylen)
     {
-      m_free(*symkey_dek);
-      m_free(*symkey_s2k);
-      return G10ERR_PASSPHRASE;
+      xfree(*symkey_dek);
+      xfree(*symkey_s2k);
+      return gpg_error (canceled?GPG_ERR_CANCELED:GPG_ERR_BAD_PASSPHRASE);
     }
 
   return 0;
@@ -397,13 +411,13 @@ setup_symkey(STRING2KEY **symkey_s2k,DEK **symkey_dek)
 static int
 write_symkey_enc(STRING2KEY *symkey_s2k,DEK *symkey_dek,DEK *dek,IOBUF out)
 {
-  int rc,seskeylen=cipher_get_keylen(dek->algo)/8;
+  int rc, seskeylen = openpgp_cipher_get_algo_keylen (dek->algo);
 
   PKT_symkey_enc *enc;
   byte enckey[33];
   PACKET pkt;
 
-  enc=m_alloc_clear(sizeof(PKT_symkey_enc)+seskeylen+1);
+  enc=xmalloc_clear(sizeof(PKT_symkey_enc)+seskeylen+1);
   encode_seskey(symkey_dek,&dek,enckey);
 
   enc->version = 4;
@@ -418,7 +432,7 @@ write_symkey_enc(STRING2KEY *symkey_s2k,DEK *symkey_dek,DEK *dek,IOBUF out)
   if((rc=build_packet(out,&pkt)))
     log_error("build symkey_enc packet failed: %s\n",g10_errstr(rc));
 
-  m_free(enc);
+  xfree(enc);
   return rc;
 }
 
@@ -427,7 +441,7 @@ write_symkey_enc(STRING2KEY *symkey_s2k,DEK *symkey_dek,DEK *dek,IOBUF out)
  * is supplied).
  */
 int
-encode_crypt( const char *filename, STRLIST remusr, int use_symkey )
+encode_crypt( const char *filename, strlist_t remusr, int use_symkey )
 {
     IOBUF inp = NULL, out = NULL;
     PACKET pkt;
@@ -437,25 +451,31 @@ encode_crypt( const char *filename, STRLIST remusr, int use_symkey )
     int rc = 0, rc2 = 0;
     u32 filesize;
     cipher_filter_context_t cfx;
-    armor_filter_context_t afx;
+    armor_filter_context_t *afx = NULL;
     compress_filter_context_t zfx;
     text_filter_context_t tfx;
-    progress_filter_context_t pfx;
+    progress_filter_context_t *pfx;
     PK_LIST pk_list,work_list;
     int do_compress = opt.compress_algo && !RFC1991;
 
+    pfx = new_progress_context ();
     memset( &cfx, 0, sizeof cfx);
-    memset( &afx, 0, sizeof afx);
     memset( &zfx, 0, sizeof zfx);
     memset( &tfx, 0, sizeof tfx);
     init_packet(&pkt);
 
     if(use_symkey
        && (rc=setup_symkey(&symkey_s2k,&symkey_dek)))
-      return rc;
+      {
+        release_progress_context (pfx);
+        return rc;
+      }
 
     if( (rc=build_pk_list( remusr, &pk_list, PUBKEY_USAGE_ENC)) )
+      {
+        release_progress_context (pfx);
        return rc;
+      }
 
     if(PGP2) {
       for(work_list=pk_list; work_list; work_list=work_list->next)
@@ -470,16 +490,26 @@ encode_crypt( const char *filename, STRLIST remusr, int use_symkey )
     }
 
     /* prepare iobufs */
-    if( !(inp = iobuf_open(filename)) ) {
-       log_error(_("can't open %s: %s\n"), filename? filename: "[stdin]",
-                                       strerror(errno) );
-       rc = G10ERR_OPEN_FILE;
+    inp = iobuf_open(filename);
+    if (inp)
+      iobuf_ioctl (inp,3,1,NULL); /* disable fd caching */
+    if (inp && is_secured_file (iobuf_get_fd (inp)))
+      {
+        iobuf_close (inp);
+        inp = NULL;
+        errno = EPERM;
+      }
+    if( !inp ) {
+        rc = gpg_error_from_syserror ();
+       log_error(_("can't open `%s': %s\n"),
+                  filename? filename: "[stdin]",
+                  gpg_strerror (rc) );
        goto leave;
     }
     else if( opt.verbose )
        log_info(_("reading from `%s'\n"), filename? filename: "[stdin]");
 
-    handle_progress (&pfx, inp, filename);
+    handle_progress (pfx, inp, filename);
 
     if( opt.textmode )
        iobuf_push_filter( inp, text_filter, &tfx );
@@ -487,19 +517,14 @@ encode_crypt( const char *filename, STRLIST remusr, int use_symkey )
     if( (rc = open_outfile( filename, opt.armor? 1:0, &out )) )
        goto leave;
 
+    if ( opt.armor )
+      {
+        afx = new_armor_context ();
+       push_armor_filter (afx, out);
+      }
 
-    if( opt.armor )
-       iobuf_push_filter( out, armor_filter, &afx );
-#ifdef ENABLE_COMMENT_PACKETS
-    else {
-       write_comment( out, "#created by GNUPG v" VERSION " ("
-                                           PRINTABLE_OS_NAME ")");
-       if( opt.comment_string )
-           write_comment( out, opt.comment_string );
-    }
-#endif
     /* create a session key */
-    cfx.dek = m_alloc_secure_clear (sizeof *cfx.dek);
+    cfx.dek = xmalloc_secure_clear (sizeof *cfx.dek);
     if( !opt.def_cipher_algo ) { /* try to get it from the prefs */
        cfx.dek->algo = select_algo_from_prefs(pk_list,PREFTYPE_SYM,-1,NULL);
        /* The only way select_algo_from_prefs can fail here is when
@@ -518,6 +543,14 @@ encode_crypt( const char *filename, STRLIST remusr, int use_symkey )
              compliance_failure();
            }
        }
+
+        /* In case 3DES has been selected, print a warning if
+           any key does not have a preference for AES.  This
+           should help to indentify why encrypting to several
+           recipients falls back to 3DES. */
+        if (opt.verbose
+            && cfx.dek->algo == CIPHER_ALGO_3DES)
+          warn_missing_aes_from_pklist (pk_list);
     }
     else {
       if(!opt.expert &&
@@ -525,7 +558,7 @@ encode_crypt( const char *filename, STRLIST remusr, int use_symkey )
                                opt.def_cipher_algo,NULL)!=opt.def_cipher_algo)
        log_info(_("WARNING: forcing symmetric cipher %s (%d)"
                   " violates recipient preferences\n"),
-                cipher_algo_to_string(opt.def_cipher_algo),
+                openpgp_cipher_algo_name (opt.def_cipher_algo),
                 opt.def_cipher_algo);
 
       cfx.dek->algo = opt.def_cipher_algo;
@@ -542,7 +575,7 @@ encode_crypt( const char *filename, STRLIST remusr, int use_symkey )
       {
         if (opt.verbose)
           log_info(_("`%s' already compressed\n"), filename);
-        do_compress = 0;        
+        do_compress = 0;
       }
     if (rc2)
       {
@@ -552,7 +585,7 @@ encode_crypt( const char *filename, STRLIST remusr, int use_symkey )
 
     make_session_key( cfx.dek );
     if( DBG_CIPHER )
-       log_hexdump("DEK is: ", cfx.dek->key, cfx.dek->keylen );
+       log_printhex ("DEK is: ", cfx.dek->key, cfx.dek->keylen );
 
     rc = write_pubkey_enc_from_list( pk_list, cfx.dek, out );
     if( rc  )
@@ -565,40 +598,28 @@ encode_crypt( const char *filename, STRLIST remusr, int use_symkey )
     if(use_symkey && (rc=write_symkey_enc(symkey_s2k,symkey_dek,cfx.dek,out)))
       goto leave;
 
-    if (!opt.no_literal) {
-       /* setup the inner packet */
-       if( filename || opt.set_filename ) {
-           char *s = make_basename( opt.set_filename ? opt.set_filename
-                                                     : filename,
-                                    iobuf_get_real_fname( inp ) );
-           pt = m_alloc( sizeof *pt + strlen(s) - 1 );
-           pt->namelen = strlen(s);
-           memcpy(pt->name, s, pt->namelen );
-           m_free(s);
-       }
-       else { /* no filename */
-           pt = m_alloc( sizeof *pt - 1 );
-           pt->namelen = 0;
-       }
-    }
+    if (!opt.no_literal)
+      pt=setup_plaintext_name(filename,inp);
 
-    if (!iobuf_is_pipe_filename (filename) && *filename 
-        && !opt.textmode ) {
+    if (!iobuf_is_pipe_filename (filename) && *filename && !opt.textmode )
+      {
         off_t tmpsize;
+        int overflow;
 
-       if ( !(tmpsize = iobuf_get_filelength(inp)) )
-          log_info(_("%s: WARNING: empty file\n"), filename );
+       if ( !(tmpsize = iobuf_get_filelength(inp, &overflow))
+             && !overflow && opt.verbose)
+          log_info(_("WARNING: `%s' is an empty file\n"), filename );
         /* We can't encode the length of very large files because
            OpenPGP uses only 32 bit for file sizes.  So if the the
            size of a file is larger than 2^32 minus some bytes for
            packet headers, we switch to partial length encoding. */
-        if ( tmpsize < (IOBUF_FILELENGTH_LIMIT - 65536) )
+        if (tmpsize < (IOBUF_FILELENGTH_LIMIT - 65536) )
           filesize = tmpsize;
         else
           filesize = 0;
-    }
+      }
     else
-       filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */
+      filesize = opt.set_filesize ? opt.set_filesize : 0; /* stdin */
 
     if (!opt.no_literal) {
        pt->timestamp = make_timestamp();
@@ -655,10 +676,9 @@ encode_crypt( const char *filename, STRLIST remusr, int use_symkey )
        byte copy_buffer[4096];
        int  bytes_copied;
        while ((bytes_copied = iobuf_read(inp, copy_buffer, 4096)) != -1)
-           if (iobuf_write(out, copy_buffer, bytes_copied) == -1) {
-               rc = G10ERR_WRITE_FILE;
-               log_error("copying input to output failed: %s\n",
-                          g10_errstr(rc) );
+           if ( (rc=iobuf_write(out, copy_buffer, bytes_copied)) ) {
+               log_error ("copying input to output failed: %s\n",
+                           gpg_strerror (rc));
                break;
            }
        wipememory(copy_buffer, 4096); /* burn buffer */
@@ -676,10 +696,12 @@ encode_crypt( const char *filename, STRLIST remusr, int use_symkey )
     if( pt )
        pt->buf = NULL;
     free_packet(&pkt);
-    m_free(cfx.dek);
-    m_free(symkey_dek);
-    m_free(symkey_s2k);
+    xfree(cfx.dek);
+    xfree(symkey_dek);
+    xfree(symkey_s2k);
     release_pk_list( pk_list );
+    release_armor_context (afx);
+    release_progress_context (pfx);
     return rc;
 }
 
@@ -702,7 +724,7 @@ encrypt_filter( void *opaque, int control,
     }
     else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */
        if( !efx->header_okay ) {
-           efx->cfx.dek = m_alloc_secure_clear( sizeof *efx->cfx.dek );
+           efx->cfx.dek = xmalloc_secure_clear( sizeof *efx->cfx.dek );
 
            if( !opt.def_cipher_algo  ) { /* try to get it from the prefs */
                efx->cfx.dek->algo =
@@ -712,6 +734,14 @@ encrypt_filter( void *opaque, int control,
                      * happen if we do not have any public keys in the list */
                    efx->cfx.dek->algo = DEFAULT_CIPHER_ALGO;
                 }
+
+                /* In case 3DES has been selected, print a warning if
+                   any key does not have a preference for AES.  This
+                   should help to indentify why encrypting to several
+                   recipients falls back to 3DES. */
+                if (opt.verbose
+                    && efx->cfx.dek->algo == CIPHER_ALGO_3DES)
+                  warn_missing_aes_from_pklist (efx->pk_list);
            }
            else {
              if(!opt.expert &&
@@ -720,7 +750,7 @@ encrypt_filter( void *opaque, int control,
                                        NULL)!=opt.def_cipher_algo)
                log_info(_("forcing symmetric cipher %s (%d) "
                           "violates recipient preferences\n"),
-                        cipher_algo_to_string(opt.def_cipher_algo),
+                        openpgp_cipher_algo_name (opt.def_cipher_algo),
                         opt.def_cipher_algo);
 
              efx->cfx.dek->algo = opt.def_cipher_algo;
@@ -730,8 +760,8 @@ encrypt_filter( void *opaque, int control,
 
            make_session_key( efx->cfx.dek );
            if( DBG_CIPHER )
-               log_hexdump("DEK is: ",
-                            efx->cfx.dek->key, efx->cfx.dek->keylen );
+               log_printhex ("DEK is: ",
+                              efx->cfx.dek->key, efx->cfx.dek->keylen );
 
            rc = write_pubkey_enc_from_list( efx->pk_list, efx->cfx.dek, a );
            if( rc )
@@ -754,8 +784,8 @@ encrypt_filter( void *opaque, int control,
     }
     else if( control == IOBUFCTRL_FREE )
       {
-       m_free(efx->symkey_dek);
-       m_free(efx->symkey_s2k);
+       xfree(efx->symkey_dek);
+       xfree(efx->symkey_s2k);
       }
     else if( control == IOBUFCTRL_DESC ) {
        *(char**)buf = "encrypt_filter";
@@ -776,12 +806,12 @@ write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out )
     int rc;
 
     for( ; pk_list; pk_list = pk_list->next ) {
-       MPI frame;
+       gcry_mpi_t frame;
 
        pk = pk_list->pk;
 
        print_pubkey_algo_note( pk->pubkey_algo );
-       enc = m_alloc_clear( sizeof *enc );
+       enc = xmalloc_clear( sizeof *enc );
        enc->pubkey_algo = pk->pubkey_algo;
        keyid_from_pk( pk, enc->keyid );
        enc->throw_keyid = (opt.throw_keyid || (pk_list->flags&1));
@@ -806,19 +836,20 @@ write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out )
         * have everything now in enc->data which is the passed to
         * build_packet()
         */
-       frame = encode_session_key( dek, pubkey_nbits( pk->pubkey_algo,
-                                                         pk->pkey ) );
-       rc = pubkey_encrypt( pk->pubkey_algo, enc->data, frame, pk->pkey );
-       mpi_free( frame );
+       frame = encode_session_key (dek, pubkey_nbits (pk->pubkey_algo,
+                                                       pk->pkey) );
+       rc = pk_encrypt (pk->pubkey_algo, enc->data, frame, pk->pkey);
+       gcry_mpi_release (frame);
        if( rc )
-           log_error("pubkey_encrypt failed: %s\n", g10_errstr(rc) );
+           log_error ("pubkey_encrypt failed: %s\n", gpg_strerror (rc) );
        else {
            if( opt.verbose ) {
                char *ustr = get_user_id_string_native (enc->keyid);
                log_info(_("%s/%s encrypted for: \"%s\"\n"),
-                   pubkey_algo_to_string(enc->pubkey_algo),
-                   cipher_algo_to_string(dek->algo), ustr );
-               m_free(ustr);
+                         openpgp_pk_algo_name (enc->pubkey_algo),
+                         openpgp_cipher_algo_name (dek->algo),
+                         ustr );
+               xfree(ustr);
            }
            /* and write it */
            init_packet(&pkt);
@@ -836,16 +867,16 @@ write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out )
 }
 
 void
-encode_crypt_files(int nfiles, char **files, STRLIST remusr)
+encode_crypt_files(int nfiles, char **files, strlist_t remusr)
 {
   int rc = 0;
 
   if (opt.outfile)
     {
       log_error(_("--output doesn't work for this command\n"));
-      return;        
+      return;
     }
-    
+
   if (!nfiles)
     {
       char line[2048];
@@ -861,7 +892,7 @@ encode_crypt_files(int nfiles, char **files, STRLIST remusr)
           line[strlen(line)-1] = '\0';
           print_file_status(STATUS_FILE_START, line, 2);
           if ( (rc = encode_crypt(line, remusr, 0)) )
-            log_error("%s: encryption failed: %s\n",
+            log_error("encryption of `%s' failed: %s\n",
                       print_fname_stdin(line), g10_errstr(rc) );
           write_status( STATUS_FILE_DONE );
         }
@@ -872,7 +903,7 @@ encode_crypt_files(int nfiles, char **files, STRLIST remusr)
         {
           print_file_status(STATUS_FILE_START, *files, 2);
           if ( (rc = encode_crypt(*files, remusr, 0)) )
-            log_error("%s: encryption failed: %s\n",
+            log_error("encryption of `%s' failed: %s\n",
                       print_fname_stdin(*files), g10_errstr(rc) );
           write_status( STATUS_FILE_DONE );
           files++;