g10: Don't limit at the frontend side for card capability.
[gnupg.git] / agent / protect.c
index a78d5a5..18b44f1 100644 (file)
@@ -15,7 +15,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
 #include "agent.h"
 
 #include "cvt-openpgp.h"
-#include "sexp-parse.h"
+#include "../common/sexp-parse.h"
 
 
-#if GCRYPT_VERSION_NUMBER < 0x010700
-# define OCB_MODE_SUPPORTED 0
-#else
-# define OCB_MODE_SUPPORTED 1
-#endif
-
-/* To use the openpgp-s2k3-ocb-aes scheme by default set the value of
- * this macro to 1.  Note that the caller of agent_protect may
- * override this default.  */
-#define PROT_DEFAULT_TO_OCB 0
-
 /* The protection mode for encryption.  The supported modes for
    decryption are listed in agent_unprotect().  */
 #define PROT_CIPHER        GCRY_CIPHER_AES128
@@ -65,7 +54,7 @@
 
 /* A table containing the information needed to create a protected
    private key.  */
-static struct {
+static const struct {
   const char *algo;
   const char *parmlist;
   int prot_from, prot_to;
@@ -353,16 +342,11 @@ do_encryption (const unsigned char *hashbegin, size_t hashlen,
   *resultlen = 0;
   *result = NULL;
 
-  if (use_ocb && !OCB_MODE_SUPPORTED)
-    return gpg_error (GPG_ERR_UNSUPPORTED_PROTECTION);
-
   modestr = (use_ocb? "openpgp-s2k3-ocb-aes"
              /*   */: "openpgp-s2k3-sha1-" PROT_CIPHER_STRING "-cbc");
 
   rc = gcry_cipher_open (&hd, PROT_CIPHER,
-#if OCB_MODE_SUPPORTED
                          use_ocb? GCRY_CIPHER_MODE_OCB :
-#endif
                          GCRY_CIPHER_MODE_CBC,
                          GCRY_CIPHER_SECURE);
   if (rc)
@@ -397,7 +381,10 @@ do_encryption (const unsigned char *hashbegin, size_t hashlen,
       outbuf = gcry_malloc_secure (outlen);
     }
   if (!outbuf)
-    rc = out_of_core ();
+    {
+      rc = out_of_core ();
+      goto leave;
+    }
 
   /* Allocate a buffer for the nonce and the salt.  */
   if (!rc)
@@ -437,11 +424,13 @@ do_encryption (const unsigned char *hashbegin, size_t hashlen,
         }
     }
 
+  if (rc)
+    goto leave;
+
   /* Set the IV/nonce.  */
-  if (!rc)
-    {
-      rc = gcry_cipher_setiv (hd, iv, use_ocb? 12 : blklen);
-    }
+  rc = gcry_cipher_setiv (hd, iv, use_ocb? 12 : blklen);
+  if (rc)
+    goto leave;
 
   if (use_ocb)
     {
@@ -452,7 +441,6 @@ do_encryption (const unsigned char *hashbegin, size_t hashlen,
       if (!rc)
         rc = gcry_cipher_authenticate
           (hd, protbegin+protlen, hashlen - (protbegin+protlen - hashbegin));
-
     }
   else
     {
@@ -464,9 +452,11 @@ do_encryption (const unsigned char *hashbegin, size_t hashlen,
       rc = gcry_md_open (&md, GCRY_MD_SHA1, 0 );
       if (!rc)
         {
-          gcry_md_write (md, hashbegin, hashlen);
+          gcry_md_write (md, hashbegin, protbegin - hashbegin);
+          gcry_md_write (md, protbegin, protlen);
           gcry_md_write (md, timestamp_exp, timestamp_exp_len);
-          gcry_md_write (md, ")", 1);
+          gcry_md_write (md, protbegin+protlen,
+                         hashlen - (protbegin+protlen - hashbegin));
           memcpy (hashvalue, gcry_md_read (md, GCRY_MD_SHA1), 20);
           gcry_md_close (md);
         }
@@ -498,7 +488,6 @@ do_encryption (const unsigned char *hashbegin, size_t hashlen,
           p += blklen;
         }
       assert ( p - outbuf == outlen);
-#if OCB_MODE_SUPPORTED
       if (use_ocb)
         {
           gcry_cipher_final (hd);
@@ -510,20 +499,16 @@ do_encryption (const unsigned char *hashbegin, size_t hashlen,
             }
         }
       else
-#endif /*OCB_MODE_SUPPORTED*/
         {
           rc = gcry_cipher_encrypt (hd, outbuf, enclen, NULL, 0);
         }
     }
 
+  if (rc)
+    goto leave;
+
   /* Release cipher handle and check for errors.  */
   gcry_cipher_close (hd);
-  if (rc)
-    {
-      xfree (iv);
-      xfree (outbuf);
-      return rc;
-    }
 
   /* Now allocate the buffer we want to return.  This is
 
@@ -562,6 +547,12 @@ do_encryption (const unsigned char *hashbegin, size_t hashlen,
   xfree (iv);
   xfree (outbuf);
   return 0;
+
+ leave:
+  gcry_cipher_close (hd);
+  xfree (iv);
+  xfree (outbuf);
+  return rc;
 }
 
 
@@ -591,7 +582,7 @@ agent_protect (const unsigned char *plainkey, const char *passphrase,
   int have_curve = 0;
 
   if (use_ocb == -1)
-    use_ocb = PROT_DEFAULT_TO_OCB;
+    use_ocb = opt.enable_extended_key_format;
 
   /* Create an S-expression with the protected-at timestamp.  */
   memcpy (timestamp_exp, "(12:protected-at15:", 19);
@@ -701,7 +692,7 @@ agent_protect (const unsigned char *plainkey, const char *passphrase,
     return rc;
 
   /* Now create the protected version of the key.  Note that the 10
-     extra bytes are for for the inserted "protected-" string (the
+     extra bytes are for the inserted "protected-" string (the
      beginning of the plaintext reads: "((11:private-key(" ).  The 35
      term is the space for (12:protected-at15:<timestamp>).  */
   *resultlen = (10
@@ -753,9 +744,6 @@ do_decryption (const unsigned char *aad_begin, size_t aad_len,
   unsigned char *outbuf;
   size_t reallen;
 
-  if (is_ocb && !OCB_MODE_SUPPORTED)
-    return gpg_error (GPG_ERR_UNSUPPORTED_PROTECTION);
-
   blklen = gcry_cipher_get_algo_blklen (prot_cipher);
   if (is_ocb)
     {
@@ -772,9 +760,7 @@ do_decryption (const unsigned char *aad_begin, size_t aad_len,
     }
 
   rc = gcry_cipher_open (&hd, prot_cipher,
-#if OCB_MODE_SUPPORTED
                          is_ocb? GCRY_CIPHER_MODE_OCB :
-#endif
                          GCRY_CIPHER_MODE_CBC,
                          GCRY_CIPHER_SECURE);
   if (rc)
@@ -811,7 +797,6 @@ do_decryption (const unsigned char *aad_begin, size_t aad_len,
   /* Decrypt.  */
   if (!rc)
     {
-#if OCB_MODE_SUPPORTED
       if (is_ocb)
         {
           rc = gcry_cipher_authenticate (hd, aad_begin,
@@ -831,7 +816,6 @@ do_decryption (const unsigned char *aad_begin, size_t aad_len,
             rc = gcry_cipher_checktag (hd, protected + protectedlen - 16, 16);
         }
       else
-#endif /*OCB_MODE_SUPPORTED*/
         {
           rc = gcry_cipher_decrypt (hd, outbuf, protectedlen,
                                     protected, protectedlen);
@@ -1033,7 +1017,7 @@ agent_unprotect (ctrl_t ctrl,
                  gnupg_isotime_t protected_at,
                  unsigned char **result, size_t *resultlen)
 {
-  static struct {
+  static const struct {
     const char *name; /* Name of the protection method. */
     int algo;         /* (A zero indicates the "openpgp-native" hack.)  */
     int keylen;       /* Used key length in bytes.  */
@@ -1175,8 +1159,7 @@ agent_unprotect (ctrl_t ctrl,
         is_ocb = algotable[i].is_ocb;
         break;
       }
-  if (i == DIM (algotable)
-      || (is_ocb && !OCB_MODE_SUPPORTED))
+  if (i == DIM (algotable))
     return gpg_error (GPG_ERR_UNSUPPORTED_PROTECTION);
 
   if (!prot_cipher)  /* This is "openpgp-native".  */