* gpg.sgml: Note that --throw-keyid is --throw-keyids. Note changes in
[gnupg.git] / sm / decrypt.c
index e3566fd..17483aa 100644 (file)
@@ -1,5 +1,5 @@
 /* decrypt.c - Decrypt a message
- *     Copyright (C) 2001 Free Software Foundation, Inc.
+ *     Copyright (C) 2001, 2003 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
 #include <time.h>
 #include <assert.h>
 
+#include "gpgsm.h"
 #include <gcrypt.h>
 #include <ksba.h>
 
-#include "gpgsm.h"
 #include "keydb.h"
 #include "i18n.h"
 
@@ -38,7 +38,7 @@ struct decrypt_filter_parm_s {
   int algo;
   int mode;
   int blklen;
-  GCRY_CIPHER_HD hd;
+  gcry_cipher_hd_t hd;
   char iv[16];
   size_t ivlen;
   int any_data;  /* dod we push anything through the filter at all? */
@@ -65,7 +65,7 @@ prepare_decryption (const char *hexkeygrip, KsbaConstSexp enc_val,
                               &seskey, &seskeylen);
   if (rc)
     {
-      log_error ("error decrypting session key: %s\n", gnupg_strerror (rc));
+      log_error ("error decrypting session key: %s\n", gpg_strerror (rc));
       goto leave;
     }
 
@@ -73,49 +73,55 @@ prepare_decryption (const char *hexkeygrip, KsbaConstSexp enc_val,
     log_printhex ("pkcs1 encoded session key:", seskey, seskeylen);
 
   n=0;
-  if (n + 7 > seskeylen )
+  if (seskeylen == 24)
     {
-      rc = seterr (Invalid_Session_Key);
-      goto leave; 
+      /* Smells like a 3-des key.  This might happen because a SC has
+         already done the unpacking. fixme! */
     }
-
-  /* FIXME: Actually the leading zero is required but due to the way
-     we encode the output in libgcrypt as an MPI we are not able to
-     encode that leading zero.  However, when using a Smartcard we are
-     doing it the rightway and therefore we have to skip the zero.  This
-     should be fixed in gpg-agent of course. */
-  if (!seskey[n])
-    n++;
-
-  if (seskey[n] != 2 )  /* wrong block type version */
-    { 
-      rc = seterr (Invalid_Session_Key);
-      goto leave; 
+  else
+    {
+      if (n + 7 > seskeylen )
+        {
+          rc = gpg_error (GPG_ERR_INV_SESSION_KEY);
+          goto leave; 
+        }
+      
+      /* FIXME: Actually the leading zero is required but due to the way
+         we encode the output in libgcrypt as an MPI we are not able to
+         encode that leading zero.  However, when using a Smartcard we are
+         doing it the rightway and therefore we have to skip the zero.  This
+         should be fixed in gpg-agent of course. */
+      if (!seskey[n])
+        n++;
+      
+      if (seskey[n] != 2 )  /* wrong block type version */
+        { 
+          rc = gpg_error (GPG_ERR_INV_SESSION_KEY);
+          goto leave; 
+        }
+      
+      for (n++; n < seskeylen && seskey[n]; n++) /* skip the random bytes */
+        ;
+      n++; /* and the zero byte */
+      if (n >= seskeylen )
+        { 
+          rc = gpg_error (GPG_ERR_INV_SESSION_KEY);
+          goto leave; 
+        }
     }
 
-  for (n++; n < seskeylen && seskey[n]; n++) /* skip the random bytes */
-    ;
-  n++; /* and the zero byte */
-  if (n >= seskeylen )
-    { 
-      rc = seterr (Invalid_Session_Key);
-      goto leave; 
-    }
-  
   if (DBG_CRYPTO)
     log_printhex ("session key:", seskey+n, seskeylen-n);
 
-  parm->hd = gcry_cipher_open (parm->algo, parm->mode, 0);
-  if (!parm->hd)
+  rc = gcry_cipher_open (&parm->hd, parm->algo, parm->mode, 0);
+  if (rc)
     {
-      rc = gcry_errno ();
-      log_error ("error creating decryptor: %s\n", gcry_strerror (rc));
-      rc = map_gcry_err (rc);
+      log_error ("error creating decryptor: %s\n", gpg_strerror (rc));
       goto leave;
     }
                         
   rc = gcry_cipher_setkey (parm->hd, seskey+n, seskeylen-n);
-  if (rc == GCRYERR_WEAK_KEY)
+  if (gpg_err_code (rc) == GPG_ERR_WEAK_KEY)
     {
       log_info (_("WARNING: message was encrypted with "
                   "a weak key in the symmetric cipher.\n"));
@@ -123,8 +129,7 @@ prepare_decryption (const char *hexkeygrip, KsbaConstSexp enc_val,
     }
   if (rc)
     {
-      log_error("key setup failed: %s\n", gcry_strerror(rc) );
-      rc = map_gcry_err (rc);
+      log_error("key setup failed: %s\n", gpg_strerror(rc) );
       goto leave;
     }
 
@@ -253,7 +258,7 @@ gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp)
   if (!kh)
     {
       log_error (_("failed to allocated keyDB handle\n"));
-      rc = GNUPG_General_Error;
+      rc = gpg_error (GPG_ERR_GENERAL);
       goto leave;
     }
 
@@ -261,29 +266,29 @@ gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp)
   in_fp = fdopen ( dup (in_fd), "rb");
   if (!in_fp)
     {
+      rc = gpg_error (gpg_err_code_from_errno (errno));
       log_error ("fdopen() failed: %s\n", strerror (errno));
-      rc = seterr (IO_Error);
       goto leave;
     }
 
   rc = gpgsm_create_reader (&b64reader, ctrl, in_fp, &reader);
   if (rc)
     {
-      log_error ("can't create reader: %s\n", gnupg_strerror (rc));
+      log_error ("can't create reader: %s\n", gpg_strerror (rc));
       goto leave;
     }
 
   rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer);
   if (rc)
     {
-      log_error ("can't create writer: %s\n", gnupg_strerror (rc));
+      log_error ("can't create writer: %s\n", gpg_strerror (rc));
       goto leave;
     }
 
   cms = ksba_cms_new ();
   if (!cms)
     {
-      rc = seterr (Out_Of_Core);
+      rc = gpg_error (GPG_ERR_ENOMEM);
       goto leave;
     }
 
