[git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-215-g1d23040

by Werner Koch cvs at cvs.gnupg.org
Wed Sep 4 18:49:30 CEST 2013


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "The GNU crypto library".

The branch, master has been updated
       via  1d23040b659661b4086c079cb9fd5f37189a7020 (commit)
       via  603fe44ef4eb44836f0eb472a1aaabbcfa2819c2 (commit)
       via  a70c46e29c480fa0f56ab4814666a5b115f84fd7 (commit)
       via  c47d4001033f68212d2847b3074a0bdda990342e (commit)
       via  c26be7a337d0bf98193bc58e043209e46d0769bb (commit)
       via  8698530b2f9ef95542f1dd550961de7af86cc256 (commit)
       via  b28b1f732e1b4f9c62a9de87c22c6bb0d3f8fdb8 (commit)
      from  4b0edf53440239d3bcc95941980c062a0801a149 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 1d23040b659661b4086c079cb9fd5f37189a7020
Author: Werner Koch <wk at gnupg.org>
Date:   Wed Sep 4 17:51:30 2013 +0200

    Change mpicalc to use Libgcrypt and install it.
    
    * src/mpicalc.c: Make use of gcry_ functions.
    (MPICALC_VERSION): New.  Set to 2.0.
    (strusage): Remove.
    (scan_mpi): New.  Replaces mpi_fromstr.
    (print_mpi): New.  Replaces mpi_print.
    (my_getc): New.
    (print_help): New.
    (main): Use simple option parser and print version info.
    * src/Makefile.am (bin_PROGRAMS): Add mpicalc.
    (mpicalc_SOURCES, mpicalc_CFLAGS, mpicalc_LDADD): New.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/src/Makefile.am b/src/Makefile.am
index d4329c9..507fcd0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -29,7 +29,7 @@ m4data_DATA = libgcrypt.m4
 include_HEADERS = gcrypt.h
 
 lib_LTLIBRARIES = libgcrypt.la
-bin_PROGRAMS = dumpsexp hmac256
+bin_PROGRAMS = dumpsexp hmac256 mpicalc
 if USE_RANDOM_DAEMON
 sbin_PROGRAMS = gcryptrnd
 bin_PROGRAMS += getrandom
@@ -128,6 +128,10 @@ dumpsexp_SOURCES = dumpsexp.c
 dumpsexp_CFLAGS = $(arch_gpg_error_cflags)
 dumpsexp_LDADD = $(arch_gpg_error_libs)
 
+mpicalc_SOURCES = mpicalc.c
+mpicalc_CFLAGS = $(arch_gpg_error_cflags)
+mpicalc_LDADD = ../src/libgcrypt.la $(arch_gpg_error_libs)
+
 hmac256_SOURCES = hmac256.c
 hmac256_CFLAGS = -DSTANDALONE $(arch_gpg_error_cflags)
 hmac256_LDADD = $(arch_gpg_error_libs)
diff --git a/src/mpicalc.c b/src/mpicalc.c
index 7043a4a..762d7c8 100644
--- a/src/mpicalc.c
+++ b/src/mpicalc.c
@@ -21,53 +21,64 @@
    hex.  Operation is like dc(1) except that the input/output radix is
    always 16 and you can use a '-' to prefix a negative number.
    Addition operators: ++ and --.  All operators must be delimited by
-   a blank
+   a blank.
  */
 
-#include <config.h>
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
 #include <stdio.h>
 #include <stdlib.h>
 #include <ctype.h>
 
-#include "util.h"
-#include "mpi.h"
+#ifdef _GCRYPT_IN_LIBGCRYPT
+# undef _GCRYPT_IN_LIBGCRYPT
+# include "gcrypt.h"
+#else
+# include <gcrypt.h>
+#endif
 
 
+#define MPICALC_VERSION "2.0"
+
 #define STACKSIZE  500
 static gcry_mpi_t stack[STACKSIZE];
 static int stackidx;
 
 
-const char *
-strusage (int level)
+static int
+scan_mpi (gcry_mpi_t retval, const char *string)
 {
-  const char *p;
-  switch (level)
+  gpg_error_t err;
+  gcry_mpi_t val;
+
+  err = gcry_mpi_scan (&val, GCRYMPI_FMT_HEX, string, 0, NULL);
+  if (err)
     {
-    case 10:
-    case 0:
-      p = "mpicalc - v" VERSION "; " "Copyright 1997 Werner Koch (dd9jn)";
-      break;
-    case 13:
-      p = "mpicalc";
-      break;
-    case 14:
-      p = VERSION;
-      break;
-    case 1:
-    case 11:
-      p = "Usage: mpicalc (-h for help)";
-      break;
-    case 2:
-    case 12:
-      p =
-	"\nSyntax: mpicalc [options] [files]\n"
-	"Simple big integer RPN calculator\n";
-      break;
-    default:
-      p = default_strusage (level);
+      fprintf (stderr, "scanning input failed: %s\n", gpg_strerror (err));
+      return -1;
+    }
+  mpi_set (retval, val);
+  mpi_release (val);
+  return 0;
+}
+
+
+static void
+print_mpi (gcry_mpi_t a)
+{
+  gpg_error_t err;
+  char *buf;
+  void *bufaddr = &buf;
+
+  err = gcry_mpi_aprint (GCRYMPI_FMT_HEX, bufaddr, NULL, a);
+  if (err)
+    fprintf (stderr, "[error printing number: %s]\n", gpg_strerror (err));
+  else
+    {
+      fputs (buf, stdout);
+      gcry_free (buf);
     }
-  return p;
 }
 
 
@@ -151,7 +162,8 @@ do_div (void)
       fputs ("stack underflow\n", stderr);
       return;
     }
-  mpi_fdiv_q (stack[stackidx - 2], stack[stackidx - 2], stack[stackidx - 1]);
+  mpi_fdiv (stack[stackidx - 2], NULL,
+            stack[stackidx - 2], stack[stackidx - 1]);
   stackidx--;
 }
 
@@ -163,22 +175,23 @@ do_rem (void)
       fputs ("stack underflow\n", stderr);
       return;
     }
-  mpi_fdiv_r (stack[stackidx - 2], stack[stackidx - 2], stack[stackidx - 1]);
+  mpi_mod (stack[stackidx - 2],
+           stack[stackidx - 2], stack[stackidx - 1]);
   stackidx--;
 }
 
 static void
 do_powm (void)
 {
-  MPI a;
+  gcry_mpi_t a;
   if (stackidx < 3)
     {
       fputs ("stack underflow\n", stderr);
       return;
     }
-  a = mpi_alloc (10);
+  a = mpi_new (0);
   mpi_powm (a, stack[stackidx - 3], stack[stackidx - 2], stack[stackidx - 1]);
-  mpi_free (stack[stackidx - 3]);
+  mpi_release (stack[stackidx - 3]);
   stack[stackidx - 3] = a;
   stackidx -= 2;
 }
@@ -186,7 +199,7 @@ do_powm (void)
 static void
 do_inv (void)
 {
-  MPI a = mpi_alloc (40);
+  gcry_mpi_t a = mpi_new (0);
   if (stackidx < 2)
     {
       fputs ("stack underflow\n", stderr);
@@ -194,14 +207,14 @@ do_inv (void)
     }
   mpi_invm (a, stack[stackidx - 2], stack[stackidx - 1]);
   mpi_set (stack[stackidx - 2], a);
-  mpi_free (a);
+  mpi_release (a);
   stackidx--;
 }
 
 static void
 do_gcd (void)
 {
-  MPI a = mpi_alloc (40);
+  gcry_mpi_t a = mpi_new (0);
   if (stackidx < 2)
     {
       fputs ("stack underflow\n", stderr);
@@ -209,7 +222,7 @@ do_gcd (void)
     }
   mpi_gcd (a, stack[stackidx - 2], stack[stackidx - 1]);
   mpi_set (stack[stackidx - 2], a);
-  mpi_free (a);
+  mpi_release (a);
   stackidx--;
 }
 
@@ -225,43 +238,123 @@ do_rshift (void)
 }
 
 
