Remove keyserver helper code.
[gnupg.git] / agent / protect.c
index 3e2cbb9..3a00218 100644 (file)
@@ -1,6 +1,7 @@
 /* protect.c - Un/Protect a secret key
  * Copyright (C) 1998, 1999, 2000, 2001, 2002,
  *               2003, 2007, 2009, 2011 Free Software Foundation, Inc.
+ * Copyright (C) 2013 Werner Koch
  *
  * This file is part of GnuPG.
  *
@@ -28,6 +29,9 @@
 #include <unistd.h>
 #include <sys/stat.h>
 #ifdef HAVE_W32_SYSTEM
+# ifdef HAVE_WINSOCK2_H
+#  include <winsock2.h>
+# endif
 # include <windows.h>
 #else
 # include <sys/times.h>
@@ -35,6 +39,7 @@
 
 #include "agent.h"
 
+#include "cvt-openpgp.h"
 #include "sexp-parse.h"
 
 #define PROT_CIPHER        GCRY_CIPHER_AES
@@ -465,6 +470,7 @@ agent_protect (const unsigned char *plainkey, const char *passphrase,
   int depth = 0;
   unsigned char *p;
   gcry_md_hd_t md;
+  int have_curve = 0;
 
   /* Create an S-expression with the protected-at timestamp.  */
   memcpy (timestamp_exp, "(12:protected-at15:", 19);
@@ -497,6 +503,11 @@ agent_protect (const unsigned char *plainkey, const char *passphrase,
   if (!protect_info[infidx].algo)
     return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
 
+  /* The parser below is a complete mess: To make it robust for ECC
+     use we should reorder the s-expression to include only what we
+     really need and thus guarantee the right order for saving stuff.
+     This should be done before calling this function and maybe with
+     the help of the new gcry_sexp_extract_param.  */
   parmlist      = protect_info[infidx].parmlist;
   prot_from_idx = protect_info[infidx].prot_from;
   prot_to_idx   = protect_info[infidx].prot_to;
@@ -520,10 +531,19 @@ agent_protect (const unsigned char *plainkey, const char *passphrase,
               /* This is a private ECC key but the first parameter is
                  the name of the curve.  We change the parameter list
                  here to the one we expect in this case.  */
+              have_curve = 1;
               parmlist = "?qd";
               prot_from_idx = 2;
               prot_to_idx = 2;
             }
+          else if (n == 5 && !memcmp (s, "flags", 5)
+                   && i == 1 && have_curve)
+            {
+              /* "curve" followed by "flags": Change again.  */
+              parmlist = "??qd";
+              prot_from_idx = 3;
+              prot_to_idx = 3;
+            }
           else
             return gpg_error (GPG_ERR_INV_SEXP);
         }
@@ -604,6 +624,7 @@ agent_protect (const unsigned char *plainkey, const char *passphrase,
   return 0;
 }
 
+
 \f
 /* Do the actual decryption and check the return list for consistency.  */
 static int
@@ -832,9 +853,10 @@ merge_lists (const unsigned char *protectedkey,
 
 /* Unprotect the key encoded in canonical format.  We assume a valid
    S-Exp here.  If a protected-at item is available, its value will
-   be stored at protocted_at unless this is NULL.  */
+   be stored at protected_at unless this is NULL.  */
 int
-agent_unprotect (const unsigned char *protectedkey, const char *passphrase,
+agent_unprotect (ctrl_t ctrl,
+                 const unsigned char *protectedkey, const char *passphrase,
                  gnupg_isotime_t protected_at,
                  unsigned char **result, size_t *resultlen)
 {
@@ -938,7 +960,30 @@ agent_unprotect (const unsigned char *protectedkey, const char *passphrase,
   if (!n)
     return gpg_error (GPG_ERR_INV_SEXP);
   if (!smatch (&s, n, "openpgp-s2k3-sha1-" PROT_CIPHER_STRING "-cbc"))
-    return gpg_error (GPG_ERR_UNSUPPORTED_PROTECTION);
+    {
+      if (smatch (&s, n, "openpgp-native"))
+        {
+          gcry_sexp_t s_prot_begin;
+
+          rc = gcry_sexp_sscan (&s_prot_begin, NULL,
+                                prot_begin,
+                                gcry_sexp_canon_len (prot_begin, 0,NULL,NULL));
+          if (rc)
+            return rc;
+
+          rc = convert_from_openpgp_native (ctrl,
+                                            s_prot_begin, passphrase, &final);
+          gcry_sexp_release (s_prot_begin);
+          if (!rc)
+            {
+              *result = final;
+              *resultlen = gcry_sexp_canon_len (final, 0, NULL, NULL);
+            }
+          return rc;
+        }
+      else
+        return gpg_error (GPG_ERR_UNSUPPORTED_PROTECTION);
+    }
   if (*s != '(' || s[1] != '(')
     return gpg_error (GPG_ERR_INV_SEXP);
   s += 2;