@@ -319,15 +324,27 @@ gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp)
           mode = gcry_cipher_mode_from_oid (algoid);
           if (!algo || !mode)
             {
+              rc = gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
               log_error ("unsupported algorithm `%s'\n", algoid? algoid:"?");
-              rc = GNUPG_Unsupported_Algorithm;
+              if (algoid && !strcmp (algoid, "1.2.840.113549.3.2"))
+                log_info (_("(this is the RC2 algorithm)\n"));
+              else if (!algoid)
+                log_info (_("(this does not seem to be an encrypted"
+                            " message)\n"));
+              {
+                char numbuf[50];
+                sprintf (numbuf, "%d", rc);
+                gpgsm_status2 (ctrl, STATUS_ERROR, "decrypt.algorithm",
+                               numbuf, algoid?algoid:"?", NULL);
+              }
+
               goto leave;
             }
           dfparm.algo = algo;
           dfparm.mode = mode;
           dfparm.blklen = gcry_cipher_get_algo_blklen (algo);
           if (dfparm.blklen > sizeof (dfparm.helpblock))
-            return GNUPG_Bug;
+            return gpg_error (GPG_ERR_BUG);
 
           rc = ksba_cms_get_content_enc_iv (cms,
                                             dfparm.iv,
@@ -368,20 +385,28 @@ gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp)
                   if (rc)
                     {
                       log_error ("failed to find the certificate: %s\n",
-                                 gnupg_strerror(rc));
+                                 gpg_strerror(rc));
                       goto oops;
                     }
 
                   rc = keydb_get_cert (kh, &cert);
                   if (rc)
                     {
-                      log_error ("failed to get cert: %s\n", gnupg_strerror (rc));
+                      log_error ("failed to get cert: %s\n", gpg_strerror (rc));
                       goto oops;     
                     }
                   /* Just in case there is a problem with the own
                      certificate we print this message - should never
                      happen of course */
-                  gpgsm_cert_use_decrypt_p (cert);
+                  rc = gpgsm_cert_use_decrypt_p (cert);
+                  if (rc)
+                    {
+                      char numbuf[50];
+                      sprintf (numbuf, "%d", rc);
+                      gpgsm_status2 (ctrl, STATUS_ERROR, "decrypt.keyusage",
+                                     numbuf, NULL);
+                      rc = 0;
+                    }
 
                   hexkeygrip = gpgsm_get_keygrip_hexstring (cert);
 
@@ -403,7 +428,7 @@ gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp)
                   if (rc)
                     {
                       log_debug ("decrypting session key failed: %s\n",
-                                 gnupg_strerror (rc));
+                                 gpg_strerror (rc));
                     }
                   else
                     { /* setup the bulk decrypter */
@@ -416,7 +441,7 @@ gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp)
             }
           if (!any_key)
             {
-              rc = GNUPG_No_Secret_Key;
+              rc = gpg_error (GPG_ERR_NO_SECKEY);
               goto leave;
             }
         }
@@ -429,7 +454,7 @@ gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp)
               if (!npadding || npadding > dfparm.blklen)
                 {
                   log_error ("invalid padding with value %d\n", npadding);
-                  rc = seterr (Invalid_Data);
+                  rc = gpg_error (GPG_ERR_INV_DATA);
                   goto leave;
                 }
               rc = ksba_writer_write (writer,
@@ -445,7 +470,7 @@ gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp)
                   if (dfparm.lastblock[i] != npadding)
                     {
                       log_error ("inconsistent padding\n");
-                      rc = seterr (Invalid_Data);
+                      rc = gpg_error (GPG_ERR_INV_DATA);
                       goto leave;
                     }
                 }
@@ -458,7 +483,7 @@ gpgsm_decrypt (CTRL ctrl, int in_fd, FILE *out_fp)
   rc = gpgsm_finish_writer (b64writer);
   if (rc) 
     {
-      log_error ("write failed: %s\n", gnupg_strerror (rc));
+      log_error ("write failed: %s\n", gpg_strerror (rc));
       goto leave;
     }
   gpgsm_status (ctrl, STATUS_DECRYPTION_OKAY, NULL);