+
+static int
+my_getc (void)
+{
+  static int shown;
+  int c;
+
+  for (;;)
+    {
+      if ((c = getc (stdin)) == EOF)
+        return EOF;
+      if (!(c & 0x80))
+        return c;
+
+      if (!shown)
+        {
+          shown = 1;
+          fputs ("note: Non ASCII characters are ignored\n", stderr);
+        }
+    }
+}
+
+
+static void
+print_help (void)
+{
+  fputs ("+   add           [0] := [1] + [0]          {-1}\n"
+         "-   subtract      [0] := [1] - [0]          {-1}\n"
+         "*   multiply      [0] := [1] * [0]          {-1}\n"
+         "/   divide        [0] := [1] - [0]          {-1}\n"
+         "%   modulo        [0] := [1] % [0]          {-1}\n"
+         ">   right shift   [0] := [0] >> 1           {0}\n"
+         "++  increment     [0] := [0]++              {0}\n"
+         "--  decrement     [0] := [0]--              {0}\n"
+         "m   multiply mod  [0] := [2] * [1] mod [0]  {-2}\n"
+         "^   power mod     [0] := [2] ^ [1] mod [0]  {-2}\n"
+         "I   inverse mod   [0] := [1]^-1 mod [0]     {-1}\n"
+         "G   gcd           [0] := gcd([1],[0])       {-1}\n"
+         "i   remove item   [0] := [1]                {-1}\n"
+         "d   dup item      [-1] := [0]               {+1}\n"
+         "r   reverse       [0] := [1], [1] := [0]    {0}\n"
+         "c   clear stack\n"
+         "p   print top item\n"
+         "f   print the stack\n"
+         "#   ignore until end of line\n"
+         "?   print this help\n"
+         , stdout);
+}
+
+
+
 int
 main (int argc, char **argv)
 {
-  static ARGPARSE_OPTS opts[] = {
-    {0}
-  };
-  ARGPARSE_ARGS pargs;
+  const char *pgm;
+  int last_argc = -1;
   int i, c;
   int state = 0;
   char strbuf[1000];
   int stridx = 0;
 
-  pargs.argc = &argc;
-  pargs.argv = &argv;
-  pargs.flags = 0;
+  if (argc)
+    {
+      pgm = strrchr (*argv, '/');
+      if (pgm)
+        pgm++;
+      else
+        pgm = *argv;
+      argc--; argv++;
+    }
+  else
+    pgm = "?";
 
-  while (arg_parse (&pargs, opts))
+  while (argc && last_argc != argc )
     {
-      switch (pargs.r_opt)
-	{
-	default:
-	  pargs.err = 2;
-	  break;
-	}
+      last_argc = argc;
+      if (!strcmp (*argv, "--"))
+        {
+          argc--; argv++;
+          break;
+        }
+      else if (!strcmp (*argv, "--version")
+               || !strcmp (*argv, "--help"))
+        {
+          printf ("%s " MPICALC_VERSION "\n"
+                  "libgcrypt %s\n"
+                  "Copyright (C) 1997, 2013  Werner Koch\n"
+                  "License LGPLv2.1+: GNU LGPL version 2.1 or later "
+                  "<http://gnu.org/licenses/old-licenses/lgpl-2.1.html>\n"
+                  "This is free software: you are free to change and "
+                  "redistribute it.\n"
+                  "There is NO WARRANTY, to the extent permitted by law.\n"
+                  "\n"
+                  "Syntax: mpicalc [options]\n"
+                  "Simple interactive big integer RPN calculator\n"
+                  "\n"
+                  "Options:\n"
+                  "  --version  print version information\n",
+                  pgm, gcry_check_version (NULL));
+          exit (0);
+        }
     }
-  if (argc)
-    usage (1);
 
+  if (argc)
+    {
+      fprintf (stderr, "usage: %s [options]  (--help for help)\n", pgm);
+      exit (1);
+    }
 
   for (i = 0; i < STACKSIZE; i++)
     stack[i] = NULL;
   stackidx = 0;
 
-  while ((c = getc (stdin)) != EOF)
+  while ((c = my_getc ()) != EOF)
     {
-      if (!state)
-	{			/* waiting */
+      if (!state) /* waiting */
+	{
 	  if (isdigit (c))
 	    {
 	      state = 1;
@@ -276,8 +369,11 @@ main (int argc, char **argv)
 	    {
 	      switch (c)
 		{
+                case '#':
+                  state = 2;
+                  break;
 		case '+':
-		  if ((c = getc (stdin)) == '+')
+		  if ((c = my_getc ()) == '+')
 		    do_inc ();
 		  else
 		    {
@@ -286,7 +382,7 @@ main (int argc, char **argv)
 		    }
 		  break;
 		case '-':
-		  if ((c = getc (stdin)) == '-')
+		  if ((c = my_getc ()) == '-')
 		    do_dec ();
 		  else if (isdigit (c) || (c >= 'A' && c <= 'F'))
 		    {
@@ -318,21 +414,21 @@ main (int argc, char **argv)
 		case '^':
 		  do_powm ();
 		  break;
+		case '>':
+		  do_rshift ();
+		  break;
 		case 'I':
 		  do_inv ();
 		  break;
 		case 'G':
 		  do_gcd ();
 		  break;
-		case '>':
-		  do_rshift ();
-		  break;
 		case 'i':	/* dummy */
 		  if (!stackidx)
 		    fputs ("stack underflow\n", stderr);
 		  else
 		    {
-		      mpi_free (stack[stackidx - 1]);
+		      mpi_release (stack[stackidx - 1]);
 		      stackidx--;
 		    }
 		  break;
@@ -341,16 +437,28 @@ main (int argc, char **argv)
 		    fputs ("stack underflow\n", stderr);
 		  else if (stackidx < STACKSIZE)
 		    {
-		      mpi_free (stack[stackidx]);
+		      mpi_release (stack[stackidx]);
 		      stack[stackidx] = mpi_copy (stack[stackidx - 1]);
 		      stackidx++;
 		    }
 		  else
 		    fputs ("stack overflow\n", stderr);
 		  break;
+		case 'r':	/* swap top elements */
+		  if (stackidx < 2)
+		    fputs ("stack underflow\n", stderr);
+		  else if (stackidx < STACKSIZE)
+		    {
+		      gcry_mpi_t tmp = stack[stackidx-1];
+                      stack[stackidx-1] = stack[stackidx - 2];
+                      stack[stackidx-2] = tmp;
+		    }
+		  break;
 		case 'c':
 		  for (i = 0; i < stackidx; i++)
-		    mpi_free (stack[i]), stack[i] = NULL;
+                    {
+                      mpi_release (stack[i]); stack[i] = NULL;
+                    }
 		  stackidx = 0;
 		  break;
 		case 'p':	/* print the tos */
@@ -358,7 +466,7 @@ main (int argc, char **argv)
 		    puts ("stack is empty");
 		  else
 		    {
-		      mpi_print (stdout, stack[stackidx - 1], 1);
+		      print_mpi (stack[stackidx - 1]);
 		      putchar ('\n');
 		    }
 		  break;
@@ -366,29 +474,33 @@ main (int argc, char **argv)
 		  for (i = stackidx - 1; i >= 0; i--)
 		    {
 		      printf ("[%2d]: ", i);
-		      mpi_print (stdout, stack[i], 1);
+		      print_mpi (stack[i]);
 		      putchar ('\n');
 		    }
 		  break;
+                case '?':
+                  print_help ();
+                  break;
 		default:
 		  fputs ("invalid operator\n", stderr);
 		}
 	    }
 	}
-      else if (state == 1)
-	{			/* in a number */
+      else if (state == 1) /* In a number. */
+	{
 	  if (!isxdigit (c))
-	    {			/* store the number */
+	    {
+              /* Store the number */
 	      state = 0;
 	      ungetc (c, stdin);
-	      if (stridx < 1000)
+	      if (stridx < sizeof strbuf)
 		strbuf[stridx] = 0;
 
 	      if (stackidx < STACKSIZE)
 		{
 		  if (!stack[stackidx])
-		    stack[stackidx] = mpi_alloc (10);
-		  if (mpi_fromstr (stack[stackidx], strbuf))
+		    stack[stackidx] = mpi_new (0);
+		  if (scan_mpi (stack[stackidx], strbuf))
 		    fputs ("invalid number\n", stderr);
 		  else
 		    stackidx++;
@@ -397,20 +509,26 @@ main (int argc, char **argv)
 		fputs ("stack overflow\n", stderr);
 	    }
 	  else
-	    {			/* store digit */
-	      if (stridx < 999)
+	    { /* Store a digit.  */
+	      if (stridx < sizeof strbuf - 1)
 		strbuf[stridx++] = c;
-	      else if (stridx == 999)
+	      else if (stridx == sizeof strbuf - 1)
 		{
 		  strbuf[stridx] = 0;
-		  fputs ("string too large - truncated\n", stderr);
+		  fputs ("input too large - truncated\n", stderr);
 		  stridx++;
 		}
 	    }
 	}
+      else if (state == 2) /* In a comment. */
+        {
+          if (c == '\n')
+            state = 0;
+        }
 
     }
+
   for (i = 0; i < stackidx; i++)
-    mpi_free (stack[i]);
+    mpi_release (stack[i]);
   return 0;
 }

commit 603fe44ef4eb44836f0eb472a1aaabbcfa2819c2
Author: Werner Koch <wk at gnupg.org>
Date:   Wed Sep 4 16:17:11 2013 +0200

    Re-indent mpicalc.c and change license.
    
    --
    
    Changed license to LGPLv2.1+.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/src/mpicalc.c b/src/mpicalc.c
index 46e5fc8..7043a4a 100644
--- a/src/mpicalc.c
+++ b/src/mpicalc.c
@@ -1,29 +1,27 @@
-/* mpicalc.c - test the mpi functions
- * Copyright (C) 1997, 1998, 1999, 2004, 2006  Werner Koch
+/* mpicalc.c - Simple RPN calculator using gcry_mpi functions
+ * Copyright (C) 1997, 1998, 1999, 2004, 2006, 2013  Werner Koch
  *
- * This is an RPN calculator; values must be given in hex.
- * Operation is like dc(1) except that the input/output radix is
- * always 16 and you can use a '-' to prefix a negative number.
- * Addition operators: ++ and --. All operators must be delimited by a blank
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
  *
- * WARNING: This is an old test utility which is not anymore
- *          maintained as part of GnuPG.  However, Libgcrypt has a
- *          copy of it which uses the libgcrypt functions.
- *
- * This file is part of GnuPG.
- *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * GnuPG is distributed in the hope that it will be useful,
+ * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
+ * GNU Lesser 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/>.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+   This program is a simple RPN calculator which was originally used
+   to develop the mpi functions of GnuPG.  Values must be given in
+   hex.  Operation is like dc(1) except that the input/output radix is
+   always 16 and you can use a '-' to prefix a negative number.
+   Addition operators: ++ and --.  All operators must be delimited by
+   a blank
  */
 
 #include <config.h>
@@ -33,354 +31,386 @@
 
 #include "util.h"
 #include "mpi.h"
-#include "i18n.h"
 
-#define STACKSIZE  100
-static MPI stack[STACKSIZE];
+
+#define STACKSIZE  500
+static gcry_mpi_t stack[STACKSIZE];
 static int stackidx;
 
 
 const char *
-strusage( int level )
+strusage (int level)
 {
-    const char *p;
-    switch( level ) {
-      case 10:
-      case 0:	p = "mpicalc - v" VERSION "; "
-		    "Copyright 1997 Werner Koch (dd9jn)" ; break;
-      case 13:	p = "mpicalc"; break;
-      case 14:	p = VERSION; break;
-      case 1:
-      case 11:	p = "Usage: mpicalc (-h for help)";
-		break;
-      case 2:
-      case 12:	p =
-    "\nSyntax: mpicalc [options] [files]\n"
-    "MPI RPN calculator\n";
-	break;
-      default:	p = default_strusage(level);
+  const char *p;
+  switch (level)
+    {
+    case 10:
+    case 0:
+      p = "mpicalc - v" VERSION "; " "Copyright 1997 Werner Koch (dd9jn)";
+      break;
+    case 13:
+      p = "mpicalc";
+      break;
+    case 14:
+      p = VERSION;
+      break;
+    case 1:
+    case 11:
+      p = "Usage: mpicalc (-h for help)";
+      break;
+    case 2:
+    case 12:
+      p =
+	"\nSyntax: mpicalc [options] [files]\n"
+	"Simple big integer RPN calculator\n";
+      break;
+    default:
+      p = default_strusage (level);
     }
-    return p;
+  return p;
 }
 
 
-static void
-i18n_init(void)
-{
-#ifdef ENABLE_NLS
-  setlocale( LC_ALL, "" );
-  bindtextdomain (PACKAGE, LOCALEDIR);
-  textdomain( PACKAGE );
-#endif
-}
-
 
 static void
-do_add(void)
+do_add (void)
 {
-    if( stackidx < 2 ) {
-	fputs("stack underflow\n",stderr);
-	return;
+  if (stackidx < 2)
+    {
+      fputs ("stack underflow\n", stderr);
+      return;
     }
-    mpi_add( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] );
-    stackidx--;
+  mpi_add (stack[stackidx - 2], stack[stackidx - 2], stack[stackidx - 1]);
+  stackidx--;
 }
 
 static void
-do_sub(void)
+do_sub (void)
 {
-    if( stackidx < 2 ) {
-	fputs("stack underflow\n", stderr);
-	return;
+  if (stackidx < 2)
+    {
+      fputs ("stack underflow\n", stderr);
+      return;
     }
-    mpi_sub( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] );
-    stackidx--;
+  mpi_sub (stack[stackidx - 2], stack[stackidx - 2], stack[stackidx - 1]);
+  stackidx--;
 }
 
 static void
-do_inc(void)
+do_inc (void)
 {
-    if( stackidx < 1 ) {
-	fputs("stack underflow\n", stderr);
-	return;
+  if (stackidx < 1)
+    {
+      fputs ("stack underflow\n", stderr);
+      return;
     }
-    mpi_add_ui( stack[stackidx-1], stack[stackidx-1], 1 );
+  mpi_add_ui (stack[stackidx - 1], stack[stackidx - 1], 1);
 }
 
 static void
-do_dec(void)
+do_dec (void)
 {
-    if( stackidx < 1 ) {
-	fputs("stack underflow\n", stderr);
-	return;
+  if (stackidx < 1)
+    {
+      fputs ("stack underflow\n", stderr);
+      return;
     }
- /* mpi_sub_ui( stack[stackidx-1], stack[stackidx-1], 1 ); */
+  /* mpi_sub_ui( stack[stackidx-1], stack[stackidx-1], 1 ); */
 }
 
 static void
-do_mul(void)
+do_mul (void)
 {
-    if( stackidx < 2 ) {
-	fputs("stack underflow\n", stderr);
-	return;
+  if (stackidx < 2)
+    {
+      fputs ("stack underflow\n", stderr);
+      return;
     }
-    mpi_mul( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] );
-    stackidx--;
+  mpi_mul (stack[stackidx - 2], stack[stackidx - 2], stack[stackidx - 1]);
+  stackidx--;
 }
 
 static void
-do_mulm(void)
+do_mulm (void)
 {
-    if( stackidx < 3 ) {
-	fputs("stack underflow\n", stderr);
-	return;
+  if (stackidx < 3)
+    {
+      fputs ("stack underflow\n", stderr);
+      return;
     }
-    mpi_mulm( stack[stackidx-3], stack[stackidx-3],
-				 stack[stackidx-2], stack[stackidx-1] );
-    stackidx -= 2;
+  mpi_mulm (stack[stackidx - 3], stack[stackidx - 3],
+	    stack[stackidx - 2], stack[stackidx - 1]);
+  stackidx -= 2;
 }
 
 static void
-do_div(void)
+do_div (void)
 {
-    if( stackidx < 2 ) {
-	fputs("stack underflow\n", stderr);
-	return;
+  if (stackidx < 2)
+    {
+      fputs ("stack underflow\n", stderr);
+      return;
     }
-    mpi_fdiv_q( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] );
-    stackidx--;
+  mpi_fdiv_q (stack[stackidx - 2], stack[stackidx - 2], stack[stackidx - 1]);
+  stackidx--;
 }
 
 static void
-do_rem(void)
+do_rem (void)
 {
-    if( stackidx < 2 ) {
-	fputs("stack underflow\n", stderr);
-	return;
+  if (stackidx < 2)
+    {
+      fputs ("stack underflow\n", stderr);
+      return;
     }
-    mpi_fdiv_r( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] );
-    stackidx--;
+  mpi_fdiv_r (stack[stackidx - 2], stack[stackidx - 2], stack[stackidx - 1]);
+  stackidx--;
 }
 
 static void
-do_powm(void)
+do_powm (void)
 {
-    MPI a;
-    if( stackidx < 3 ) {
-	fputs("stack underflow\n", stderr);
-	return;
+  MPI a;
+  if (stackidx < 3)
+    {
+      fputs ("stack underflow\n", stderr);
+      return;
     }
-    a= mpi_alloc(10);
-    mpi_powm( a, stack[stackidx-3], stack[stackidx-2], stack[stackidx-1] );
-    mpi_free(stack[stackidx-3]);
-    stack[stackidx-3] = a;
-    stackidx -= 2;
+  a = mpi_alloc (10);
+  mpi_powm (a, stack[stackidx - 3], stack[stackidx - 2], stack[stackidx - 1]);
+  mpi_free (stack[stackidx - 3]);
+  stack[stackidx - 3] = a;
+  stackidx -= 2;
 }
 
 static void
-do_inv(void)
+do_inv (void)
 {
-    MPI a = mpi_alloc(40);
-    if( stackidx < 2 ) {
-	fputs("stack underflow\n", stderr);
-	return;
+  MPI a = mpi_alloc (40);
+  if (stackidx < 2)
+    {
+      fputs ("stack underflow\n", stderr);
+      return;
     }
-    mpi_invm( a, stack[stackidx-2], stack[stackidx-1] );
-    mpi_set(stack[stackidx-2],a);
-    mpi_free(a);
-    stackidx--;
+  mpi_invm (a, stack[stackidx - 2], stack[stackidx - 1]);
+  mpi_set (stack[stackidx - 2], a);
+  mpi_free (a);
+  stackidx--;
 }
 
 static void
-do_gcd(void)
+do_gcd (void)
 {
-    MPI a = mpi_alloc(40);
-    if( stackidx < 2 ) {
-	fputs("stack underflow\n", stderr);
-	return;
+  MPI a = mpi_alloc (40);
+  if (stackidx < 2)
+    {
+      fputs ("stack underflow\n", stderr);
+      return;
     }
-    mpi_gcd( a, stack[stackidx-2], stack[stackidx-1] );
-    mpi_set(stack[stackidx-2],a);
-    mpi_free(a);
-    stackidx--;
+  mpi_gcd (a, stack[stackidx - 2], stack[stackidx - 1]);
+  mpi_set (stack[stackidx - 2], a);
+  mpi_free (a);
+  stackidx--;
 }
 
 static void
-do_rshift(void)
+do_rshift (void)
 {
-    if( stackidx < 1 ) {
-	fputs("stack underflow\n", stderr);
-	return;
+  if (stackidx < 1)
+    {
+      fputs ("stack underflow\n", stderr);
+      return;
     }
-    mpi_rshift( stack[stackidx-1],stack[stackidx-1], 1 );
+  mpi_rshift (stack[stackidx - 1], stack[stackidx - 1], 1);
 }
 
 
 int
-main(int argc, char **argv)
+main (int argc, char **argv)
 {
-    static ARGPARSE_OPTS opts[] = {
-    {0} };
-    ARGPARSE_ARGS pargs;
-    int i, c;
-    int state = 0;
-    char strbuf[1000];
-    int stridx=0;
+  static ARGPARSE_OPTS opts[] = {
+    {0}
+  };
+  ARGPARSE_ARGS pargs;
+  int i, c;
+  int state = 0;
+  char strbuf[1000];
+  int stridx = 0;
 
-    pargs.argc = &argc;
-    pargs.argv = &argv;
-    pargs.flags = 0;
+  pargs.argc = &argc;
+  pargs.argv = &argv;
+  pargs.flags = 0;
 
-    i18n_init();
-    while( arg_parse( &pargs, opts) ) {
-	switch( pargs.r_opt ) {
-	  default : pargs.err = 2; break;
+  while (arg_parse (&pargs, opts))
+    {
+      switch (pargs.r_opt)
+	{
+	default:
+	  pargs.err = 2;
+	  break;
 	}
     }
-    if( argc )
-	usage(1);
+  if (argc)
+    usage (1);
 
 
-    for(i=0; i < STACKSIZE; i++ )
-	stack[i] = NULL;
-    stackidx =0;
+  for (i = 0; i < STACKSIZE; i++)
+    stack[i] = NULL;
+  stackidx = 0;
 
-    while( (c=getc(stdin)) != EOF ) {
-	if( !state ) {	/* waiting */
-	    if( isdigit(c) ) {
-		state = 1;
-		ungetc(c, stdin);
-		strbuf[0] = '0';
-		strbuf[1] = 'x';
-		stridx=2;
+  while ((c = getc (stdin)) != EOF)
+    {
+      if (!state)
+	{			/* waiting */
+	  if (isdigit (c))
+	    {
+	      state = 1;
+	      ungetc (c, stdin);
+	      strbuf[0] = '0';
+	      strbuf[1] = 'x';
+	      stridx = 2;
 	    }
-	    else if( isspace(c) )
-		;
-	    else {
-		switch(c) {
-		  case '+':
-		    if( (c=getc(stdin)) == '+' )
-			do_inc();
-		    else {
-			ungetc(c, stdin);
-			do_add();
+	  else if (isspace (c))
+	    ;
+	  else
+	    {
+	      switch (c)
+		{
+		case '+':
+		  if ((c = getc (stdin)) == '+')
+		    do_inc ();
+		  else
+		    {
+		      ungetc (c, stdin);
+		      do_add ();
 		    }
-		    break;
-		  case '-':
-		    if( (c=getc(stdin)) == '-' )
-			do_dec();
-		    else if( isdigit(c) || (c >='A' && c <= 'F') ) {
-			state = 1;
-			ungetc(c, stdin);
-			strbuf[0] = '-';
-			strbuf[1] = '0';
-			strbuf[2] = 'x';
-			stridx=3;
+		  break;
+		case '-':
+		  if ((c = getc (stdin)) == '-')
+		    do_dec ();
+		  else if (isdigit (c) || (c >= 'A' && c <= 'F'))
+		    {
+		      state = 1;
+		      ungetc (c, stdin);
+		      strbuf[0] = '-';
+		      strbuf[1] = '0';
+		      strbuf[2] = 'x';
+		      stridx = 3;
 		    }
-		    else {
-			ungetc(c, stdin);
-			do_sub();
+		  else
+		    {
+		      ungetc (c, stdin);
+		      do_sub ();
 		    }
-		    break;
-		  case '*':
-		    do_mul();
-		    break;
-		  case 'm':
-		    do_mulm();
-		    break;
-		  case '/':
-		    do_div();
-		    break;
-		  case '%':
-		    do_rem();
-		    break;
-		  case '^':
-		    do_powm();
-		    break;
-		  case 'I':
-		    do_inv();
-		    break;
-		  case 'G':
-		    do_gcd();
-		    break;
-		  case '>':
-		    do_rshift();
-		    break;
-		  case 'i': /* dummy */
-		    if( !stackidx )
-			fputs("stack underflow\n", stderr);
-		    else {
-			mpi_free(stack[stackidx-1]);
-			stackidx--;
+		  break;
+		case '*':
+		  do_mul ();
+		  break;
+		case 'm':
+		  do_mulm ();
+		  break;
+		case '/':
+		  do_div ();
+		  break;
+		case '%':
+		  do_rem ();
+		  break;
+		case '^':
+		  do_powm ();
+		  break;
+		case 'I':
+		  do_inv ();
+		  break;
+		case 'G':
+		  do_gcd ();
+		  break;
+		case '>':
+		  do_rshift ();
+		  break;
+		case 'i':	/* dummy */
+		  if (!stackidx)
+		    fputs ("stack underflow\n", stderr);
+		  else
+		    {
+		      mpi_free (stack[stackidx - 1]);
+		      stackidx--;
 		    }
-		    break;
-		  case 'd': /* duplicate the tos */
-		    if( !stackidx )
-			fputs("stack underflow\n", stderr);
-		    else if( stackidx < STACKSIZE ) {
-			mpi_free(stack[stackidx]);
-			stack[stackidx] = mpi_copy( stack[stackidx-1] );
-			stackidx++;
+		  break;
+		case 'd':	/* duplicate the tos */
+		  if (!stackidx)
+		    fputs ("stack underflow\n", stderr);
+		  else if (stackidx < STACKSIZE)
+		    {
+		      mpi_free (stack[stackidx]);
+		      stack[stackidx] = mpi_copy (stack[stackidx - 1]);
+		      stackidx++;
 		    }
-		    else
-			fputs("stack overflow\n", stderr);
-		    break;
-		  case 'c':
-		    for(i=0; i < stackidx; i++ )
-			mpi_free(stack[i]), stack[i] = NULL;
-		    stackidx = 0;
-		    break;
-		  case 'p': /* print the tos */
-		    if( !stackidx )
-			puts("stack is empty");
-		    else {
-			mpi_print(stdout, stack[stackidx-1], 1 );
-			putchar('\n');
+		  else
+		    fputs ("stack overflow\n", stderr);
+		  break;
+		case 'c':
+		  for (i = 0; i < stackidx; i++)
+		    mpi_free (stack[i]), stack[i] = NULL;
+		  stackidx = 0;
+		  break;
+		case 'p':	/* print the tos */
+		  if (!stackidx)
+		    puts ("stack is empty");
+		  else
+		    {
+		      mpi_print (stdout, stack[stackidx - 1], 1);
+		      putchar ('\n');
 		    }
-		    break;
-		  case 'f': /* print the stack */
-		    for( i = stackidx-1 ; i >= 0; i-- ) {
-			printf("[%2d]: ", i );
-			mpi_print(stdout, stack[i], 1 );
-			putchar('\n');
+		  break;
+		case 'f':	/* print the stack */
+		  for (i = stackidx - 1; i >= 0; i--)
+		    {
+		      printf ("[%2d]: ", i);
+		      mpi_print (stdout, stack[i], 1);
+		      putchar ('\n');
 		    }
-		    break;
-		  default:
-		    fputs("invalid operator\n", stderr);
+		  break;
+		default:
+		  fputs ("invalid operator\n", stderr);
 		}
 	    }
 	}
-	else if( state == 1 ) { /* in a number */
-	    if( !isxdigit(c) ) { /* store the number */
-		state = 0;
-		ungetc(c, stdin);
-		if( stridx < 1000 )
-		    strbuf[stridx] = 0;
+      else if (state == 1)
+	{			/* in a number */
+	  if (!isxdigit (c))
+	    {			/* store the number */
+	      state = 0;
+	      ungetc (c, stdin);
+	      if (stridx < 1000)
+		strbuf[stridx] = 0;
 
-		if( stackidx < STACKSIZE ) {
-		    if( !stack[stackidx] )
-			stack[stackidx] = mpi_alloc(10);
-		    if( mpi_fromstr(stack[stackidx], strbuf) )
-			fputs("invalid number\n", stderr);
-		    else
-			stackidx++;
+	      if (stackidx < STACKSIZE)
+		{
+		  if (!stack[stackidx])
+		    stack[stackidx] = mpi_alloc (10);
+		  if (mpi_fromstr (stack[stackidx], strbuf))
+		    fputs ("invalid number\n", stderr);
+		  else
+		    stackidx++;
 		}
-		else
-		    fputs("stack overflow\n", stderr);
+	      else
+		fputs ("stack overflow\n", stderr);
 	    }
-	    else { /* store digit */
-		if( stridx < 999 )
-		    strbuf[stridx++] = c;
-		else if( stridx == 999 ) {
-		    strbuf[stridx] = 0;
-		    fputs("string too large - truncated\n", stderr);
-		    stridx++;
+	  else
+	    {			/* store digit */
+	      if (stridx < 999)
+		strbuf[stridx++] = c;
+	      else if (stridx == 999)
+		{
+		  strbuf[stridx] = 0;
+		  fputs ("string too large - truncated\n", stderr);
+		  stridx++;
 		}
 	    }
 	}
 
     }
-    for(i=0; i < stackidx; i++ )
-	mpi_free(stack[i]);
-    return 0;
+  for (i = 0; i < stackidx; i++)
+    mpi_free (stack[i]);
+  return 0;
 }

commit a70c46e29c480fa0f56ab4814666a5b115f84fd7
Author: Werner Koch <wk at gnupg.org>
Date:   Wed Sep 4 15:37:01 2013 +0200

    Add mpicalc.c to help with testing.
    
    * src/mpicalc.c: Take from GnuPG 1.4
    --
    
    Taken from GnuPG commit 45efde9557661ea071a01bcb938f1591ed4ec1a3

diff --git a/src/mpicalc.c b/src/mpicalc.c
new file mode 100644
index 0000000..46e5fc8
--- /dev/null
+++ b/src/mpicalc.c
@@ -0,0 +1,386 @@
+/* mpicalc.c - test the mpi functions
+ * Copyright (C) 1997, 1998, 1999, 2004, 2006  Werner Koch
+ *
+ * This is an RPN calculator; values must be given in hex.
+ * Operation is like dc(1) except that the input/output radix is
+ * always 16 and you can use a '-' to prefix a negative number.
+ * Addition operators: ++ and --. All operators must be delimited by a blank
+ *
+ * WARNING: This is an old test utility which is not anymore
+ *          maintained as part of GnuPG.  However, Libgcrypt has a
+ *          copy of it which uses the libgcrypt functions.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * 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/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "util.h"
+#include "mpi.h"
+#include "i18n.h"
+
+#define STACKSIZE  100
+static MPI stack[STACKSIZE];
+static int stackidx;
+
+
+const char *
+strusage( int level )
+{
+    const char *p;
+    switch( level ) {
+      case 10:
+      case 0:	p = "mpicalc - v" VERSION "; "
+		    "Copyright 1997 Werner Koch (dd9jn)" ; break;
+      case 13:	p = "mpicalc"; break;
+      case 14:	p = VERSION; break;
+      case 1:
+      case 11:	p = "Usage: mpicalc (-h for help)";
+		break;
+      case 2:
+      case 12:	p =
+    "\nSyntax: mpicalc [options] [files]\n"
+    "MPI RPN calculator\n";
+	break;
+      default:	p = default_strusage(level);
+    }
+    return p;
+}
+
+
+static void
+i18n_init(void)
+{
+#ifdef ENABLE_NLS
+  setlocale( LC_ALL, "" );
+  bindtextdomain (PACKAGE, LOCALEDIR);
+  textdomain( PACKAGE );
+#endif
+}
+
+
+static void
+do_add(void)
+{
+    if( stackidx < 2 ) {
+	fputs("stack underflow\n",stderr);
+	return;
+    }
+    mpi_add( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] );
+    stackidx--;
+}
+
+static void
+do_sub(void)
+{
+    if( stackidx < 2 ) {
+	fputs("stack underflow\n", stderr);
+	return;
+    }
+    mpi_sub( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] );
+    stackidx--;
+}
+
+static void
+do_inc(void)
+{
+    if( stackidx < 1 ) {
+	fputs("stack underflow\n", stderr);
+	return;
+    }
+    mpi_add_ui( stack[stackidx-1], stack[stackidx-1], 1 );
+}
+
+static void
+do_dec(void)
+{
+    if( stackidx < 1 ) {
+	fputs("stack underflow\n", stderr);
+	return;
+    }
+ /* mpi_sub_ui( stack[stackidx-1], stack[stackidx-1], 1 ); */
+}
+
+static void
+do_mul(void)
+{
+    if( stackidx < 2 ) {
+	fputs("stack underflow\n", stderr);
+	return;
+    }
+    mpi_mul( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] );
+    stackidx--;
+}
+
+static void
+do_mulm(void)
+{
+    if( stackidx < 3 ) {
+	fputs("stack underflow\n", stderr);
+	return;
+    }
+    mpi_mulm( stack[stackidx-3], stack[stackidx-3],
+				 stack[stackidx-2], stack[stackidx-1] );
+    stackidx -= 2;
+}
+
+static void
+do_div(void)
+{
+    if( stackidx < 2 ) {
+	fputs("stack underflow\n", stderr);
+	return;
+    }
+    mpi_fdiv_q( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] );
+    stackidx--;
+}
+
+static void
+do_rem(void)
+{
+    if( stackidx < 2 ) {
+	fputs("stack underflow\n", stderr);
+	return;
+    }
+    mpi_fdiv_r( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] );
+    stackidx--;
+}
+
+static void
+do_powm(void)
+{
+    MPI a;
+    if( stackidx < 3 ) {
+	fputs("stack underflow\n", stderr);
+	return;
+    }
+    a= mpi_alloc(10);
+    mpi_powm( a, stack[stackidx-3], stack[stackidx-2], stack[stackidx-1] );
+    mpi_free(stack[stackidx-3]);
+    stack[stackidx-3] = a;
+    stackidx -= 2;
+}
+
+static void
+do_inv(void)
+{
+    MPI a = mpi_alloc(40);
+    if( stackidx < 2 ) {
+	fputs("stack underflow\n", stderr);
+	return;
+    }
+    mpi_invm( a, stack[stackidx-2], stack[stackidx-1] );
+    mpi_set(stack[stackidx-2],a);
+    mpi_free(a);
+    stackidx--;
+}
+
+static void
+do_gcd(void)
+{
+    MPI a = mpi_alloc(40);
+    if( stackidx < 2 ) {
+	fputs("stack underflow\n", stderr);
+	return;
+    }
+    mpi_gcd( a, stack[stackidx-2], stack[stackidx-1] );
+    mpi_set(stack[stackidx-2],a);
+    mpi_free(a);
+    stackidx--;
+}
+
+static void
+do_rshift(void)
+{
+    if( stackidx < 1 ) {
+	fputs("stack underflow\n", stderr);
+	return;
+    }
+    mpi_rshift( stack[stackidx-1],stack[stackidx-1], 1 );
+}
+
+
+int
+main(int argc, char **argv)
+{
+    static ARGPARSE_OPTS opts[] = {
+    {0} };
+    ARGPARSE_ARGS pargs;
+    int i, c;
+    int state = 0;
+    char strbuf[1000];
+    int stridx=0;
+
+    pargs.argc = &argc;
+    pargs.argv = &argv;
+    pargs.flags = 0;
+
+    i18n_init();
+    while( arg_parse( &pargs, opts) ) {
+	switch( pargs.r_opt ) {
+	  default : pargs.err = 2; break;
+	}
+    }
+    if( argc )
+	usage(1);
+
+
+    for(i=0; i < STACKSIZE; i++ )
+	stack[i] = NULL;
+    stackidx =0;
+
+    while( (c=getc(stdin)) != EOF ) {
+	if( !state ) {	/* waiting */
+	    if( isdigit(c) ) {
+		state = 1;
+		ungetc(c, stdin);
+		strbuf[0] = '0';
+		strbuf[1] = 'x';
+		stridx=2;
+	    }
+	    else if( isspace(c) )
+		;
+	    else {
+		switch(c) {
+		  case '+':
+		    if( (c=getc(stdin)) == '+' )
+			do_inc();
+		    else {
+			ungetc(c, stdin);
+			do_add();
+		    }
+		    break;
+		  case '-':
+		    if( (c=getc(stdin)) == '-' )
+			do_dec();
+		    else if( isdigit(c) || (c >='A' && c <= 'F') ) {
+			state = 1;
+			ungetc(c, stdin);
+			strbuf[0] = '-';
+			strbuf[1] = '0';
+			strbuf[2] = 'x';
+			stridx=3;
+		    }
+		    else {
+			ungetc(c, stdin);
+			do_sub();
+		    }
+		    break;
+		  case '*':
+		    do_mul();
+		    break;
+		  case 'm':
+		    do_mulm();
+		    break;
+		  case '/':
+		    do_div();
+		    break;
+		  case '%':
+		    do_rem();
+		    break;
+		  case '^':
+		    do_powm();
+		    break;
+		  case 'I':
+		    do_inv();
+		    break;
+		  case 'G':
+		    do_gcd();
+		    break;
+		  case '>':
+		    do_rshift();
+		    break;
+		  case 'i': /* dummy */
+		    if( !stackidx )
+			fputs("stack underflow\n", stderr);
+		    else {
+			mpi_free(stack[stackidx-1]);
+			stackidx--;
+		    }
+		    break;
+		  case 'd': /* duplicate the tos */
+		    if( !stackidx )
+			fputs("stack underflow\n", stderr);
+		    else if( stackidx < STACKSIZE ) {
+			mpi_free(stack[stackidx]);
+			stack[stackidx] = mpi_copy( stack[stackidx-1] );
+			stackidx++;
+		    }
+		    else
+			fputs("stack overflow\n", stderr);
+		    break;
+		  case 'c':
+		    for(i=0; i < stackidx; i++ )
+			mpi_free(stack[i]), stack[i] = NULL;
+		    stackidx = 0;
+		    break;
+		  case 'p': /* print the tos */
+		    if( !stackidx )
+			puts("stack is empty");
+		    else {
+			mpi_print(stdout, stack[stackidx-1], 1 );
+			putchar('\n');
+		    }
+		    break;
+		  case 'f': /* print the stack */
+		    for( i = stackidx-1 ; i >= 0; i-- ) {
+			printf("[%2d]: ", i );
+			mpi_print(stdout, stack[i], 1 );
+			putchar('\n');
+		    }
+		    break;
+		  default:
+		    fputs("invalid operator\n", stderr);
+		}
+	    }
+	}
+	else if( state == 1 ) { /* in a number */
+	    if( !isxdigit(c) ) { /* store the number */
+		state = 0;
+		ungetc(c, stdin);
+		if( stridx < 1000 )
+		    strbuf[stridx] = 0;
+
+		if( stackidx < STACKSIZE ) {
+		    if( !stack[stackidx] )
+			stack[stackidx] = mpi_alloc(10);
+		    if( mpi_fromstr(stack[stackidx], strbuf) )
+			fputs("invalid number\n", stderr);
+		    else
+			stackidx++;
+		}
+		else
+		    fputs("stack overflow\n", stderr);
+	    }
+	    else { /* store digit */
+		if( stridx < 999 )
+		    strbuf[stridx++] = c;
+		else if( stridx == 999 ) {
+		    strbuf[stridx] = 0;
+		    fputs("string too large - truncated\n", stderr);
+		    stridx++;
+		}
+	    }
+	}
+
+    }
+    for(i=0; i < stackidx; i++ )
+	mpi_free(stack[i]);
+    return 0;
+}

commit c47d4001033f68212d2847b3074a0bdda990342e
Author: Werner Koch <wk at gnupg.org>
Date:   Wed Sep 4 11:20:57 2013 +0200

    Prepare support for EdDSA.
    
    * src/cipher.h (PUBKEY_FLAG_EDDSA): New.
    * cipher/pubkey.c (pubkey_verify): Repalce args CMP and OPAQUEV by
    CTX.  Pass flags and hash algo to the verify function.  Change all
    verify functions to accept these args.
    (sexp_data_to_mpi): Implement new flag "eddsa".
    (gcry_pk_verify): Pass CTX instead of the compare function to
    pubkey_verify.
    * cipher/ecc.c (sign): Rename to sign_ecdsa.  Change all callers.
    (verify): Rename to verify_ecdsa.  Change all callers.
    (sign_eddsa, verify_eddsa): New stub functions.
    (ecc_sign): Divert to sign_ecdsa or sign_eddsa.
    (ecc_verify): Divert to verify_ecdsa or verify_eddsa.

diff --git a/cipher/dsa.c b/cipher/dsa.c
index ac2dee1..3a64dda 100644
--- a/cipher/dsa.c
+++ b/cipher/dsa.c
@@ -1004,7 +1004,8 @@ dsa_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey,
 
 static gcry_err_code_t
 dsa_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey,
-            int (*cmp) (void *, gcry_mpi_t), void *opaquev)
+            int (*cmp) (void *, gcry_mpi_t), void *opaquev,
+            int flags, int hashalgo)
 {
   gcry_err_code_t err = GPG_ERR_NO_ERROR;
   DSA_public_key pk;
@@ -1012,6 +1013,8 @@ dsa_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey,
   (void)algo;
   (void)cmp;
   (void)opaquev;
+  (void)flags;
+  (void)hashalgo;
 
   if ((! data[0]) || (! data[1]) || (! hash)
       || (! pkey[0]) || (! pkey[1]) || (! pkey[2]) || (! pkey[3]))
diff --git a/cipher/ecc.c b/cipher/ecc.c
index 8a7ca0b..0cb279f 100644
--- a/cipher/ecc.c
+++ b/cipher/ecc.c
@@ -77,12 +77,11 @@ static void *progress_cb_data;
 /* Local prototypes. */
 static void test_keys (ECC_secret_key * sk, unsigned int nbits);
 static int check_secret_key (ECC_secret_key * sk);
-static gpg_err_code_t sign (gcry_mpi_t input, ECC_secret_key *skey,
-                            gcry_mpi_t r, gcry_mpi_t s,
-                            int flags, int hashalgo);
-static gpg_err_code_t verify (gcry_mpi_t input, ECC_public_key *pkey,
-                              gcry_mpi_t r, gcry_mpi_t s);
-
+static gpg_err_code_t sign_ecdsa (gcry_mpi_t input, ECC_secret_key *skey,
+                                  gcry_mpi_t r, gcry_mpi_t s,
+                                  int flags, int hashalgo);
+static gpg_err_code_t verify_ecdsa (gcry_mpi_t input, ECC_public_key *pkey,
+                                    gcry_mpi_t r, gcry_mpi_t s);
 
 static gcry_mpi_t gen_y_2 (gcry_mpi_t x, elliptic_curve_t * base);
 
@@ -284,10 +283,10 @@ test_keys (ECC_secret_key *sk, unsigned int nbits)
 
   gcry_mpi_randomize (test, nbits, GCRY_WEAK_RANDOM);
 
-  if (sign (test, sk, r, s, 0, 0) )
+  if (sign_ecdsa (test, sk, r, s, 0, 0) )
     log_fatal ("ECDSA operation: sign failed\n");
 
-  if (verify (test, &pk, r, s))
+  if (verify_ecdsa (test, &pk, r, s))
     {
       log_fatal ("ECDSA operation: sign, verify failed\n");
     }
@@ -411,13 +410,13 @@ check_secret_key (ECC_secret_key * sk)
 }
 
 
-/*
+/* Compute an ECDSA signature.
  * Return the signature struct (r,s) from the message hash.  The caller
  * must have allocated R and S.
  */
 static gpg_err_code_t
-sign (gcry_mpi_t input, ECC_secret_key *skey, gcry_mpi_t r, gcry_mpi_t s,
-      int flags, int hashalgo)
+sign_ecdsa (gcry_mpi_t input, ECC_secret_key *skey, gcry_mpi_t r, gcry_mpi_t s,
+            int flags, int hashalgo)
 {
   gpg_err_code_t err = 0;
   int extraloops = 0;
@@ -532,11 +531,12 @@ sign (gcry_mpi_t input, ECC_secret_key *skey, gcry_mpi_t r, gcry_mpi_t s,
 }
 
 
-/*
+/* Verify an ECDSA signature.
  * Check if R and S verifies INPUT.
  */
 static gpg_err_code_t
-verify (gcry_mpi_t input, ECC_public_key *pkey, gcry_mpi_t r, gcry_mpi_t s)
+verify_ecdsa (gcry_mpi_t input, ECC_public_key *pkey,
+              gcry_mpi_t r, gcry_mpi_t s)
 {
   gpg_err_code_t err = 0;
   gcry_mpi_t h, h1, h2, x;
@@ -615,6 +615,59 @@ verify (gcry_mpi_t input, ECC_public_key *pkey, gcry_mpi_t r, gcry_mpi_t s)
 
 
 

+/* Compute an EdDSA signature. See:
+ *   [ed25519] 23pp. (PDF) Daniel J. Bernstein, Niels Duif, Tanja
+ *   Lange, Peter Schwabe, Bo-Yin Yang. High-speed high-security
+ *   signatures.  Journal of Cryptographic Engineering 2 (2012), 77-89.
+ *   Document ID: a1a62a2f76d23f65d622484ddd09caf8.
+ *   URL: http://cr.yp.to/papers.html#ed25519. Date: 2011.09.26.
+ *
+ * Despite that this function requires the specification of a hash
+ * algorithm, we only support what has been specified by the paper.
+ * This may change in the future.  Note that we don't check the used
+ * curve; the user is responsible to use Ed25519.
+ *
+ * Return the signature struct (r,s) from the message hash.  The caller
+ * must have allocated R and S.
+ */
+static gpg_err_code_t
+sign_eddsa (gcry_mpi_t input, ECC_secret_key *skey,
+            gcry_mpi_t r, gcry_mpi_t s, int hashalgo)
+{
+  (void)skey;
+  (void)r;
+  (void)s;
+
+  if (!mpi_is_opaque (input))
+    return GPG_ERR_INV_DATA;
+  if (hashalgo != GCRY_MD_SHA512)
+    return GPG_ERR_DIGEST_ALGO;
+
+  return GPG_ERR_NOT_IMPLEMENTED;
+}
+
+
+/* Verify an EdDSA signature.  See sign_eddsa for the reference.
+ * Check if R and S verifies INPUT.
+ */
+static gpg_err_code_t
+verify_eddsa (gcry_mpi_t input, ECC_public_key *pkey,
+              gcry_mpi_t r, gcry_mpi_t s, int hashalgo)
+{
+  (void)pkey;
+  (void)r;
+  (void)s;
+
+  if (!mpi_is_opaque (input))
+    return GPG_ERR_INV_DATA;
+  if (hashalgo != GCRY_MD_SHA512)
+    return GPG_ERR_DIGEST_ALGO;
+
+  return GPG_ERR_NOT_IMPLEMENTED;
+}
+
+
+

 /*********************************************
  **************  interface  ******************
  *********************************************/
@@ -796,7 +849,10 @@ ecc_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey,
 
   resarr[0] = mpi_alloc (mpi_get_nlimbs (sk.E.p));
   resarr[1] = mpi_alloc (mpi_get_nlimbs (sk.E.p));
-  err = sign (data, &sk, resarr[0], resarr[1], flags, hashalgo);
+  if ((flags & PUBKEY_FLAG_EDDSA))
+    err = sign_eddsa (data, &sk, resarr[0], resarr[1], hashalgo);
+  else
+    err = sign_ecdsa (data, &sk, resarr[0], resarr[1], flags, hashalgo);
   if (err)
     {
       mpi_free (resarr[0]);
@@ -810,7 +866,8 @@ ecc_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey,
 
 static gcry_err_code_t
 ecc_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey,
-            int (*cmp)(void *, gcry_mpi_t), void *opaquev)
+            int (*cmp)(void *, gcry_mpi_t), void *opaquev,
+            int flags, int hashalgo)
 {
   gpg_err_code_t err;
   ECC_public_key pk;
@@ -843,7 +900,11 @@ ecc_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey,
       return err;
     }
 
-  if (mpi_is_opaque (hash))
+  if ((flags & PUBKEY_FLAG_EDDSA))
+    {
+      err = verify_eddsa (hash, &pk, data[0], data[1], hashalgo);
+    }
+  else if (mpi_is_opaque (hash))
     {
       const void *abuf;
       unsigned int abits, qbits;
@@ -858,12 +919,12 @@ ecc_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey,
           if (abits > qbits)
             gcry_mpi_rshift (a, a, abits - qbits);
 
-          err = verify (a, &pk, data[0], data[1]);
+          err = verify_ecdsa (a, &pk, data[0], data[1]);
           gcry_mpi_release (a);
         }
     }
   else
-    err = verify (hash, &pk, data[0], data[1]);
+    err = verify_ecdsa (hash, &pk, data[0], data[1]);
 
   point_free (&pk.E.G);
   point_free (&pk.Q);
diff --git a/cipher/elgamal.c b/cipher/elgamal.c
index 7540e3f..d105cb4 100644
--- a/cipher/elgamal.c
+++ b/cipher/elgamal.c
@@ -789,7 +789,8 @@ elg_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey,
 
 static gcry_err_code_t
 elg_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey,
-            int (*cmp) (void *, gcry_mpi_t), void *opaquev)
+            int (*cmp) (void *, gcry_mpi_t), void *opaquev,
+            int flags, int hashalgo)
 {
   gcry_err_code_t err = GPG_ERR_NO_ERROR;
   ELG_public_key pk;
@@ -797,6 +798,8 @@ elg_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey,
   (void)algo;
   (void)cmp;
   (void)opaquev;
+  (void)flags;
+  (void)hashalgo;
 
   if (mpi_is_opaque (hash))
     return GPG_ERR_INV_DATA;
diff --git a/cipher/pubkey.c b/cipher/pubkey.c
index e6c1cf6..fb8de14 100644
--- a/cipher/pubkey.c
+++ b/cipher/pubkey.c
@@ -41,8 +41,7 @@ static gcry_err_code_t pubkey_sign (int algo, gcry_mpi_t *resarr,
                                     struct pk_encoding_ctx *ctx);
 static gcry_err_code_t pubkey_verify (int algo, gcry_mpi_t hash,
                                       gcry_mpi_t *data, gcry_mpi_t *pkey,
-				     int (*cmp) (void *, gcry_mpi_t),
-                                      void *opaque);
+                                      struct pk_encoding_ctx *ctx);
 
 
 /* A dummy extraspec so that we do not need to tests the extraspec
@@ -179,7 +178,8 @@ dummy_sign (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data,
 static gcry_err_code_t
 dummy_verify (int algorithm, gcry_mpi_t hash, gcry_mpi_t *data,
               gcry_mpi_t *pkey,
-	      int (*cmp) (void *, gcry_mpi_t), void *opaquev)
+	      int (*cmp) (void *, gcry_mpi_t), void *opaquev,
+              int flags, int hashalgo)
 {
   (void)algorithm;
   (void)hash;
@@ -187,6 +187,8 @@ dummy_verify (int algorithm, gcry_mpi_t hash, gcry_mpi_t *data,
   (void)pkey;
   (void)cmp;
   (void)opaquev;
+  (void)flags;
+  (void)hashalgo;
   fips_signal_error ("using dummy public key function");
   return GPG_ERR_NOT_IMPLEMENTED;
 }
@@ -757,8 +759,7 @@ pubkey_sign (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data,
  */
 static gcry_err_code_t
 pubkey_verify (int algorithm, gcry_mpi_t hash, gcry_mpi_t *data,
-               gcry_mpi_t *pkey,
-	       int (*cmp)(void *, gcry_mpi_t), void *opaquev)
+               gcry_mpi_t *pkey, struct pk_encoding_ctx *ctx)
 {
   gcry_pk_spec_t *pubkey;
   gcry_module_t module;
@@ -780,7 +781,9 @@ pubkey_verify (int algorithm, gcry_mpi_t hash, gcry_mpi_t *data,
   if (module)
     {
       pubkey = (gcry_pk_spec_t *) module->spec;
-      rc = pubkey->verify (algorithm, hash, data, pkey, cmp, opaquev);
+      rc = pubkey->verify (algorithm, hash, data, pkey,
+                           ctx->verify_cmp, ctx,
+                           ctx->flags, ctx->hash_algo);
       _gcry_module_release (module);
       goto ready;
     }
@@ -2484,7 +2487,7 @@ sexp_to_enc (gcry_sexp_t sexp, gcry_mpi_t **retarray, gcry_module_t *retalgo,
    (<mpi>)
    or
    (data
-    [(flags [raw, direct, pkcs1, oaep, pss, no-blinding, rfc6979])]
+    [(flags [raw, direct, pkcs1, oaep, pss, no-blinding, rfc6979, eddsa])]
     [(hash <algo> <value>)]
     [(value <text>)]
     [(hash-algo <algo>)]
@@ -2496,7 +2499,9 @@ sexp_to_enc (gcry_sexp_t sexp, gcry_mpi_t **retarray, gcry_module_t *retalgo,
    Either the VALUE or the HASH element must be present for use
    with signatures.  VALUE is used for encryption.
 
-   HASH-ALGO and LABEL are specific to OAEP.
+   HASH-ALGO is specific to OAEP and EDDSA.
+
+   LABEL is specific to OAEP.
 
    SALT-LENGTH is for PSS.
 
@@ -2533,8 +2538,13 @@ sexp_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
             s = gcry_sexp_nth_data (lflags, i, &n);
             if (!s)
               ; /* not a data element*/
-	    else if (n == 7 && ! memcmp (s, "rfc6979", 7))
+	    else if (n == 7 && !memcmp (s, "rfc6979", 7))
 	      parsed_flags |= PUBKEY_FLAG_RFC6979;
+	    else if (n == 5 && !memcmp (s, "eddsa", 5))
+              {
+                ctx->encoding = PUBKEY_ENC_RAW;
+                parsed_flags |= PUBKEY_FLAG_EDDSA;
+              }
             else if ( n == 3 && !memcmp (s, "raw", 3)
                       && ctx->encoding == PUBKEY_ENC_UNKNOWN)
               {
@@ -2570,6 +2580,54 @@ sexp_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
     rc = GPG_ERR_INV_OBJ; /* none or both given */
   else if (unknown_flag)
     rc = GPG_ERR_INV_FLAG;
+  else if (ctx->encoding == PUBKEY_ENC_RAW
+           && (parsed_flags & PUBKEY_FLAG_EDDSA))
+    {
+      /* Prepare for EdDSA.  */
+      gcry_sexp_t list;
+      void *value;
+      size_t valuelen;
+
+      if (lvalue)
+        {
+          rc = GPG_ERR_INV_OBJ;
+          goto leave;
+        }
+      /* Get HASH-ALGO. */
+      list = gcry_sexp_find_token (ldata, "hash-algo", 0);
+      if (list)
+        {
+          s = gcry_sexp_nth_data (list, 1, &n);
+          if (!s)
+            rc = GPG_ERR_NO_OBJ;
+          else
+            {
+              ctx->hash_algo = get_hash_algo (s, n);
+              if (!ctx->hash_algo)
+                rc = GPG_ERR_DIGEST_ALGO;
+            }
+          gcry_sexp_release (list);
+        }
+      else
+        rc = GPG_ERR_INV_OBJ;
+      if (rc)
+        goto leave;
+
+      /* Get VALUE.  */
+      value = gcry_sexp_nth_buffer (lvalue, 1, &valuelen);
+      if (!value)
+        rc = GPG_ERR_INV_OBJ;
+      else if ((valuelen * 8) < valuelen)
+        {
+          gcry_free (value);
+          rc = GPG_ERR_TOO_LARGE;
+        }
+      if (rc)
+        goto leave;
+
+      /* Note that mpi_set_opaque takes ownership of VALUE.  */
+      *ret_mpi = gcry_mpi_set_opaque (NULL, value, valuelen*8);
+    }
   else if (ctx->encoding == PUBKEY_ENC_RAW && lhash
            && (explicit_raw || (parsed_flags & PUBKEY_FLAG_RFC6979)))
     {
@@ -3406,8 +3464,7 @@ gcry_pk_verify (gcry_sexp_t s_sig, gcry_sexp_t s_hash, gcry_sexp_t s_pkey)
   if (rc)
     goto leave;
 
-  rc = pubkey_verify (module_key->mod_id, hash, sig, pkey,
-		      ctx.verify_cmp, &ctx);
+  rc = pubkey_verify (module_key->mod_id, hash, sig, pkey, &ctx);
 
  leave:
   if (pkey)
diff --git a/cipher/rsa.c b/cipher/rsa.c
index c9fcebf..bb22d05 100644
--- a/cipher/rsa.c
+++ b/cipher/rsa.c
@@ -1020,8 +1020,8 @@ rsa_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey,
 
 static gcry_err_code_t
 rsa_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey,
-		  int (*cmp) (void *opaque, gcry_mpi_t tmp),
-		  void *opaquev)
+            int (*cmp) (void *opaque, gcry_mpi_t tmp), void *opaquev,
+            int flags, int hashalgo)
 {
   RSA_public_key pk;
   gcry_mpi_t result;
@@ -1030,6 +1030,8 @@ rsa_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey,
   (void)algo;
   (void)cmp;
   (void)opaquev;
+  (void)flags;
+  (void)hashalgo;
 
   if (mpi_is_opaque (hash))
     return GPG_ERR_INV_DATA;
diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi
index 770a245..4c8cdb1 100644
--- a/doc/gcrypt.texi
+++ b/doc/gcrypt.texi
@@ -2364,6 +2364,7 @@ Here, the data to be signed is directly given as an @var{MPI}.
 
 @noindent
 For DSA the input data is expected in this format:
+
 @example
 (data
   (flags raw)
@@ -2411,11 +2412,28 @@ S-expression returned is:
 @end example
 
 Where @var{r-mpi} and @var{s-mpi} are the result of the DSA sign
-operation.  For Elgamal signing (which is slow, yields large numbers
-and probably is not as secure as the other algorithms), the same format is
-used with "elg" replacing "dsa"; for ECDSA signing, the same format is used
+operation.
+
+For Elgamal signing (which is slow, yields large numbers and probably
+is not as secure as the other algorithms), the same format is used
+with "elg" replacing "dsa"; for ECDSA signing, the same format is used
 with "ecdsa" replacing "dsa".
 
+For the EdDSA algorithm (cf. Ed25515) the required input parameters are:
+
+ at example
+(data
+  (flags eddsa)
+  (hash-algo sha-512)
+  (value @var{message}))
+ at end example
+
+Note that the @var{message} may be of any length; hashing is part of
+the algorithm.  Using a large data block for @var{message} is not
+suggested; in that case the used protocol should better require that a
+hash of the message is used as input to the EdDSA algorithm.
+
+
 @end deftypefun
 @c end gcry_pk_sign
 
diff --git a/src/cipher.h b/src/cipher.h
index bb92758..3674c2d 100644
--- a/src/cipher.h
+++ b/src/cipher.h
@@ -28,6 +28,7 @@
 
 #define PUBKEY_FLAG_NO_BLINDING    (1 << 0)
 #define PUBKEY_FLAG_RFC6979        (1 << 1)
+#define PUBKEY_FLAG_EDDSA          (1 << 2)
 
 enum pk_operation
   {
diff --git a/src/gcrypt-module.h b/src/gcrypt-module.h
index 5276e8f..75ca8ab 100644
--- a/src/gcrypt-module.h
+++ b/src/gcrypt-module.h
@@ -137,7 +137,9 @@ typedef gcry_err_code_t (*gcry_pk_verify_t) (int algo,
 					     gcry_mpi_t *data,
 					     gcry_mpi_t *pkey,
 					     int (*cmp) (void *, gcry_mpi_t),
-					     void *opaquev);
+					     void *opaquev,
+                                             int flags,
+                                             int hashalgo);
 
 /* Type for the pk_get_nbits function.  */
 typedef unsigned (*gcry_pk_get_nbits_t) (int algo, gcry_mpi_t *pkey);

commit c26be7a337d0bf98193bc58e043209e46d0769bb
Author: Werner Koch <wk at gnupg.org>
Date:   Tue Sep 3 12:01:15 2013 +0200

    Prepare support for non-Weierstrass EC equations.
    
    * src/mpi.h (gcry_mpi_ec_models): New.
    * src/ec-context.h (mpi_ec_ctx_s): Add MODEL.
    * cipher/ecc-common.h (elliptic_curve_t): Ditto.
    * cipher/ecc-curves.c (ecc_domain_parms_t): Ditto.
    (domain_parms): Mark als as Weierstrass.
    (_gcry_ecc_fill_in_curve): Check model.
    (_gcry_ecc_get_curve): Set model to Weierstrass.
    * cipher/ecc-misc.c (_gcry_ecc_model2str): New.
    * cipher/ecc.c (generate_key, ecc_generate_ext): Print model in the
    debug output.
    
    * mpi/ec.c (_gcry_mpi_ec_dup_point): Switch depending on model.
    Factor code out to ...
    (dup_point_weierstrass): new.
    (dup_point_montgomery, dup_point_twistededwards): New stub functions.
    (_gcry_mpi_ec_add_points): Switch depending on model.  Factor code out
    to ...
    (add_points_weierstrass): new.
    (add_points_montgomery, add_points_twistededwards): New stub
    functions.
    
    * tests/Makefile.am (TESTS): Reorder tests.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/cipher/ecc-common.h b/cipher/ecc-common.h
index 94da73e..614baae 100644
--- a/cipher/ecc-common.h
+++ b/cipher/ecc-common.h
@@ -23,9 +23,11 @@
 /* Definition of a curve.  */
 typedef struct
 {
+  enum gcry_mpi_ec_models model;/* The model descrinbing this curve.  */
   gcry_mpi_t p;         /* Prime specifying the field GF(p).  */
   gcry_mpi_t a;         /* First coefficient of the Weierstrass equation.  */
-  gcry_mpi_t b;         /* Second coefficient of the Weierstrass equation.  */
+  gcry_mpi_t b;         /* Second coefficient of the Weierstrass equation.
+                           or d as used by Twisted Edwards curves.  */
   mpi_point_struct G;   /* Base point (generator).  */
   gcry_mpi_t n;         /* Order of G.  */
   const char *name;     /* Name of the curve or NULL.  */
@@ -73,6 +75,7 @@ gcry_sexp_t     _gcry_ecc_get_param_sexp (const char *name);
 /*-- ecc-misc.c --*/
 void _gcry_ecc_curve_free (elliptic_curve_t *E);
 elliptic_curve_t _gcry_ecc_curve_copy (elliptic_curve_t E);
+const char *_gcry_ecc_model2str (enum gcry_mpi_ec_models model);
 gcry_mpi_t   _gcry_ecc_ec2os (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t p);
 gcry_error_t _gcry_ecc_os2ec (mpi_point_t result, gcry_mpi_t value);
 
diff --git a/cipher/ecc-curves.c b/cipher/ecc-curves.c
index e813b6b..e956dad 100644
--- a/cipher/ecc-curves.c
+++ b/cipher/ecc-curves.c
@@ -77,8 +77,12 @@ typedef struct
   const char *desc;           /* Description of the curve.  */
   unsigned int nbits;         /* Number of bits.  */
   unsigned int fips:1;        /* True if this is a FIPS140-2 approved curve. */
+
+  enum gcry_mpi_ec_models model;/* The model describing this curve.  */
+
   const char *p;              /* Order of the prime field.  */
-  const char *a, *b;          /* The coefficients. */
+  const char *a, *b;          /* The coefficients.  For Twisted Edwards
+                                 Curves b is used for d.  */
   const char *n;              /* The order of the base point.  */
   const char *g_x, *g_y;      /* Base point.  */
 } ecc_domain_parms_t;
@@ -89,6 +93,7 @@ static const ecc_domain_parms_t domain_parms[] =
   {
     {
       "NIST P-192", 192, 1,
+      MPI_EC_WEIERSTRASS,
       "0xfffffffffffffffffffffffffffffffeffffffffffffffff",
       "0xfffffffffffffffffffffffffffffffefffffffffffffffc",
       "0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1",
@@ -99,6 +104,7 @@ static const ecc_domain_parms_t domain_parms[] =
     },
     {
       "NIST P-224", 224, 1,
+      MPI_EC_WEIERSTRASS,
       "0xffffffffffffffffffffffffffffffff000000000000000000000001",
       "0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe",
       "0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4",
@@ -109,6 +115,7 @@ static const ecc_domain_parms_t domain_parms[] =
     },
     {
       "NIST P-256", 256, 1,
+      MPI_EC_WEIERSTRASS,
       "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
       "0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc",
       "0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
@@ -119,6 +126,7 @@ static const ecc_domain_parms_t domain_parms[] =
     },
     {
       "NIST P-384", 384, 1,
+      MPI_EC_WEIERSTRASS,
       "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
       "ffffffff0000000000000000ffffffff",
       "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
@@ -135,6 +143,7 @@ static const ecc_domain_parms_t domain_parms[] =
     },
     {
       "NIST P-521", 521, 1,
+      MPI_EC_WEIERSTRASS,
       "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
       "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
       "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
@@ -151,6 +160,7 @@ static const ecc_domain_parms_t domain_parms[] =
     },
 
     { "brainpoolP160r1", 160, 0,
+      MPI_EC_WEIERSTRASS,
       "0xe95e4a5f737059dc60dfc7ad95b3d8139515620f",
       "0x340e7be2a280eb74e2be61bada745d97e8f7c300",
       "0x1e589a8595423412134faa2dbdec95c8d8675e58",
@@ -160,6 +170,7 @@ static const ecc_domain_parms_t domain_parms[] =
     },
 
     { "brainpoolP192r1", 192, 0,
+      MPI_EC_WEIERSTRASS,
       "0xc302f41d932a36cda7a3463093d18db78fce476de1a86297",
       "0x6a91174076b1e0e19c39c031fe8685c1cae040e5c69a28ef",
       "0x469a28ef7c28cca3dc721d044f4496bcca7ef4146fbf25c9",
@@ -169,6 +180,7 @@ static const ecc_domain_parms_t domain_parms[] =
     },
 
     { "brainpoolP224r1", 224, 0,
+      MPI_EC_WEIERSTRASS,
       "0xd7c134aa264366862a18302575d1d787b09f075797da89f57ec8c0ff",
       "0x68a5e62ca9ce6c1c299803a6c1530b514e182ad8b0042a59cad29f43",
       "0x2580f63ccfe44138870713b1a92369e33e2135d266dbb372386c400b",
@@ -178,6 +190,7 @@ static const ecc_domain_parms_t domain_parms[] =
     },
 
     { "brainpoolP256r1", 256, 0,
+      MPI_EC_WEIERSTRASS,
       "0xa9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377",
       "0x7d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9",
       "0x26dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b6",
@@ -187,6 +200,7 @@ static const ecc_domain_parms_t domain_parms[] =
     },
 
     { "brainpoolP320r1", 320, 0,
+      MPI_EC_WEIERSTRASS,
       "0xd35e472036bc4fb7e13c785ed201e065f98fcfa6f6f40def4f92b9ec7893ec28"
       "fcd412b1f1b32e27",
       "0x3ee30b568fbab0f883ccebd46d3f3bb8a2a73513f5eb79da66190eb085ffa9f4"
@@ -202,6 +216,7 @@ static const ecc_domain_parms_t domain_parms[] =
     },
 
     { "brainpoolP384r1", 384, 0,
+      MPI_EC_WEIERSTRASS,
       "0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b412b1da197fb71123"
       "acd3a729901d1a71874700133107ec53",
       "0x7bc382c63d8c150c3c72080ace05afa0c2bea28e4fb22787139165efba91f90f"
@@ -217,6 +232,7 @@ static const ecc_domain_parms_t domain_parms[] =
     },
 
     { "brainpoolP512r1", 512, 0,
+      MPI_EC_WEIERSTRASS,
       "0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330871"
       "7d4d9b009bc66842aecda12ae6a380e62881ff2f2d82c68528aa6056583a48f3",
       "0x7830a3318b603b89e2327145ac234cc594cbdd8d3df91610a83441caea9863bc"
@@ -231,7 +247,7 @@ static const ecc_domain_parms_t domain_parms[] =
       "b2dcde494a5f485e5bca4bd88a2763aed1ca2b2fa8f0540678cd1e0f3ad80892"
     },
 
-    { NULL, 0, 0, NULL, NULL, NULL, NULL }
+    { NULL, 0, 0, 0, NULL, NULL, NULL, NULL }
   };
 
 
@@ -302,10 +318,23 @@ _gcry_ecc_fill_in_curve (unsigned int nbits, const char *name,
      possible to bypass this check by specifying the curve parameters
      directly.  */
   if (fips_mode () && !domain_parms[idx].fips )
+
     return GPG_ERR_NOT_SUPPORTED;
 
+  switch (domain_parms[idx].model)
+    {
+    case MPI_EC_WEIERSTRASS:
+      break;
+    case MPI_EC_TWISTEDEDWARDS:
+    case MPI_EC_MONTGOMERY:
+      return GPG_ERR_NOT_SUPPORTED;
+    default:
+      return GPG_ERR_BUG;
+    }
+
   if (r_nbits)
     *r_nbits = domain_parms[idx].nbits;
+
   curve->p = scanval (domain_parms[idx].p);
   curve->a = scanval (domain_parms[idx].a);
   curve->b = scanval (domain_parms[idx].b);
@@ -319,7 +348,8 @@ _gcry_ecc_fill_in_curve (unsigned int nbits, const char *name,
 }
 
 
-/* Return the name matching the parameters in PKEY.  */
+/* Return the name matching the parameters in PKEY.  This works only
+   with curves described by the Weierstrass equation. */
 const char *
 _gcry_ecc_get_curve (gcry_mpi_t *pkey, int iterator, unsigned int *r_nbits)
 {
@@ -347,6 +377,7 @@ _gcry_ecc_get_curve (gcry_mpi_t *pkey, int iterator, unsigned int *r_nbits)
   if (!pkey[0] || !pkey[1] || !pkey[2] || !pkey[3] || !pkey[4])
     return NULL;
 
+  E.model = MPI_EC_WEIERSTRASS;
   E.p = pkey[0];
   E.a = pkey[1];
   E.b = pkey[2];
@@ -505,7 +536,7 @@ point_from_keyparam (gcry_mpi_point_t *r_a,
 
 /* This function creates a new context for elliptic curve operations.
    Either KEYPARAM or CURVENAME must be given.  If both are given and
-   KEYPARAM has no curve parameter CURVENAME is used to add missing
+   KEYPARAM has no curve parameter, CURVENAME is used to add missing
    parameters.  On success 0 is returned and the new context stored at
    R_CTX.  On error NULL is stored at R_CTX and an error code is
    returned.  The context needs to be released using
diff --git a/cipher/ecc-misc.c b/cipher/ecc-misc.c
index 5e06bef..5c86121 100644
--- a/cipher/ecc-misc.c
+++ b/cipher/ecc-misc.c
@@ -64,6 +64,25 @@ _gcry_ecc_curve_copy (elliptic_curve_t E)
 }
 
 
+/*
+ * Return a description of the curve model.
+ */
+const char *
+_gcry_ecc_model2str (enum gcry_mpi_ec_models model)
+{
+  const char *str = "?";
+  switch (model)
+    {
+    case MPI_EC_WEIERSTRASS:    str = "Weierstrass"; break;
+    case MPI_EC_MONTGOMERY:     str = "Montgomery";  break;
+    case MPI_EC_TWISTEDEDWARDS: str = "Twisted Edwards"; break;
+    }
+  return str;
+}
+
+
+
+
 gcry_mpi_t
 _gcry_ecc_ec2os (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t p)
 {
diff --git a/cipher/ecc.c b/cipher/ecc.c
index 9174f9b..8a7ca0b 100644
--- a/cipher/ecc.c
+++ b/cipher/ecc.c
@@ -108,8 +108,8 @@ _gcry_register_pk_ecc_progress (void (*cb) (void *, const char *,
 
 

 
-/****************
- * Solve the right side of the equation that defines a curve.
+/*
+ * Solve the right side of the Weierstrass equation.
  */
 static gcry_mpi_t
 gen_y_2 (gcry_mpi_t x, elliptic_curve_t *base)
@@ -158,6 +158,7 @@ generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name,
 
   if (DBG_CIPHER)
     {
+      log_debug ("ecgen curve model: %s\n", _gcry_ecc_model2str (E.model));
       log_mpidump ("ecgen curve  p", E.p);
       log_mpidump ("ecgen curve  a", E.a);
       log_mpidump ("ecgen curve  b", E.b);
@@ -166,7 +167,7 @@ generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name,
       log_mpidump ("ecgen curve Gy", E.G.y);
       log_mpidump ("ecgen curve Gz", E.G.z);
       if (E.name)
-        log_debug   ("ecgen curve used: %s\n", E.name);
+        log_debug ("ecgen curve used: %s\n", E.name);
     }
 
   random_level = transient_key ? GCRY_STRONG_RANDOM : GCRY_VERY_STRONG_RANDOM;
@@ -696,6 +697,7 @@ ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue,
 
   if (DBG_CIPHER)
     {
+      log_debug ("ecgen result model: %s\n", _gcry_ecc_model2str (sk.E.model));
       log_mpidump ("ecgen result p", skey[0]);
       log_mpidump ("ecgen result a", skey[1]);
       log_mpidump ("ecgen result b", skey[2]);
diff --git a/mpi/ec.c b/mpi/ec.c
index 8fb47a3..54fa028 100644
--- a/mpi/ec.c
+++ b/mpi/ec.c
@@ -684,9 +684,9 @@ _gcry_mpi_ec_get_affine (gcry_mpi_t x, gcry_mpi_t y, mpi_point_t point,
 
 
 

-/*  RESULT = 2 * POINT  */
-void
-_gcry_mpi_ec_dup_point (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx)
+/*  RESULT = 2 * POINT  (Weierstrass version). */
+static void
+dup_point_weierstrass (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx)
 {
 #define x3 (result->x)
 #define y3 (result->y)
@@ -767,12 +767,48 @@ _gcry_mpi_ec_dup_point (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx)
 }
 
 
+/*  RESULT = 2 * POINT  (Montgomery version). */
+static void
+dup_point_montgomery (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx)
+{
+  log_fatal ("%s: %s not yet supported\n",
+             "_gcry_mpi_ec_dup_point", "Montgomery");
+}
+
 
-/* RESULT = P1 + P2 */
+/*  RESULT = 2 * POINT  (Twisted Edwards version). */
+static void
+dup_point_twistededwards (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx)
+{
+  log_fatal ("%s: %s not yet supported\n",
+             "_gcry_mpi_ec_dup_point", "Twisted Edwards");
+}
+
+
+/*  RESULT = 2 * POINT  */
 void
-_gcry_mpi_ec_add_points (mpi_point_t result,
-                         mpi_point_t p1, mpi_point_t p2,
-                         mpi_ec_t ctx)
+_gcry_mpi_ec_dup_point (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx)
+{
+  switch (ctx->model)
+    {
+    case MPI_EC_WEIERSTRASS:
+      dup_point_weierstrass (result, point, ctx);
+      break;
+    case MPI_EC_MONTGOMERY:
+      dup_point_montgomery (result, point, ctx);
+      break;
+    case MPI_EC_TWISTEDEDWARDS:
+      dup_point_twistededwards (result, point, ctx);
+      break;
+    }
+}
+
+
+/* RESULT = P1 + P2  (Weierstrass version).*/
+static void
+add_points_weierstrass (mpi_point_t result,
+                        mpi_point_t p1, mpi_point_t p2,
+                        mpi_ec_t ctx)
 {
 #define x1 (p1->x    )
 #define y1 (p1->y    )
@@ -910,6 +946,48 @@ _gcry_mpi_ec_add_points (mpi_point_t result,
 }
 
 
+/* RESULT = P1 + P2  (Montgomery version).*/
+static void
+add_points_montgomery (mpi_point_t result,
+                       mpi_point_t p1, mpi_point_t p2,
+                       mpi_ec_t ctx)
+{
+  log_fatal ("%s: %s not yet supported\n",
+             "_gcry_mpi_ec_add_points", "Montgomery");
+}
+
+
+/* RESULT = P1 + P2  (Twisted Edwards version).*/
+static void
+add_points_twistededwards (mpi_point_t result,
+                           mpi_point_t p1, mpi_point_t p2,
+                           mpi_ec_t ctx)
+{
+  log_fatal ("%s: %s not yet supported\n",
+             "_gcry_mpi_ec_add_points", "Twisted Edwards");
+}
+
+
+/* RESULT = P1 + P2 */
+void
+_gcry_mpi_ec_add_points (mpi_point_t result,
+                         mpi_point_t p1, mpi_point_t p2,
+                         mpi_ec_t ctx)
+{
+  switch (ctx->model)
+    {
+    case MPI_EC_WEIERSTRASS:
+      add_points_weierstrass (result, p1, p2, ctx);
+      break;
+    case MPI_EC_MONTGOMERY:
+      add_points_montgomery (result, p1, p2, ctx);
+      break;
+    case MPI_EC_TWISTEDEDWARDS:
+      add_points_twistededwards (result, p1, p2, ctx);
+      break;
+    }
+}
+
 
 /* Scalar point multiplication - the main function for ECC.  If takes
    an integer SCALAR and a POINT as well as the usual context CTX.
diff --git a/src/ec-context.h b/src/ec-context.h
index 7002d47..7df3576 100644
--- a/src/ec-context.h
+++ b/src/ec-context.h
@@ -23,8 +23,10 @@
 /* This context is used with all our EC functions. */
 struct mpi_ec_ctx_s
 {
+  enum gcry_mpi_ec_models model; /* The model describing this curve.  */
+
   /* Domain parameters.  Note that they may not all be set and if set
-     the MPIs may be flaged as constant.*/
+     the MPIs may be flaged as constant. */
   gcry_mpi_t p;         /* Prime specifying the field GF(p).  */
   gcry_mpi_t a;         /* First coefficient of the Weierstrass equation.  */
   gcry_mpi_t b;         /* Second coefficient of the Weierstrass equation.  */
diff --git a/src/mpi.h b/src/mpi.h
index fd265bf..0114dba 100644
--- a/src/mpi.h
+++ b/src/mpi.h
@@ -272,6 +272,18 @@ void _gcry_mpi_get_point (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t z,
 void _gcry_mpi_snatch_point (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t z,
                              mpi_point_t point);
 
+/* Models describing an elliptic curve.  */
+enum gcry_mpi_ec_models
+  {
+
+    MPI_EC_WEIERSTRASS = 0,
+    MPI_EC_MONTGOMERY,
+    MPI_EC_TWISTEDEDWARDS
+    /* The equation for Twisted Edwards curves is
+          ax^2 + y^2 = 1 + bx^2y^2
+       Note that we use 'b' instead of the commonly used 'd'.  */
+  };
+
 /* Context used with elliptic curve functions.  */
 struct mpi_ec_ctx_s;
 typedef struct mpi_ec_ctx_s *mpi_ec_t;
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 35bcd60..4cbc34b 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -18,9 +18,10 @@
 
 ## Process this file with automake to produce Makefile.in
 
-TESTS = version t-convert t-mpi-bit t-mpi-point prime basic \
-        mpitests tsexp keygen pubkey hmac keygrip fips186-dsa aeswrap \
-	curves t-kdf pkcs1v2 random dsa-rfc6979
+TESTS = version mpitests tsexp t-convert \
+	t-mpi-bit t-mpi-point curves \
+	prime basic keygen pubkey hmac t-kdf keygrip \
+	fips186-dsa aeswrap pkcs1v2 random dsa-rfc6979
 
 
 # The last test to run.

commit 8698530b2f9ef95542f1dd550961de7af86cc256
Author: Werner Koch <wk at gnupg.org>
Date:   Fri Aug 30 17:56:35 2013 +0200

    mpi: Suppress newer gcc warnings.
    
    * src/g10lib.h (GCC_ATTR_UNUSED): Define for gcc >= 3.5.
    * mpi/mpih-div.c (_gcry_mpih_mod_1, _gcry_mpih_divmod_1): Mark dummy
    as unused.
    * mpi/mpi-internal.h (UDIV_QRNND_PREINV): Mark _ql as unused.
    --
    
    Due to the use of macros and longlong.h, we use variables which are
    only used by some architectures.  At least gcc 4.7.2 prints new
    warnings abot set but not used variables.  This patch silences them.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/mpi/mpi-internal.h b/mpi/mpi-internal.h
index e75b7c6..178378f 100644
--- a/mpi/mpi-internal.h
+++ b/mpi/mpi-internal.h
@@ -145,7 +145,8 @@ typedef int mpi_size_t;        /* (must be a signed type) */
  */
 #define UDIV_QRNND_PREINV(q, r, nh, nl, d, di) \
     do {							    \
-	mpi_limb_t _q, _ql, _r; 				    \
+        mpi_limb_t _ql GCC_ATTR_UNUSED;                               \
+	mpi_limb_t _q, _r;                                          \
 	mpi_limb_t _xh, _xl;					    \
 	umul_ppmm (_q, _ql, (nh), (di));			    \
 	_q += (nh);	/* DI is 2**BITS_PER_MPI_LIMB too small */  \
diff --git a/mpi/mpih-div.c b/mpi/mpih-div.c
index b33dcbf..0bddd22 100644
--- a/mpi/mpih-div.c
+++ b/mpi/mpih-div.c
@@ -48,7 +48,7 @@ _gcry_mpih_mod_1(mpi_ptr_t dividend_ptr, mpi_size_t dividend_size,
 {
     mpi_size_t i;
     mpi_limb_t n1, n0, r;
-    int dummy;
+    int dummy GCC_ATTR_UNUSED;
 
     /* Botch: Should this be handled at all?  Rely on callers?	*/
     if( !dividend_size )
@@ -396,7 +396,7 @@ _gcry_mpih_divmod_1( mpi_ptr_t quot_ptr,
 {
     mpi_size_t i;
     mpi_limb_t n1, n0, r;
-    int dummy;
+    int dummy GCC_ATTR_UNUSED;
 
     if( !dividend_size )
 	return 0;
diff --git a/src/g10lib.h b/src/g10lib.h
index 31131a5..2d84dd3 100644
--- a/src/g10lib.h
+++ b/src/g10lib.h
@@ -67,6 +67,13 @@
 #endif
 
 
+#if __GNUC__ > 2 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 5 )
+#define GCC_ATTR_UNUSED  __attribute__ ((unused))
+#else
+#define GCC_ATTR_UNUSED
+#endif
+
+
 /* Gettext macros.  */
 
 #define _(a)  _gcry_gettext(a)

commit b28b1f732e1b4f9c62a9de87c22c6bb0d3f8fdb8
Author: Werner Koch <wk at gnupg.org>
Date:   Fri Aug 30 17:52:17 2013 +0200

    Do not check with cpp for typedefed constants.
    
    * src/gcrypt-int.h: Include error code replacements depeding on the
    version of libgpg-error.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/src/gcrypt-int.h b/src/gcrypt-int.h
index 33969fe..295328b 100644
--- a/src/gcrypt-int.h
+++ b/src/gcrypt-int.h
@@ -28,7 +28,7 @@
 
 /* These error codes are used but not defined in the required
    libgpg-error 1.11.  Define them here. */
-#ifndef GPG_ERR_NO_CRYPT_CTX
+#if GPG_ERROR_VERSION_NUMBER < 0x010c00  /* 1.12 */
 # define GPG_ERR_NO_CRYPT_CTX	    191
 # define GPG_ERR_WRONG_CRYPT_CTX    192
 # define GPG_ERR_BAD_CRYPT_CTX	    193

-----------------------------------------------------------------------

Summary of changes:
 cipher/dsa.c        |    5 +-
 cipher/ecc-common.h |    5 +-
 cipher/ecc-curves.c |   39 ++++-
 cipher/ecc-misc.c   |   19 ++
 cipher/ecc.c        |  105 ++++++++--
 cipher/elgamal.c    |    5 +-
 cipher/pubkey.c     |   79 +++++++-
 cipher/rsa.c        |    6 +-
 doc/gcrypt.texi     |   24 ++-
 mpi/ec.c            |   92 ++++++++-
 mpi/mpi-internal.h  |    3 +-
 mpi/mpih-div.c      |    4 +-
 src/Makefile.am     |    6 +-
 src/cipher.h        |    1 +
 src/ec-context.h    |    4 +-
 src/g10lib.h        |    7 +
 src/gcrypt-int.h    |    2 +-
 src/gcrypt-module.h |    4 +-
 src/mpi.h           |   12 ++
 src/mpicalc.c       |  534 +++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/Makefile.am   |    7 +-
 21 files changed, 902 insertions(+), 61 deletions(-)
 create mode 100644 src/mpicalc.c


hooks/post-receive
-- 
The GNU crypto library
http://git.gnupg.org




More information about the Gnupg-commits mailing list