LCOV - code coverage report
Current view: top level - tests - t-mpi-point.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 390 561 69.5 %
Date: 2015-11-05 17:08:00 Functions: 16 22 72.7 %

          Line data    Source code
       1             : /* t-mpi-point.c  - Tests for mpi point functions
       2             :  * Copyright (C) 2013 g10 Code GmbH
       3             :  *
       4             :  * This file is part of Libgcrypt.
       5             :  *
       6             :  * Libgcrypt is free software; you can redistribute it and/or modify
       7             :  * it under the terms of the GNU Lesser General Public License as
       8             :  * published by the Free Software Foundation; either version 2.1 of
       9             :  * the License, or (at your option) any later version.
      10             :  *
      11             :  * Libgcrypt is distributed in the hope that it will be useful,
      12             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :  * GNU Lesser General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU Lesser General Public
      17             :  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
      18             :  */
      19             : 
      20             : #ifdef HAVE_CONFIG_H
      21             : # include <config.h>
      22             : #endif
      23             : #include <stdio.h>
      24             : #include <stdlib.h>
      25             : #include <string.h>
      26             : #include <assert.h>
      27             : #include <stdarg.h>
      28             : 
      29             : #include "../src/gcrypt-int.h"
      30             : 
      31             : #define PGM "t-mpi-point"
      32             : 
      33             : static const char *wherestr;
      34             : static int verbose;
      35             : static int debug;
      36             : static int error_count;
      37             : 
      38             : 
      39             : #define my_isascii(c) (!((c) & 0x80))
      40             : #define digitp(p)   (*(p) >= '0' && *(p) <= '9')
      41             : #define hexdigitp(a) (digitp (a)                     \
      42             :                       || (*(a) >= 'A' && *(a) <= 'F')  \
      43             :                       || (*(a) >= 'a' && *(a) <= 'f'))
      44             : #define xtoi_1(p)   (*(p) <= '9'? (*(p)- '0'): \
      45             :                      *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
      46             : #define xtoi_2(p)   ((xtoi_1(p) * 16) + xtoi_1((p)+1))
      47             : #define xmalloc(a)    gcry_xmalloc ((a))
      48             : #define xcalloc(a,b)  gcry_xcalloc ((a),(b))
      49             : #define xfree(a)      gcry_free ((a))
      50             : #define pass() do { ; } while (0)
      51             : 
      52             : 
      53             : static struct
      54             : {
      55             :   const char *desc;           /* Description of the curve.  */
      56             :   const char *p;              /* Order of the prime field.  */
      57             :   const char *a, *b;          /* The coefficients. */
      58             :   const char *n;              /* The order of the base point.  */
      59             :   const char *g_x, *g_y;      /* Base point.  */
      60             :   const char *h;              /* Cofactor.  */
      61             : } test_curve[] =
      62             :   {
      63             :     {
      64             :       "NIST P-192",
      65             :       "0xfffffffffffffffffffffffffffffffeffffffffffffffff",
      66             :       "0xfffffffffffffffffffffffffffffffefffffffffffffffc",
      67             :       "0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1",
      68             :       "0xffffffffffffffffffffffff99def836146bc9b1b4d22831",
      69             : 
      70             :       "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012",
      71             :       "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811",
      72             :       "0x01"
      73             :     },
      74             :     {
      75             :       "NIST P-224",
      76             :       "0xffffffffffffffffffffffffffffffff000000000000000000000001",
      77             :       "0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe",
      78             :       "0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4",
      79             :       "0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d" ,
      80             : 
      81             :       "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
      82             :       "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34",
      83             :       "0x01"
      84             :     },
      85             :     {
      86             :       "NIST P-256",
      87             :       "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
      88             :       "0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc",
      89             :       "0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
      90             :       "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
      91             : 
      92             :       "0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
      93             :       "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5",
      94             :       "0x01"
      95             :     },
      96             :     {
      97             :       "NIST P-384",
      98             :       "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
      99             :       "ffffffff0000000000000000ffffffff",
     100             :       "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
     101             :       "ffffffff0000000000000000fffffffc",
     102             :       "0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875a"
     103             :       "c656398d8a2ed19d2a85c8edd3ec2aef",
     104             :       "0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf"
     105             :       "581a0db248b0a77aecec196accc52973",
     106             : 
     107             :       "0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a38"
     108             :       "5502f25dbf55296c3a545e3872760ab7",
     109             :       "0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c0"
     110             :       "0a60b1ce1d7e819d7a431d7c90ea0e5f",
     111             :       "0x01"
     112             :     },
     113             :     {
     114             :       "NIST P-521",
     115             :       "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
     116             :       "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
     117             :       "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
     118             :       "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc",
     119             :       "0x051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef10"
     120             :       "9e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00",
     121             :       "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
     122             :       "ffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409",
     123             : 
     124             :       "0xc6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3d"
     125             :       "baa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66",
     126             :       "0x11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e6"
     127             :       "62c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650",
     128             :       "0x01"
     129             :     },
     130             :     {
     131             :       "Ed25519",
     132             :       "0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED",
     133             :       "-0x01",
     134             :       "-0x2DFC9311D490018C7338BF8688861767FF8FF5B2BEBE27548A14B235ECA6874A",
     135             :       "0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED",
     136             :       "0x216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A",
     137             :       "0x6666666666666666666666666666666666666666666666666666666666666658",
     138             :       "0x08"
     139             :     },
     140             :     { NULL, NULL, NULL, NULL, NULL, NULL }
     141             :   };
     142             : 
     143             : /* A sample public key for NIST P-256.  */
     144             : static const char sample_p256_q[] =
     145             :   "04"
     146             :   "42B927242237639A36CE9221B340DB1A9AB76DF2FE3E171277F6A4023DED146E"
     147             :   "E86525E38CCECFF3FB8D152CC6334F70D23A525175C1BCBDDE6E023B2228770E";
     148             : static const char sample_p256_q_x[] =
     149             :   "42B927242237639A36CE9221B340DB1A9AB76DF2FE3E171277F6A4023DED146E";
     150             : static const char sample_p256_q_y[] =
     151             :   "00E86525E38CCECFF3FB8D152CC6334F70D23A525175C1BCBDDE6E023B2228770E";
     152             : 
     153             : 
     154             : /* A sample public key for Ed25519.  */
     155             : static const char sample_ed25519_q[] =
     156             :   "04"
     157             :   "55d0e09a2b9d34292297e08d60d0f620c513d47253187c24b12786bd777645ce"
     158             :   "1a5107f7681a02af2523a6daf372e10e3a0764c9d3fe4bd5b70ab18201985ad7";
     159             : static const char sample_ed25519_q_x[] =
     160             :   "55d0e09a2b9d34292297e08d60d0f620c513d47253187c24b12786bd777645ce";
     161             : static const char sample_ed25519_q_y[] =
     162             :   "1a5107f7681a02af2523a6daf372e10e3a0764c9d3fe4bd5b70ab18201985ad7";
     163             : static const char sample_ed25519_q_eddsa[] =
     164             :   "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a";
     165             : static const char sample_ed25519_d[] =
     166             :   "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60";
     167             : 
     168             : 
     169             : static void
     170           9 : show (const char *format, ...)
     171             : {
     172             :   va_list arg_ptr;
     173             : 
     174           9 :   if (!verbose)
     175          18 :     return;
     176           0 :   fprintf (stderr, "%s: ", PGM);
     177           0 :   va_start (arg_ptr, format);
     178           0 :   vfprintf (stderr, format, arg_ptr);
     179           0 :   va_end (arg_ptr);
     180             : }
     181             : 
     182             : static void
     183           0 : fail (const char *format, ...)
     184             : {
     185             :   va_list arg_ptr;
     186             : 
     187           0 :   fflush (stdout);
     188           0 :   fprintf (stderr, "%s: ", PGM);
     189           0 :   if (wherestr)
     190           0 :     fprintf (stderr, "%s: ", wherestr);
     191           0 :   va_start (arg_ptr, format);
     192           0 :   vfprintf (stderr, format, arg_ptr);
     193           0 :   va_end (arg_ptr);
     194           0 :   error_count++;
     195           0 : }
     196             : 
     197             : static void
     198           0 : die (const char *format, ...)
     199             : {
     200             :   va_list arg_ptr;
     201             : 
     202           0 :   fflush (stdout);
     203           0 :   fprintf (stderr, "%s: ", PGM);
     204           0 :   if (wherestr)
     205           0 :     fprintf (stderr, "%s: ", wherestr);
     206           0 :   va_start (arg_ptr, format);
     207           0 :   vfprintf (stderr, format, arg_ptr);
     208           0 :   va_end (arg_ptr);
     209           0 :   exit (1);
     210             : }
     211             : 
     212             : 
     213             : static void
     214           0 : print_mpi_2 (const char *text, const char *text2, gcry_mpi_t a)
     215             : {
     216             :   gcry_error_t err;
     217             :   char *buf;
     218           0 :   void *bufaddr = &buf;
     219             : 
     220           0 :   err = gcry_mpi_aprint (GCRYMPI_FMT_HEX, bufaddr, NULL, a);
     221           0 :   if (err)
     222           0 :     fprintf (stderr, "%s%s: [error printing number: %s]\n",
     223             :              text, text2? text2:"", gpg_strerror (err));
     224             :   else
     225             :     {
     226           0 :       fprintf (stderr, "%s%s: %s\n", text, text2? text2:"", buf);
     227           0 :       gcry_free (buf);
     228             :     }
     229           0 : }
     230             : 
     231             : 
     232             : static void
     233           0 : print_mpi (const char *text, gcry_mpi_t a)
     234             : {
     235           0 :   print_mpi_2 (text, NULL, a);
     236           0 : }
     237             : 
     238             : 
     239             : static void
     240           0 : print_point (const char *text, gcry_mpi_point_t a)
     241             : {
     242             :   gcry_mpi_t x, y, z;
     243             : 
     244           0 :   x = gcry_mpi_new (0);
     245           0 :   y = gcry_mpi_new (0);
     246           0 :   z = gcry_mpi_new (0);
     247           0 :   gcry_mpi_point_get (x, y, z, a);
     248           0 :   print_mpi_2 (text, ".x", x);
     249           0 :   print_mpi_2 (text, ".y", y);
     250           0 :   print_mpi_2 (text, ".z", z);
     251           0 :   gcry_mpi_release (x);
     252           0 :   gcry_mpi_release (y);
     253           0 :   gcry_mpi_release (z);
     254           0 : }
     255             : 
     256             : 
     257             : static void
     258           0 : print_sexp (const char *prefix, gcry_sexp_t a)
     259             : {
     260             :   char *buf;
     261             :   size_t size;
     262             : 
     263           0 :   if (prefix)
     264           0 :     fputs (prefix, stderr);
     265           0 :   size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0);
     266           0 :   buf = gcry_xmalloc (size);
     267             : 
     268           0 :   gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size);
     269           0 :   fprintf (stderr, "%.*s", (int)size, buf);
     270           0 :   gcry_free (buf);
     271           0 : }
     272             : 
     273             : 
     274             : static gcry_mpi_t
     275         100 : hex2mpi (const char *string)
     276             : {
     277             :   gpg_error_t err;
     278             :   gcry_mpi_t val;
     279             : 
     280         100 :   err = gcry_mpi_scan (&val, GCRYMPI_FMT_HEX, string, 0, NULL);
     281         100 :   if (err)
     282           0 :     die ("hex2mpi '%s' failed: %s\n", string, gpg_strerror (err));
     283         100 :   return val;
     284             : }
     285             : 
     286             : 
     287             : /* Convert STRING consisting of hex characters into its binary
     288             :    representation and return it as an allocated buffer. The valid
     289             :    length of the buffer is returned at R_LENGTH.  The string is
     290             :    delimited by end of string.  The function returns NULL on
     291             :    error.  */
     292             : static void *
     293           2 : hex2buffer (const char *string, size_t *r_length)
     294             : {
     295             :   const char *s;
     296             :   unsigned char *buffer;
     297             :   size_t length;
     298             : 
     299           2 :   buffer = xmalloc (strlen(string)/2+1);
     300           2 :   length = 0;
     301          99 :   for (s=string; *s; s +=2 )
     302             :     {
     303          97 :       if (!hexdigitp (s) || !hexdigitp (s+1))
     304           0 :         return NULL;           /* Invalid hex digits. */
     305          97 :       ((unsigned char*)buffer)[length++] = xtoi_2 (s);
     306             :     }
     307           2 :   *r_length = length;
     308           2 :   return buffer;
     309             : }
     310             : 
     311             : 
     312             : static gcry_mpi_t
     313           2 : hex2mpiopa (const char *string)
     314             : {
     315             :   char *buffer;
     316             :   size_t buflen;
     317             :   gcry_mpi_t val;
     318             : 
     319           2 :   buffer = hex2buffer (string, &buflen);
     320           2 :   if (!buffer)
     321           0 :     die ("hex2mpiopa '%s' failed: parser error\n", string);
     322           2 :   val = gcry_mpi_set_opaque (NULL, buffer, buflen*8);
     323           2 :   if (!buffer)
     324           0 :     die ("hex2mpiopa '%s' failed: set_opaque error%s\n", string);
     325           2 :   return val;
     326             : }
     327             : 
     328             : 
     329             : /* Compare A to B, where B is given as a hex string.  */
     330             : static int
     331          86 : cmp_mpihex (gcry_mpi_t a, const char *b)
     332             : {
     333             :   gcry_mpi_t bval;
     334             :   int res;
     335             : 
     336          86 :   if (gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE))
     337           1 :     bval = hex2mpiopa (b);
     338             :   else
     339          85 :     bval = hex2mpi (b);
     340          86 :   res = gcry_mpi_cmp (a, bval);
     341          86 :   gcry_mpi_release (bval);
     342          86 :   return res;
     343             : }
     344             : 
     345             : 
     346             : /* Wrapper to emulate the libgcrypt internal EC context allocation
     347             :    function.  */
     348             : static gpg_error_t
     349           4 : ec_p_new (gcry_ctx_t *r_ctx, gcry_mpi_t p, gcry_mpi_t a)
     350             : {
     351             :   gpg_error_t err;
     352             :   gcry_sexp_t sexp;
     353             : 
     354           4 :   if (p && a)
     355           2 :     err = gcry_sexp_build (&sexp, NULL, "(ecdsa (p %m)(a %m))", p, a);
     356           2 :   else if (p)
     357           0 :     err = gcry_sexp_build (&sexp, NULL, "(ecdsa (p %m))", p);
     358           2 :   else if (a)
     359           1 :     err = gcry_sexp_build (&sexp, NULL, "(ecdsa (a %m))", a);
     360             :   else
     361           1 :     err = gcry_sexp_build (&sexp, NULL, "(ecdsa)");
     362           4 :   if (err)
     363           0 :     return err;
     364           4 :   err = gcry_mpi_ec_new (r_ctx, sexp, NULL);
     365           4 :   gcry_sexp_release (sexp);
     366           4 :   return err;
     367             : }
     368             : 
     369             : 
     370             : 
     371             : static void
     372           1 : set_get_point (void)
     373             : {
     374             :   gcry_mpi_point_t point;
     375             :   gcry_mpi_t x, y, z;
     376             : 
     377           1 :   wherestr = "set_get_point";
     378           1 :   show ("checking point setting functions\n");
     379             : 
     380           1 :   point = gcry_mpi_point_new (0);
     381           1 :   x = gcry_mpi_set_ui (NULL, 17);
     382           1 :   y = gcry_mpi_set_ui (NULL, 42);
     383           1 :   z = gcry_mpi_set_ui (NULL, 11371);
     384           1 :   gcry_mpi_point_get (x, y, z, point);
     385           1 :   if (gcry_mpi_cmp_ui (x, 0)
     386           1 :       || gcry_mpi_cmp_ui (y, 0) || gcry_mpi_cmp_ui (z, 0))
     387           0 :     fail ("new point not initialized to (0,0,0)\n");
     388           1 :   gcry_mpi_point_snatch_get (x, y, z, point);
     389           1 :   point = NULL;
     390           1 :   if (gcry_mpi_cmp_ui (x, 0)
     391           1 :       || gcry_mpi_cmp_ui (y, 0) || gcry_mpi_cmp_ui (z, 0))
     392           0 :     fail ("snatch_get failed\n");
     393           1 :   gcry_mpi_release (x);
     394           1 :   gcry_mpi_release (y);
     395           1 :   gcry_mpi_release (z);
     396             : 
     397           1 :   point = gcry_mpi_point_new (0);
     398           1 :   x = gcry_mpi_set_ui (NULL, 17);
     399           1 :   y = gcry_mpi_set_ui (NULL, 42);
     400           1 :   z = gcry_mpi_set_ui (NULL, 11371);
     401           1 :   gcry_mpi_point_set (point, x, y, z);
     402           1 :   gcry_mpi_set_ui (x, 23);
     403           1 :   gcry_mpi_set_ui (y, 24);
     404           1 :   gcry_mpi_set_ui (z, 25);
     405           1 :   gcry_mpi_point_get (x, y, z, point);
     406           1 :   if (gcry_mpi_cmp_ui (x, 17)
     407           1 :       || gcry_mpi_cmp_ui (y, 42) || gcry_mpi_cmp_ui (z, 11371))
     408           0 :     fail ("point_set/point_get failed\n");
     409           1 :   gcry_mpi_point_snatch_set (point, x, y, z);
     410           1 :   x = gcry_mpi_new (0);
     411           1 :   y = gcry_mpi_new (0);
     412           1 :   z = gcry_mpi_new (0);
     413           1 :   gcry_mpi_point_get (x, y, z, point);
     414           1 :   if (gcry_mpi_cmp_ui (x, 17)
     415           1 :       || gcry_mpi_cmp_ui (y, 42) || gcry_mpi_cmp_ui (z, 11371))
     416           0 :     fail ("point_snatch_set/point_get failed\n");
     417             : 
     418           1 :   gcry_mpi_point_release (point);
     419           1 :   gcry_mpi_release (x);
     420           1 :   gcry_mpi_release (y);
     421           1 :   gcry_mpi_release (z);
     422           1 : }
     423             : 
     424             : 
     425             : static void
     426           1 : context_alloc (void)
     427             : {
     428             :   gpg_error_t err;
     429             :   gcry_ctx_t ctx;
     430             :   gcry_mpi_t p, a;
     431             : 
     432           1 :   wherestr = "context_alloc";
     433           1 :   show ("checking context functions\n");
     434             : 
     435           1 :   p = gcry_mpi_set_ui (NULL, 1);
     436           1 :   a = gcry_mpi_set_ui (NULL, 1);
     437           1 :   err = ec_p_new (&ctx, p, a);
     438           1 :   if (err)
     439           0 :     die ("ec_p_new returned an error: %s\n", gpg_strerror (err));
     440           1 :   gcry_mpi_release (p);
     441           1 :   gcry_mpi_release (a);
     442           1 :   gcry_ctx_release (ctx);
     443             : 
     444           1 :   p = NULL;
     445           1 :   a = gcry_mpi_set_ui (NULL, 0);
     446             : 
     447           1 :   err = ec_p_new (&ctx, p, a);
     448           1 :   if (!err || gpg_err_code (err) != GPG_ERR_EINVAL)
     449           0 :     fail ("ec_p_new: bad parameter detection failed (1)\n");
     450             : 
     451           1 :   gcry_mpi_release (a);
     452           1 :   a = NULL;
     453           1 :   err = ec_p_new (&ctx, p, a);
     454           1 :   if (!err || gpg_err_code (err) != GPG_ERR_EINVAL)
     455           0 :     fail ("ec_p_new: bad parameter detection failed (2)\n");
     456             : 
     457           1 : }
     458             : 
     459             : 
     460             : static int
     461          48 : get_and_cmp_mpi (const char *name, const char *mpistring, const char *desc,
     462             :                  gcry_ctx_t ctx)
     463             : {
     464             :   gcry_mpi_t mpi;
     465             : 
     466          48 :   mpi = gcry_mpi_ec_get_mpi (name, ctx, 1);
     467          48 :   if (!mpi)
     468             :     {
     469           0 :       fail ("error getting parameter '%s' of curve '%s'\n", name, desc);
     470           0 :       return 1;
     471             :     }
     472          48 :   if (debug)
     473           0 :     print_mpi (name, mpi);
     474          48 :   if (cmp_mpihex (mpi, mpistring))
     475             :     {
     476           0 :       fail ("parameter '%s' of curve '%s' does not match\n", name, desc);
     477           0 :       gcry_mpi_release (mpi);
     478           0 :       return 1;
     479             :     }
     480          48 :   gcry_mpi_release (mpi);
     481          48 :   return 0;
     482             : }
     483             : 
     484             : 
     485             : static int
     486           8 : get_and_cmp_point (const char *name,
     487             :                    const char *mpi_x_string, const char *mpi_y_string,
     488             :                    const char *desc, gcry_ctx_t ctx)
     489             : {
     490             :   gcry_mpi_point_t point;
     491             :   gcry_mpi_t x, y, z;
     492           8 :   int result = 0;
     493             : 
     494           8 :   point = gcry_mpi_ec_get_point (name, ctx, 1);
     495           8 :   if (!point)
     496             :     {
     497           0 :       fail ("error getting point parameter '%s' of curve '%s'\n", name, desc);
     498           0 :       return 1;
     499             :     }
     500           8 :   if (debug)
     501           0 :     print_point (name, point);
     502             : 
     503           8 :   x = gcry_mpi_new (0);
     504           8 :   y = gcry_mpi_new (0);
     505           8 :   z = gcry_mpi_new (0);
     506           8 :   gcry_mpi_point_snatch_get (x, y, z, point);
     507           8 :   if (cmp_mpihex (x, mpi_x_string))
     508             :     {
     509           0 :       fail ("x coordinate of '%s' of curve '%s' does not match\n", name, desc);
     510           0 :       result = 1;
     511             :     }
     512           8 :   if (cmp_mpihex (y, mpi_y_string))
     513             :     {
     514           0 :       fail ("y coordinate of '%s' of curve '%s' does not match\n", name, desc);
     515           0 :       result = 1;
     516             :     }
     517           8 :   if (cmp_mpihex (z, "01"))
     518             :     {
     519           0 :       fail ("z coordinate of '%s' of curve '%s' is not 1\n", name, desc);
     520           0 :       result = 1;
     521             :     }
     522           8 :   gcry_mpi_release (x);
     523           8 :   gcry_mpi_release (y);
     524           8 :   gcry_mpi_release (z);
     525           8 :   return result;
     526             : }
     527             : 
     528             : 
     529             : static void
     530           1 : context_param (void)
     531             : {
     532             :   gpg_error_t err;
     533             :   int idx;
     534           1 :   gcry_ctx_t ctx = NULL;
     535             :   gcry_mpi_t q, d;
     536             :   gcry_sexp_t keyparam;
     537             : 
     538           1 :   wherestr = "context_param";
     539             : 
     540           1 :   show ("checking standard curves\n");
     541           7 :   for (idx=0; test_curve[idx].desc; idx++)
     542             :     {
     543           6 :       gcry_ctx_release (ctx);
     544           6 :       err = gcry_mpi_ec_new (&ctx, NULL, test_curve[idx].desc);
     545           6 :       if (err)
     546             :         {
     547           0 :           fail ("can't create context for curve '%s': %s\n",
     548             :                 test_curve[idx].desc, gpg_strerror (err));
     549           0 :           continue;
     550             :         }
     551           6 :       if (get_and_cmp_mpi ("p", test_curve[idx].p, test_curve[idx].desc, ctx))
     552           0 :         continue;
     553           6 :       if (get_and_cmp_mpi ("a", test_curve[idx].a, test_curve[idx].desc, ctx))
     554           0 :         continue;
     555           6 :       if (get_and_cmp_mpi ("b", test_curve[idx].b, test_curve[idx].desc, ctx))
     556           0 :         continue;
     557           6 :       if (get_and_cmp_mpi ("g.x",test_curve[idx].g_x, test_curve[idx].desc,ctx))
     558           0 :         continue;
     559           6 :       if (get_and_cmp_mpi ("g.y",test_curve[idx].g_y, test_curve[idx].desc,ctx))
     560           0 :         continue;
     561           6 :       if (get_and_cmp_mpi ("n", test_curve[idx].n, test_curve[idx].desc, ctx))
     562           0 :         continue;
     563           6 :       if (get_and_cmp_point ("g", test_curve[idx].g_x, test_curve[idx].g_y,
     564             :                              test_curve[idx].desc, ctx))
     565           0 :         continue;
     566           6 :       if (get_and_cmp_mpi ("h", test_curve[idx].h, test_curve[idx].desc, ctx))
     567           0 :         continue;
     568             : 
     569             :     }
     570             : 
     571           1 :   show ("checking sample public key (nistp256)\n");
     572           1 :   q = hex2mpi (sample_p256_q);
     573           1 :   err = gcry_sexp_build (&keyparam, NULL,
     574             :                         "(public-key(ecc(curve %s)(q %m)))",
     575             :                         "NIST P-256", q);
     576           1 :   if (err)
     577           0 :     die ("gcry_sexp_build failed: %s\n", gpg_strerror (err));
     578           1 :   gcry_mpi_release (q);
     579             : 
     580             :   /* We can't call gcry_pk_testkey because it is only implemented for
     581             :      private keys.  */
     582             :   /* err = gcry_pk_testkey (keyparam); */
     583             :   /* if (err) */
     584             :   /*   fail ("gcry_pk_testkey failed for sample public key: %s\n", */
     585             :   /*         gpg_strerror (err)); */
     586             : 
     587           1 :   gcry_ctx_release (ctx);
     588           1 :   err = gcry_mpi_ec_new (&ctx, keyparam, NULL);
     589           1 :   if (err)
     590           0 :     fail ("gcry_mpi_ec_new failed for sample public key (nistp256): %s\n",
     591             :           gpg_strerror (err));
     592             :   else
     593             :     {
     594             :       gcry_sexp_t sexp;
     595             : 
     596           1 :       get_and_cmp_mpi ("q", sample_p256_q, "nistp256", ctx);
     597           1 :       get_and_cmp_point ("q", sample_p256_q_x, sample_p256_q_y, "nistp256",
     598             :                          ctx);
     599             : 
     600             :       /* Delete Q.  */
     601           1 :       err = gcry_mpi_ec_set_mpi ("q", NULL, ctx);
     602           1 :       if (err)
     603           0 :         fail ("clearing Q for nistp256 failed: %s\n", gpg_strerror (err));
     604           1 :       if (gcry_mpi_ec_get_mpi ("q", ctx, 0))
     605           0 :         fail ("clearing Q for nistp256 did not work\n");
     606             : 
     607             :       /* Set Q again.  */
     608           1 :       q = hex2mpi (sample_p256_q);
     609           1 :       err = gcry_mpi_ec_set_mpi ("q", q, ctx);
     610           1 :       if (err)
     611           0 :         fail ("setting Q for nistp256 failed: %s\n", gpg_strerror (err));
     612           1 :       get_and_cmp_mpi ("q", sample_p256_q, "nistp256(2)", ctx);
     613           1 :       gcry_mpi_release (q);
     614             : 
     615             :       /* Get as s-expression.  */
     616           1 :       err = gcry_pubkey_get_sexp (&sexp, 0, ctx);
     617           1 :       if (err)
     618           0 :         fail ("gcry_pubkey_get_sexp(0) failed: %s\n", gpg_strerror (err));
     619           1 :       else if (debug)
     620           0 :         print_sexp ("Result of gcry_pubkey_get_sexp (0):\n", sexp);
     621           1 :       gcry_sexp_release (sexp);
     622             : 
     623           1 :       err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_PUBKEY, ctx);
     624           1 :       if (err)
     625           0 :         fail ("gcry_pubkey_get_sexp(GET_PUBKEY) failed: %s\n",
     626             :               gpg_strerror (err));
     627           1 :       else if (debug)
     628           0 :         print_sexp ("Result of gcry_pubkey_get_sexp (GET_PUBKEY):\n", sexp);
     629           1 :       gcry_sexp_release (sexp);
     630             : 
     631           1 :       err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_SECKEY, ctx);
     632           1 :       if (gpg_err_code (err) != GPG_ERR_NO_SECKEY)
     633           0 :         fail ("gcry_pubkey_get_sexp(GET_SECKEY) returned wrong error: %s\n",
     634             :               gpg_strerror (err));
     635           1 :       gcry_sexp_release (sexp);
     636             :     }
     637             : 
     638           1 :   show ("checking sample public key (Ed25519)\n");
     639           1 :   q = hex2mpi (sample_ed25519_q);
     640           1 :   gcry_sexp_release (keyparam);
     641           1 :   err = gcry_sexp_build (&keyparam, NULL,
     642             :                         "(public-key(ecc(curve %s)(flags eddsa)(q %m)))",
     643             :                         "Ed25519", q);
     644           1 :   if (err)
     645           0 :     die ("gcry_sexp_build failed: %s\n", gpg_strerror (err));
     646           1 :   gcry_mpi_release (q);
     647             : 
     648             :   /* We can't call gcry_pk_testkey because it is only implemented for
     649             :      private keys.  */
     650             :   /* err = gcry_pk_testkey (keyparam); */
     651             :   /* if (err) */
     652             :   /*   fail ("gcry_pk_testkey failed for sample public key: %s\n", */
     653             :   /*         gpg_strerror (err)); */
     654             : 
     655           1 :   gcry_ctx_release (ctx);
     656           1 :   err = gcry_mpi_ec_new (&ctx, keyparam, NULL);
     657           1 :   if (err)
     658           0 :     fail ("gcry_mpi_ec_new failed for sample public key: %s\n",
     659             :           gpg_strerror (err));
     660             :   else
     661             :     {
     662             :       gcry_sexp_t sexp;
     663             : 
     664           1 :       get_and_cmp_mpi ("q", sample_ed25519_q, "Ed25519", ctx);
     665           1 :       get_and_cmp_point ("q", sample_ed25519_q_x, sample_ed25519_q_y,
     666             :                          "Ed25519", ctx);
     667           1 :       get_and_cmp_mpi ("q@eddsa", sample_ed25519_q_eddsa, "Ed25519", ctx);
     668             : 
     669             :       /* Set d to see whether Q is correctly re-computed.  */
     670           1 :       d = hex2mpi (sample_ed25519_d);
     671           1 :       err = gcry_mpi_ec_set_mpi ("d", d, ctx);
     672           1 :       if (err)
     673           0 :         fail ("setting d for Ed25519 failed: %s\n", gpg_strerror (err));
     674           1 :       gcry_mpi_release (d);
     675           1 :       get_and_cmp_mpi ("q", sample_ed25519_q, "Ed25519(recompute Q)", ctx);
     676             : 
     677             :       /* Delete Q by setting d and then clearing d.  The clearing is
     678             :          required so that we can check whether Q has been cleared and
     679             :          because further tests only expect a public key.  */
     680           1 :       d = hex2mpi (sample_ed25519_d);
     681           1 :       err = gcry_mpi_ec_set_mpi ("d", d, ctx);
     682           1 :       if (err)
     683           0 :         fail ("setting d for Ed25519 failed: %s\n", gpg_strerror (err));
     684           1 :       gcry_mpi_release (d);
     685           1 :       err = gcry_mpi_ec_set_mpi ("d", NULL, ctx);
     686           1 :       if (err)
     687           0 :         fail ("setting d for Ed25519 failed(2): %s\n", gpg_strerror (err));
     688           1 :       if (gcry_mpi_ec_get_mpi ("q", ctx, 0))
     689           0 :         fail ("setting d for Ed25519 did not reset Q\n");
     690             : 
     691             :       /* Set Q again.  We need to use an opaque MPI here because
     692             :          sample_ed25519_q is in uncompressed format which can only be
     693             :          auto-detected if passed opaque.  */
     694           1 :       q = hex2mpiopa (sample_ed25519_q);
     695           1 :       err = gcry_mpi_ec_set_mpi ("q", q, ctx);
     696           1 :       if (err)
     697           0 :         fail ("setting Q for Ed25519 failed: %s\n", gpg_strerror (err));
     698           1 :       gcry_mpi_release (q);
     699           1 :       get_and_cmp_mpi ("q", sample_ed25519_q, "Ed25519(2)", ctx);
     700             : 
     701             :       /* Get as s-expression.  */
     702           1 :       err = gcry_pubkey_get_sexp (&sexp, 0, ctx);
     703           1 :       if (err)
     704           0 :         fail ("gcry_pubkey_get_sexp(0) failed: %s\n", gpg_strerror (err));
     705           1 :       else if (debug)
     706           0 :         print_sexp ("Result of gcry_pubkey_get_sexp (0):\n", sexp);
     707           1 :       gcry_sexp_release (sexp);
     708             : 
     709           1 :       err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_PUBKEY, ctx);
     710           1 :       if (err)
     711           0 :         fail ("gcry_pubkey_get_sexp(GET_PUBKEY) failed: %s\n",
     712             :               gpg_strerror (err));
     713           1 :       else if (debug)
     714           0 :         print_sexp ("Result of gcry_pubkey_get_sexp (GET_PUBKEY):\n", sexp);
     715           1 :       gcry_sexp_release (sexp);
     716             : 
     717           1 :       err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_SECKEY, ctx);
     718           1 :       if (gpg_err_code (err) != GPG_ERR_NO_SECKEY)
     719           0 :         fail ("gcry_pubkey_get_sexp(GET_SECKEY) returned wrong error: %s\n",
     720             :               gpg_strerror (err));
     721           1 :       gcry_sexp_release (sexp);
     722             : 
     723             :     }
     724             : 
     725           1 :   gcry_ctx_release (ctx);
     726           1 :   gcry_sexp_release (keyparam);
     727           1 : }
     728             : 
     729             : 
     730             : 
     731             : 
     732             : /* Create a new point from (X,Y,Z) given as hex strings.  */
     733             : gcry_mpi_point_t
     734           1 : make_point (const char *x, const char *y, const char *z)
     735             : {
     736             :   gcry_mpi_point_t point;
     737             : 
     738           1 :   point = gcry_mpi_point_new (0);
     739           1 :   gcry_mpi_point_snatch_set (point, hex2mpi (x), hex2mpi (y), hex2mpi (z));
     740             : 
     741           1 :   return point;
     742             : }
     743             : 
     744             : 
     745             : /* This tests checks that the low-level EC API yields the same result
     746             :    as using the high level API.  The values have been taken from a
     747             :    test run using the high level API.  */
     748             : static void
     749           1 : basic_ec_math (void)
     750             : {
     751             :   gpg_error_t err;
     752             :   gcry_ctx_t ctx;
     753             :   gcry_mpi_t P, A;
     754             :   gcry_mpi_point_t G, Q;
     755             :   gcry_mpi_t d;
     756             :   gcry_mpi_t x, y, z;
     757             : 
     758           1 :   wherestr = "basic_ec_math";
     759           1 :   show ("checking basic math functions for EC\n");
     760             : 
     761           1 :   P = hex2mpi ("0xfffffffffffffffffffffffffffffffeffffffffffffffff");
     762           1 :   A = hex2mpi ("0xfffffffffffffffffffffffffffffffefffffffffffffffc");
     763           1 :   G = make_point ("188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012",
     764             :                   "7192B95FFC8DA78631011ED6B24CDD573F977A11E794811",
     765             :                   "1");
     766           1 :   d = hex2mpi ("D4EF27E32F8AD8E2A1C6DDEBB1D235A69E3CEF9BCE90273D");
     767           1 :   Q = gcry_mpi_point_new (0);
     768             : 
     769           1 :   err = ec_p_new (&ctx, P, A);
     770           1 :   if (err)
     771           0 :     die ("ec_p_new failed: %s\n", gpg_strerror (err));
     772             : 
     773           1 :   x = gcry_mpi_new (0);
     774           1 :   y = gcry_mpi_new (0);
     775           1 :   z = gcry_mpi_new (0);
     776             : 
     777             :   {
     778             :     /* A quick check that multiply by zero works.  */
     779             :     gcry_mpi_t tmp;
     780             : 
     781           1 :     tmp = gcry_mpi_new (0);
     782           1 :     gcry_mpi_ec_mul (Q, tmp, G, ctx);
     783           1 :     gcry_mpi_release (tmp);
     784           1 :     gcry_mpi_point_get (x, y, z, Q);
     785           1 :     if (gcry_mpi_cmp_ui (x, 0) || gcry_mpi_cmp_ui (y, 0)
     786           1 :         || gcry_mpi_cmp_ui (z, 0))
     787           0 :       fail ("multiply a point by zero failed\n");
     788             :   }
     789             : 
     790           1 :   gcry_mpi_ec_mul (Q, d, G, ctx);
     791           1 :   gcry_mpi_point_get (x, y, z, Q);
     792           1 :   if (cmp_mpihex (x, "222D9EC717C89D047E0898C9185B033CD11C0A981EE6DC66")
     793           1 :       || cmp_mpihex (y, "605DE0A82D70D3E0F84A127D0739ED33D657DF0D054BFDE8")
     794           1 :       || cmp_mpihex (z, "00B06B519071BC536999AC8F2D3934B3C1FC9EACCD0A31F88F"))
     795           0 :     fail ("computed public key does not match\n");
     796           1 :   if (debug)
     797             :     {
     798           0 :       print_mpi ("Q.x", x);
     799           0 :       print_mpi ("Q.y", y);
     800           0 :       print_mpi ("Q.z", z);
     801             :     }
     802             : 
     803           1 :   if (gcry_mpi_ec_get_affine (x, y, Q, ctx))
     804           0 :     fail ("failed to get affine coordinates\n");
     805           1 :   if (cmp_mpihex (x, "008532093BA023F4D55C0424FA3AF9367E05F309DC34CDC3FE")
     806           1 :       || cmp_mpihex (y, "00C13CA9E617C6C8487BFF6A726E3C4F277913D97117939966"))
     807           0 :     fail ("computed affine coordinates of public key do not match\n");
     808           1 :   if (debug)
     809             :     {
     810           0 :       print_mpi ("q.x", x);
     811           0 :       print_mpi ("q.y", y);
     812             :     }
     813             : 
     814           1 :   gcry_mpi_release (z);
     815           1 :   gcry_mpi_release (y);
     816           1 :   gcry_mpi_release (x);
     817           1 :   gcry_mpi_point_release (Q);
     818           1 :   gcry_mpi_release (d);
     819           1 :   gcry_mpi_point_release (G);
     820           1 :   gcry_mpi_release (A);
     821           1 :   gcry_mpi_release (P);
     822           1 :   gcry_ctx_release (ctx);
     823           1 : }
     824             : 
     825             : 
     826             : /* This is the same as basic_ec_math but uses more advanced
     827             :    features.  */
     828             : static void
     829           1 : basic_ec_math_simplified (void)
     830             : {
     831             :   gpg_error_t err;
     832             :   gcry_ctx_t ctx;
     833             :   gcry_mpi_point_t G, Q;
     834             :   gcry_mpi_t d;
     835             :   gcry_mpi_t x, y, z;
     836             :   gcry_sexp_t sexp;
     837             : 
     838           1 :   wherestr = "basic_ec_math_simplified";
     839           1 :   show ("checking basic math functions for EC (variant)\n");
     840             : 
     841           1 :   d = hex2mpi ("D4EF27E32F8AD8E2A1C6DDEBB1D235A69E3CEF9BCE90273D");
     842           1 :   Q = gcry_mpi_point_new (0);
     843             : 
     844           1 :   err = gcry_mpi_ec_new (&ctx, NULL, "NIST P-192");
     845           1 :   if (err)
     846           0 :     die ("gcry_mpi_ec_new failed: %s\n", gpg_strerror (err));
     847           1 :   G = gcry_mpi_ec_get_point ("g", ctx, 1);
     848           1 :   if (!G)
     849           0 :     die ("gcry_mpi_ec_get_point(G) failed\n");
     850           1 :   gcry_mpi_ec_mul (Q, d, G, ctx);
     851             : 
     852           1 :   x = gcry_mpi_new (0);
     853           1 :   y = gcry_mpi_new (0);
     854           1 :   z = gcry_mpi_new (0);
     855           1 :   gcry_mpi_point_get (x, y, z, Q);
     856           1 :   if (cmp_mpihex (x, "222D9EC717C89D047E0898C9185B033CD11C0A981EE6DC66")
     857           1 :       || cmp_mpihex (y, "605DE0A82D70D3E0F84A127D0739ED33D657DF0D054BFDE8")
     858           1 :       || cmp_mpihex (z, "00B06B519071BC536999AC8F2D3934B3C1FC9EACCD0A31F88F"))
     859           0 :     fail ("computed public key does not match\n");
     860           1 :   if (debug)
     861             :     {
     862           0 :       print_mpi ("Q.x", x);
     863           0 :       print_mpi ("Q.y", y);
     864           0 :       print_mpi ("Q.z", z);
     865             :     }
     866             : 
     867           1 :   if (gcry_mpi_ec_get_affine (x, y, Q, ctx))
     868           0 :     fail ("failed to get affine coordinates\n");
     869           1 :   if (cmp_mpihex (x, "008532093BA023F4D55C0424FA3AF9367E05F309DC34CDC3FE")
     870           1 :       || cmp_mpihex (y, "00C13CA9E617C6C8487BFF6A726E3C4F277913D97117939966"))
     871           0 :     fail ("computed affine coordinates of public key do not match\n");
     872           1 :   if (debug)
     873             :     {
     874           0 :       print_mpi ("q.x", x);
     875           0 :       print_mpi ("q.y", y);
     876             :     }
     877             : 
     878           1 :   gcry_mpi_release (z);
     879           1 :   gcry_mpi_release (y);
     880           1 :   gcry_mpi_release (x);
     881             : 
     882             :   /* Let us also check whether we can update the context.  */
     883           1 :   err = gcry_mpi_ec_set_point ("g", G, ctx);
     884           1 :   if (err)
     885           0 :     die ("gcry_mpi_ec_set_point(G) failed\n");
     886           1 :   err = gcry_mpi_ec_set_mpi ("d", d, ctx);
     887           1 :   if (err)
     888           0 :     die ("gcry_mpi_ec_set_mpi(d) failed\n");
     889             : 
     890             :   /* FIXME: Below we need to check that the returned S-expression is
     891             :      as requested.  For now we use manual inspection using --debug.  */
     892             : 
     893             :   /* Does get_sexp return the private key?  */
     894           1 :   err = gcry_pubkey_get_sexp (&sexp, 0, ctx);
     895           1 :   if (err)
     896           0 :     fail ("gcry_pubkey_get_sexp(0) failed: %s\n", gpg_strerror (err));
     897           1 :   else if (debug)
     898           0 :     print_sexp ("Result of gcry_pubkey_get_sexp (0):\n", sexp);
     899           1 :   gcry_sexp_release (sexp);
     900             : 
     901             :   /* Does get_sexp return the public key if requested?  */
     902           1 :   err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_PUBKEY, ctx);
     903           1 :   if (err)
     904           0 :     fail ("gcry_pubkey_get_sexp(GET_PUBKEY) failed: %s\n", gpg_strerror (err));
     905           1 :   else if (debug)
     906           0 :     print_sexp ("Result of gcry_pubkey_get_sexp (GET_PUBKEY):\n", sexp);
     907           1 :   gcry_sexp_release (sexp);
     908             : 
     909             :   /* Does get_sexp return the public key after d has been deleted?  */
     910           1 :   err = gcry_mpi_ec_set_mpi ("d", NULL, ctx);
     911           1 :   if (err)
     912           0 :     die ("gcry_mpi_ec_set_mpi(d=NULL) failed\n");
     913           1 :   err = gcry_pubkey_get_sexp (&sexp, 0, ctx);
     914           1 :   if (err)
     915           0 :     fail ("gcry_pubkey_get_sexp(0 w/o d) failed: %s\n", gpg_strerror (err));
     916           1 :   else if (debug)
     917           0 :     print_sexp ("Result of gcry_pubkey_get_sexp (0 w/o d):\n", sexp);
     918           1 :   gcry_sexp_release (sexp);
     919             : 
     920             :   /* Does get_sexp return an error after d has been deleted?  */
     921           1 :   err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_SECKEY, ctx);
     922           1 :   if (gpg_err_code (err) != GPG_ERR_NO_SECKEY)
     923           0 :     fail ("gcry_pubkey_get_sexp(GET_SECKEY) returned wrong error: %s\n",
     924             :           gpg_strerror (err));
     925           1 :   gcry_sexp_release (sexp);
     926             : 
     927             :   /* Does get_sexp return an error after d and Q have been deleted?  */
     928           1 :   err = gcry_mpi_ec_set_point ("q", NULL, ctx);
     929           1 :   if (err)
     930           0 :     die ("gcry_mpi_ec_set_point(q=NULL) failed\n");
     931           1 :   err = gcry_pubkey_get_sexp (&sexp, 0, ctx);
     932           1 :   if (gpg_err_code (err) != GPG_ERR_BAD_CRYPT_CTX)
     933           0 :     fail ("gcry_pubkey_get_sexp(0 w/o Q,d) returned wrong error: %s\n",
     934             :           gpg_strerror (err));
     935           1 :   gcry_sexp_release (sexp);
     936             : 
     937             : 
     938           1 :   gcry_mpi_point_release (Q);
     939           1 :   gcry_mpi_release (d);
     940           1 :   gcry_mpi_point_release (G);
     941           1 :   gcry_ctx_release (ctx);
     942           1 : }
     943             : 
     944             : 
     945             : /* Check the math used with Twisted Edwards curves.  */
     946             : static void
     947           1 : twistededwards_math (void)
     948             : {
     949             :   gpg_error_t err;
     950             :   gcry_ctx_t ctx;
     951             :   gcry_mpi_point_t G, Q;
     952             :   gcry_mpi_t k;
     953             :   gcry_mpi_t w, a, x, y, z, p, n, b, I;
     954             : 
     955           1 :   wherestr = "twistededwards_math";
     956           1 :   show ("checking basic Twisted Edwards math\n");
     957             : 
     958           1 :   err = gcry_mpi_ec_new (&ctx, NULL, "Ed25519");
     959           1 :   if (err)
     960           0 :     die ("gcry_mpi_ec_new failed: %s\n", gpg_strerror (err));
     961             : 
     962           1 :   k = hex2mpi
     963             :     ("2D3501E723239632802454EE5DDC406EFB0BDF18486A5BDE9C0390A9C2984004"
     964             :      "F47252B628C953625B8DEB5DBCB8DA97AA43A1892D11FA83596F42E0D89CB1B6");
     965           1 :   G = gcry_mpi_ec_get_point ("g", ctx, 1);
     966           1 :   if (!G)
     967           0 :     die ("gcry_mpi_ec_get_point(G) failed\n");
     968           1 :   Q = gcry_mpi_point_new (0);
     969             : 
     970             : 
     971           1 :   w = gcry_mpi_new (0);
     972           1 :   a = gcry_mpi_new (0);
     973           1 :   x = gcry_mpi_new (0);
     974           1 :   y = gcry_mpi_new (0);
     975           1 :   z = gcry_mpi_new (0);
     976           1 :   I = gcry_mpi_new (0);
     977           1 :   p = gcry_mpi_ec_get_mpi ("p", ctx, 1);
     978           1 :   n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
     979           1 :   b = gcry_mpi_ec_get_mpi ("b", ctx, 1);
     980             : 
     981             :   /* Check: 2^{p-1} mod p == 1 */
     982           1 :   gcry_mpi_sub_ui (a, p, 1);
     983           1 :   gcry_mpi_powm (w, GCRYMPI_CONST_TWO, a, p);
     984           1 :   if (gcry_mpi_cmp_ui (w, 1))
     985           0 :     fail ("failed assertion: 2^{p-1} mod p == 1\n");
     986             : 
     987             :   /* Check: p % 4 == 1 */
     988           1 :   gcry_mpi_mod (w, p, GCRYMPI_CONST_FOUR);
     989           1 :   if (gcry_mpi_cmp_ui (w, 1))
     990           0 :     fail ("failed assertion: p % 4 == 1\n");
     991             : 
     992             :   /* Check: 2^{n-1} mod n == 1 */
     993           1 :   gcry_mpi_sub_ui (a, n, 1);
     994           1 :   gcry_mpi_powm (w, GCRYMPI_CONST_TWO, a, n);
     995           1 :   if (gcry_mpi_cmp_ui (w, 1))
     996           0 :     fail ("failed assertion: 2^{n-1} mod n == 1\n");
     997             : 
     998             :   /* Check: b^{(p-1)/2} mod p == p-1 */
     999           1 :   gcry_mpi_sub_ui (a, p, 1);
    1000           1 :   gcry_mpi_div (x, NULL, a, GCRYMPI_CONST_TWO, -1);
    1001           1 :   gcry_mpi_powm (w, b, x, p);
    1002           1 :   gcry_mpi_abs (w);
    1003           1 :   if (gcry_mpi_cmp (w, a))
    1004           0 :     fail ("failed assertion: b^{(p-1)/2} mod p == p-1\n");
    1005             : 
    1006             :   /* I := 2^{(p-1)/4} mod p */
    1007           1 :   gcry_mpi_sub_ui (a, p, 1);
    1008           1 :   gcry_mpi_div (x, NULL, a, GCRYMPI_CONST_FOUR, -1);
    1009           1 :   gcry_mpi_powm (I, GCRYMPI_CONST_TWO, x, p);
    1010             : 
    1011             :   /* Check: I^2 mod p == p-1 */
    1012           1 :   gcry_mpi_powm (w, I, GCRYMPI_CONST_TWO, p);
    1013           1 :   if (gcry_mpi_cmp (w, a))
    1014           0 :     fail ("failed assertion: I^2 mod p == p-1\n");
    1015             : 
    1016             :   /* Check: G is on the curve */
    1017           1 :   if (!gcry_mpi_ec_curve_point (G, ctx))
    1018           0 :     fail ("failed assertion: G is on the curve\n");
    1019             : 
    1020             :   /* Check: nG == (0,1) */
    1021           1 :   gcry_mpi_ec_mul (Q, n, G, ctx);
    1022           1 :   if (gcry_mpi_ec_get_affine (x, y, Q, ctx))
    1023           0 :     fail ("failed to get affine coordinates\n");
    1024           1 :   if (gcry_mpi_cmp_ui (x, 0) || gcry_mpi_cmp_ui (y, 1))
    1025           0 :     fail ("failed assertion: nG == (0,1)\n");
    1026             : 
    1027             :   /* Now two arbitrary point operations taken from the ed25519.py
    1028             :      sample data.  */
    1029           1 :   gcry_mpi_release (a);
    1030           1 :   a = hex2mpi
    1031             :     ("4f71d012df3c371af3ea4dc38385ca5bb7272f90cb1b008b3ed601c76de1d496"
    1032             :      "e30cbf625f0a756a678d8f256d5325595cccc83466f36db18f0178eb9925edd3");
    1033           1 :   gcry_mpi_ec_mul (Q, a, G, ctx);
    1034           1 :   if (gcry_mpi_ec_get_affine (x, y, Q, ctx))
    1035           0 :     fail ("failed to get affine coordinates\n");
    1036           1 :   if (cmp_mpihex (x, ("157f7361c577aad36f67ed33e38dc7be"
    1037             :                       "00014fecc2165ca5cee9eee19fe4d2c1"))
    1038           1 :       || cmp_mpihex (y, ("5a69dbeb232276b38f3f5016547bb2a2"
    1039             :                          "4025645f0b820e72b8cad4f0a909a092")))
    1040             :     {
    1041           0 :       fail ("sample point multiply failed:\n");
    1042           0 :       print_mpi ("r", a);
    1043           0 :       print_mpi ("Rx", x);
    1044           0 :       print_mpi ("Ry", y);
    1045             :     }
    1046             : 
    1047           1 :   gcry_mpi_release (a);
    1048           1 :   a = hex2mpi
    1049             :     ("2d3501e723239632802454ee5ddc406efb0bdf18486a5bde9c0390a9c2984004"
    1050             :      "f47252b628c953625b8deb5dbcb8da97aa43a1892d11fa83596f42e0d89cb1b6");
    1051           1 :   gcry_mpi_ec_mul (Q, a, G, ctx);
    1052           1 :   if (gcry_mpi_ec_get_affine (x, y, Q, ctx))
    1053           0 :     fail ("failed to get affine coordinates\n");
    1054           1 :   if (cmp_mpihex (x, ("6218e309d40065fcc338b3127f468371"
    1055             :                       "82324bd01ce6f3cf81ab44e62959c82a"))
    1056           1 :       || cmp_mpihex (y, ("5501492265e073d874d9e5b81e7f8784"
    1057             :                          "8a826e80cce2869072ac60c3004356e5")))
    1058             :     {
    1059           0 :       fail ("sample point multiply failed:\n");
    1060           0 :       print_mpi ("r", a);
    1061           0 :       print_mpi ("Rx", x);
    1062           0 :       print_mpi ("Ry", y);
    1063             :     }
    1064             : 
    1065             : 
    1066           1 :   gcry_mpi_release (I);
    1067           1 :   gcry_mpi_release (b);
    1068           1 :   gcry_mpi_release (n);
    1069           1 :   gcry_mpi_release (p);
    1070           1 :   gcry_mpi_release (w);
    1071           1 :   gcry_mpi_release (a);
    1072           1 :   gcry_mpi_release (x);
    1073           1 :   gcry_mpi_release (y);
    1074           1 :   gcry_mpi_release (z);
    1075           1 :   gcry_mpi_point_release (Q);
    1076           1 :   gcry_mpi_point_release (G);
    1077           1 :   gcry_mpi_release (k);
    1078           1 :   gcry_ctx_release (ctx);
    1079           1 : }
    1080             : 
    1081             : 
    1082             : int
    1083           1 : main (int argc, char **argv)
    1084             : {
    1085             : 
    1086           1 :   if (argc > 1 && !strcmp (argv[1], "--verbose"))
    1087           0 :     verbose = 1;
    1088           1 :   else if (argc > 1 && !strcmp (argv[1], "--debug"))
    1089           0 :     verbose = debug = 1;
    1090             : 
    1091           1 :   if (!gcry_check_version (GCRYPT_VERSION))
    1092           0 :     die ("version mismatch\n");
    1093             : 
    1094           1 :   gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
    1095           1 :   gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
    1096           1 :   if (debug)
    1097           0 :     gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
    1098           1 :   gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
    1099             : 
    1100           1 :   set_get_point ();
    1101           1 :   context_alloc ();
    1102           1 :   context_param ();
    1103           1 :   basic_ec_math ();
    1104           1 :   basic_ec_math_simplified ();
    1105           1 :   twistededwards_math ();
    1106             : 
    1107           1 :   show ("All tests completed. Errors: %d\n", error_count);
    1108           1 :   return error_count ? 1 : 0;
    1109             : }

Generated by: LCOV version 1.11