Support ECC and DSA pub keys. master
authorap4y <mail@ap4y.me>
Wed, 3 Apr 2019 08:59:31 +0000 (21:59 +1300)
committerNIIBE Yutaka <gniibe@fsij.org>
Mon, 15 Apr 2019 01:53:17 +0000 (10:53 +0900)
--
Note that ECC means only EdDSA for this patch.  -- gniibe

Signed-off-by: ap4y <mail@ap4y.me>
Some-comments-by: NIIBE Yutaka <gniibe@fsij.org>
src/util/support.c
src/util/support.h

index 8e576c6..773f3d8 100644 (file)
@@ -86,26 +86,17 @@ challenge_verify_sexp (gcry_sexp_t sexp_key,
   gpg_error_t err = GPG_ERR_NO_ERROR;
   gcry_sexp_t sexp_signature = NULL;
   gcry_sexp_t sexp_data = NULL;
-  gcry_mpi_t mpi_signature = NULL;
+  int algo = pk_algo (sexp_key);
 
-  /* Convert buffers into MPIs.  */
-  if (! err)
-    {
-      if (gcry_mpi_scan (&mpi_signature, GCRYMPI_FMT_USG, response, response_n,
-                        NULL))
-       err = gpg_error (GPG_ERR_BAD_MPI);
-    }
+  if (algo == 0)
+    return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
+
+  err = challenge_data (&sexp_data, algo, challenge, challenge_n);
 
-  /* Create according S-Expressions.  */
-  if (! err)
-    err = gcry_sexp_build (&sexp_data, NULL,
-                          "(data (flags pkcs1) (hash sha1 %b))",
-                          challenge_n, challenge);
   if (! err)
-    err = gcry_sexp_build (&sexp_signature, NULL, "(sig-val (rsa (s %m)))",
-                          mpi_signature);
+    err = response_signature (&sexp_signature, algo,
+                              response, response_n);
 
-  /* Verify.  */
   if (! err)
     err = gcry_pk_verify (sexp_signature, sexp_data, sexp_key);
 
@@ -113,8 +104,6 @@ challenge_verify_sexp (gcry_sexp_t sexp_key,
     gcry_sexp_release (sexp_data);
   if (sexp_signature)
     gcry_sexp_release (sexp_signature);
-  if (mpi_signature)
-    gcry_mpi_release (mpi_signature);
 
   return err;
 }
@@ -387,4 +376,69 @@ my_strlen (const char *s)
   return ret;
 }
 
+int
+pk_algo (gcry_sexp_t sexp_key)
+{
+  gcry_sexp_t sexp_data;
+  char *algoname;
+  int algo;
+
+  sexp_data = gcry_sexp_find_token (sexp_key, "public-key", 0);
+  if (!sexp_data)
+    return 0;
+
+  gcry_sexp_t sexp_tmp = gcry_sexp_cadr (sexp_data);
+  gcry_sexp_release (sexp_data);
+  sexp_data = sexp_tmp;
+
+  algoname = gcry_sexp_nth_string (sexp_data, 0);
+  gcry_sexp_release (sexp_data);
+  if (!algoname)
+    return 0;
+
+  algo = gcry_pk_map_name (algoname);
+  xfree(algoname);
+  return algo;
+}
+
+gpg_error_t
+challenge_data (gcry_sexp_t *data, int algo,
+                unsigned char *challenge, size_t challenge_n)
+{
+  if (algo == GCRY_PK_ECC)
+    {
+      return gcry_sexp_build (data, NULL,
+                              "(data (flags eddsa) (hash-algo sha512) (value %b))",
+                              challenge_n, challenge);
+    }
+
+  return gcry_sexp_build (data, NULL,
+                          "(data (flags pkcs1) (hash sha1 %b))",
+                          challenge_n, challenge);
+}
+
+gpg_error_t
+response_signature (gcry_sexp_t *sig, int algo,
+                    unsigned char *response, size_t response_n)
+{
+  switch (algo)
+    {
+    case GCRY_PK_RSA:
+      return gcry_sexp_build (sig, NULL,
+                              "(sig-val (rsa (s %b)))",
+                              response_n, response);
+    case GCRY_PK_DSA:
+      return gcry_sexp_build (sig, NULL,
+                              "(sig-val (dsa (r %b) (s %b)))",
+                              response_n / 2, response,
+                              response_n / 2, response + response_n / 2);
+    case GCRY_PK_ECC:
+      return gcry_sexp_build (sig, NULL,
+                              "(sig-val (eddsa (r %b) (s %b)))",
+                              response_n / 2, response,
+                              response_n / 2, response + response_n / 2);
+    default:
+      return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
+    }
+}
 /* END */
index e25cf01..740ffa0 100644 (file)
@@ -71,6 +71,13 @@ void char_vector_free (char **a);
 
 int my_strlen (const char *s);
 
+int pk_algo (gcry_sexp_t sexp_key);
+
+gpg_error_t challenge_data (gcry_sexp_t *data, int algo,
+                            unsigned char *challenge, size_t challenge_n);
+
+gpg_error_t response_signature (gcry_sexp_t *sig, int algo,
+                                unsigned char *response, size_t response_n);
 #endif
 
 /* END */