gpg: Add new compliance mode "de-vs".
[gnupg.git] / common / sexputil.c
index e18756a..0c5c730 100644 (file)
@@ -25,7 +25,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/>.
  */
 
 /* This file implements a few utility functions useful when working
@@ -45,6 +45,7 @@
 #include "util.h"
 #include "tlv.h"
 #include "sexp-parse.h"
+#include "openpgpdefs.h"  /* for pubkey_algo_t */
 
 
 /* Return a malloced string with the S-expression CANON in advanced
@@ -335,7 +336,7 @@ hash_algo_from_sigval (const unsigned char *sigval)
   if (sskip (&s, &depth) || depth)
     return 0; /* Invalid S-expression.  */
   if (*s != '(')
-    return 0; /* No futher list.  */
+    return 0; /* No further list.  */
   /* Check whether this is (hash ALGO).  */
   s++;
   n = snext (&s);
@@ -370,9 +371,9 @@ make_canon_sexp_from_rsa_pk (const void *m_arg, size_t mlen,
   char mlen_str[35];
   char elen_str[35];
   unsigned char *keybuf, *p;
-  const char const part1[] = "(10:public-key(3:rsa(1:n";
-  const char const part2[] = ")(1:e";
-  const char const part3[] = ")))";
+  const char part1[] = "(10:public-key(3:rsa(1:n";
+  const char part2[] = ")(1:e";
+  const char part3[] = ")))";
 
   /* Remove leading zeroes.  */
   for (; mlen && !*m; mlen--, m++)
@@ -512,17 +513,18 @@ get_rsa_pk_from_canon_sexp (const unsigned char *keydata, size_t keydatalen,
 
 
 /* Return the algo of a public RSA expressed as an canonical encoded
-   S-expression.  On error the algo is set to 0. */
+   S-expression.  The return value is a statically allocated
+   string.  On error that string is set to NULL. */
 gpg_error_t
 get_pk_algo_from_canon_sexp (const unsigned char *keydata, size_t keydatalen,
-                             int *r_algo)
+                             const char **r_algo)
 {
   gpg_error_t err;
   const unsigned char *buf, *tok;
   size_t buflen, toklen;
   int depth;
 
-  *r_algo = 0;
+  *r_algo = NULL;
 
   buf = keydata;
   buflen = keydatalen;
@@ -541,15 +543,66 @@ get_pk_algo_from_canon_sexp (const unsigned char *keydata, size_t keydatalen,
     return gpg_error (GPG_ERR_BAD_PUBKEY);
 
   if (toklen == 3 && !memcmp ("rsa", tok, toklen))
-    *r_algo = GCRY_PK_RSA;
+    *r_algo = "rsa";
   else if (toklen == 3 && !memcmp ("dsa", tok, toklen))
-    *r_algo = GCRY_PK_DSA;
+    *r_algo = "dsa";
   else if (toklen == 3 && !memcmp ("elg", tok, toklen))
-    *r_algo = GCRY_PK_ELG;
+    *r_algo = "elg";
   else if (toklen == 5 && !memcmp ("ecdsa", tok, toklen))
-    *r_algo = GCRY_PK_ECDSA;
+    *r_algo = "ecdsa";
+  else if (toklen == 5 && !memcmp ("eddsa", tok, toklen))
+    *r_algo = "eddsa";
   else
-    return  gpg_error (GPG_ERR_PUBKEY_ALGO);
+    return gpg_error (GPG_ERR_PUBKEY_ALGO);
 
   return 0;
 }
+
+
+/* Return the algo of a public KEY of SEXP. */
+int
+get_pk_algo_from_key (gcry_sexp_t key)
+{
+  gcry_sexp_t list;
+  const char *s;
+  size_t n;
+  char algoname[6];
+  int algo = 0;
+
+  list = gcry_sexp_nth (key, 1);
+  if (!list)
+    goto out;
+  s = gcry_sexp_nth_data (list, 0, &n);
+  if (!s)
+    goto out;
+  if (n >= sizeof (algoname))
+    goto out;
+  memcpy (algoname, s, n);
+  algoname[n] = 0;
+
+  algo = gcry_pk_map_name (algoname);
+  if (algo == GCRY_PK_ECC)
+    {
+      gcry_sexp_t l1 = gcry_sexp_find_token (list, "flags", 0);
+      int i;
+
+      for (i = l1 ? gcry_sexp_length (l1)-1 : 0; i > 0; i--)
+       {
+         s = gcry_sexp_nth_data (l1, i, &n);
+         if (!s)
+           continue; /* Not a data element. */
+
+         if (n == 5 && !memcmp (s, "eddsa", 5))
+           {
+             algo = GCRY_PK_EDDSA;
+             break;
+           }
+       }
+      gcry_sexp_release (l1);
+    }
+
+ out:
+  gcry_sexp_release (list);
+
+  return algo;
+}