LCOV - code coverage report
Current view: top level - tests - t-mpi-point.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 393 569 69.1 %
Date: 2016-12-01 18:32:04 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             :       "0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEC",
     134             :       "0x52036CEE2B6FFE738CC740797779E89800700A4D4141D8AB75EB4DCA135978A3",
     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             :       /* P-192 and Ed25519 are not supported in fips mode */
     544           6 :       if (gcry_fips_mode_active())
     545             :         {
     546           0 :           if (!strcmp(test_curve[idx].desc, "NIST P-192")
     547           0 :               || !strcmp(test_curve[idx].desc, "Ed25519"))
     548             :             {
     549           0 :               show("skipping %s in fips mode\n", test_curve[idx].desc );
     550           0 :               continue;
     551             :             }
     552             :         }
     553             : 
     554           6 :       gcry_ctx_release (ctx);
     555           6 :       err = gcry_mpi_ec_new (&ctx, NULL, test_curve[idx].desc);
     556           6 :       if (err)
     557             :         {
     558           0 :           fail ("can't create context for curve '%s': %s\n",
     559             :                 test_curve[idx].desc, gpg_strerror (err));
     560           0 :           continue;
     561             :         }
     562           6 :       if (get_and_cmp_mpi ("p", test_curve[idx].p, test_curve[idx].desc, ctx))
     563           0 :         continue;
     564           6 :       if (get_and_cmp_mpi ("a", test_curve[idx].a, test_curve[idx].desc, ctx))
     565           0 :         continue;
     566           6 :       if (get_and_cmp_mpi ("b", test_curve[idx].b, test_curve[idx].desc, ctx))
     567           0 :         continue;
     568           6 :       if (get_and_cmp_mpi ("g.x",test_curve[idx].g_x, test_curve[idx].desc,ctx))
     569           0 :         continue;
     570           6 :       if (get_and_cmp_mpi ("g.y",test_curve[idx].g_y, test_curve[idx].desc,ctx))
     571           0 :         continue;
     572           6 :       if (get_and_cmp_mpi ("n", test_curve[idx].n, test_curve[idx].desc, ctx))
     573           0 :         continue;
     574           6 :       if (get_and_cmp_point ("g", test_curve[idx].g_x, test_curve[idx].g_y,
     575             :                              test_curve[idx].desc, ctx))
     576           0 :         continue;
     577           6 :       if (get_and_cmp_mpi ("h", test_curve[idx].h, test_curve[idx].desc, ctx))
     578           0 :         continue;
     579             : 
     580             :     }
     581             : 
     582           1 :   show ("checking sample public key (nistp256)\n");
     583           1 :   q = hex2mpi (sample_p256_q);
     584           1 :   err = gcry_sexp_build (&keyparam, NULL,
     585             :                         "(public-key(ecc(curve %s)(q %m)))",
     586             :                         "NIST P-256", q);
     587           1 :   if (err)
     588           0 :     die ("gcry_sexp_build failed: %s\n", gpg_strerror (err));
     589           1 :   gcry_mpi_release (q);
     590             : 
     591             :   /* We can't call gcry_pk_testkey because it is only implemented for
     592             :      private keys.  */
     593             :   /* err = gcry_pk_testkey (keyparam); */
     594             :   /* if (err) */
     595             :   /*   fail ("gcry_pk_testkey failed for sample public key: %s\n", */
     596             :   /*         gpg_strerror (err)); */
     597             : 
     598           1 :   gcry_ctx_release (ctx);
     599           1 :   err = gcry_mpi_ec_new (&ctx, keyparam, NULL);
     600           1 :   if (err)
     601           0 :     fail ("gcry_mpi_ec_new failed for sample public key (nistp256): %s\n",
     602             :           gpg_strerror (err));
     603             :   else
     604             :     {
     605             :       gcry_sexp_t sexp;
     606             : 
     607           1 :       get_and_cmp_mpi ("q", sample_p256_q, "nistp256", ctx);
     608           1 :       get_and_cmp_point ("q", sample_p256_q_x, sample_p256_q_y, "nistp256",
     609             :                          ctx);
     610             : 
     611             :       /* Delete Q.  */
     612           1 :       err = gcry_mpi_ec_set_mpi ("q", NULL, ctx);
     613           1 :       if (err)
     614           0 :         fail ("clearing Q for nistp256 failed: %s\n", gpg_strerror (err));
     615           1 :       if (gcry_mpi_ec_get_mpi ("q", ctx, 0))
     616           0 :         fail ("clearing Q for nistp256 did not work\n");
     617             : 
     618             :       /* Set Q again.  */
     619           1 :       q = hex2mpi (sample_p256_q);
     620           1 :       err = gcry_mpi_ec_set_mpi ("q", q, ctx);
     621           1 :       if (err)
     622           0 :         fail ("setting Q for nistp256 failed: %s\n", gpg_strerror (err));
     623           1 :       get_and_cmp_mpi ("q", sample_p256_q, "nistp256(2)", ctx);
     624           1 :       gcry_mpi_release (q);
     625             : 
     626             :       /* Get as s-expression.  */
     627           1 :       err = gcry_pubkey_get_sexp (&sexp, 0, ctx);
     628           1 :       if (err)
     629           0 :         fail ("gcry_pubkey_get_sexp(0) failed: %s\n", gpg_strerror (err));
     630           1 :       else if (debug)
     631           0 :         print_sexp ("Result of gcry_pubkey_get_sexp (0):\n", sexp);
     632           1 :       gcry_sexp_release (sexp);
     633             : 
     634           1 :       err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_PUBKEY, ctx);
     635           1 :       if (err)
     636           0 :         fail ("gcry_pubkey_get_sexp(GET_PUBKEY) failed: %s\n",
     637             :               gpg_strerror (err));
     638           1 :       else if (debug)
     639           0 :         print_sexp ("Result of gcry_pubkey_get_sexp (GET_PUBKEY):\n", sexp);
     640           1 :       gcry_sexp_release (sexp);
     641             : 
     642           1 :       err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_SECKEY, ctx);
     643           1 :       if (gpg_err_code (err) != GPG_ERR_NO_SECKEY)
     644           0 :         fail ("gcry_pubkey_get_sexp(GET_SECKEY) returned wrong error: %s\n",
     645             :               gpg_strerror (err));
     646           1 :       gcry_sexp_release (sexp);
     647             :     }
     648             : 
     649             :   /* Skipping Ed25519 if in FIPS mode (it isn't supported) */
     650           1 :   if (gcry_fips_mode_active())
     651           0 :     goto cleanup;
     652             : 
     653           1 :   show ("checking sample public key (Ed25519)\n");
     654           1 :   q = hex2mpi (sample_ed25519_q);
     655           1 :   gcry_sexp_release (keyparam);
     656           1 :   err = gcry_sexp_build (&keyparam, NULL,
     657             :                         "(public-key(ecc(curve %s)(flags eddsa)(q %m)))",
     658             :                         "Ed25519", q);
     659           1 :   if (err)
     660           0 :     die ("gcry_sexp_build failed: %s\n", gpg_strerror (err));
     661           1 :   gcry_mpi_release (q);
     662             : 
     663             :   /* We can't call gcry_pk_testkey because it is only implemented for
     664             :      private keys.  */
     665             :   /* err = gcry_pk_testkey (keyparam); */
     666             :   /* if (err) */
     667             :   /*   fail ("gcry_pk_testkey failed for sample public key: %s\n", */
     668             :   /*         gpg_strerror (err)); */
     669             : 
     670           1 :   gcry_ctx_release (ctx);
     671           1 :   err = gcry_mpi_ec_new (&ctx, keyparam, NULL);
     672           1 :   if (err)
     673           0 :     fail ("gcry_mpi_ec_new failed for sample public key: %s\n",
     674             :           gpg_strerror (err));
     675             :   else
     676             :     {
     677             :       gcry_sexp_t sexp;
     678             : 
     679           1 :       get_and_cmp_mpi ("q", sample_ed25519_q, "Ed25519", ctx);
     680           1 :       get_and_cmp_point ("q", sample_ed25519_q_x, sample_ed25519_q_y,
     681             :                          "Ed25519", ctx);
     682           1 :       get_and_cmp_mpi ("q@eddsa", sample_ed25519_q_eddsa, "Ed25519", ctx);
     683             : 
     684             :       /* Set d to see whether Q is correctly re-computed.  */
     685           1 :       d = hex2mpi (sample_ed25519_d);
     686           1 :       err = gcry_mpi_ec_set_mpi ("d", d, ctx);
     687           1 :       if (err)
     688           0 :         fail ("setting d for Ed25519 failed: %s\n", gpg_strerror (err));
     689           1 :       gcry_mpi_release (d);
     690           1 :       get_and_cmp_mpi ("q", sample_ed25519_q, "Ed25519(recompute Q)", ctx);
     691             : 
     692             :       /* Delete Q by setting d and then clearing d.  The clearing is
     693             :          required so that we can check whether Q has been cleared and
     694             :          because further tests only expect a public key.  */
     695           1 :       d = hex2mpi (sample_ed25519_d);
     696           1 :       err = gcry_mpi_ec_set_mpi ("d", d, ctx);
     697           1 :       if (err)
     698           0 :         fail ("setting d for Ed25519 failed: %s\n", gpg_strerror (err));
     699           1 :       gcry_mpi_release (d);
     700           1 :       err = gcry_mpi_ec_set_mpi ("d", NULL, ctx);
     701           1 :       if (err)
     702           0 :         fail ("setting d for Ed25519 failed(2): %s\n", gpg_strerror (err));
     703           1 :       if (gcry_mpi_ec_get_mpi ("q", ctx, 0))
     704           0 :         fail ("setting d for Ed25519 did not reset Q\n");
     705             : 
     706             :       /* Set Q again.  We need to use an opaque MPI here because
     707             :          sample_ed25519_q is in uncompressed format which can only be
     708             :          auto-detected if passed opaque.  */
     709           1 :       q = hex2mpiopa (sample_ed25519_q);
     710           1 :       err = gcry_mpi_ec_set_mpi ("q", q, ctx);
     711           1 :       if (err)
     712           0 :         fail ("setting Q for Ed25519 failed: %s\n", gpg_strerror (err));
     713           1 :       gcry_mpi_release (q);
     714           1 :       get_and_cmp_mpi ("q", sample_ed25519_q, "Ed25519(2)", ctx);
     715             : 
     716             :       /* Get as s-expression.  */
     717           1 :       err = gcry_pubkey_get_sexp (&sexp, 0, ctx);
     718           1 :       if (err)
     719           0 :         fail ("gcry_pubkey_get_sexp(0) failed: %s\n", gpg_strerror (err));
     720           1 :       else if (debug)
     721           0 :         print_sexp ("Result of gcry_pubkey_get_sexp (0):\n", sexp);
     722           1 :       gcry_sexp_release (sexp);
     723             : 
     724           1 :       err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_PUBKEY, ctx);
     725           1 :       if (err)
     726           0 :         fail ("gcry_pubkey_get_sexp(GET_PUBKEY) failed: %s\n",
     727             :               gpg_strerror (err));
     728           1 :       else if (debug)
     729           0 :         print_sexp ("Result of gcry_pubkey_get_sexp (GET_PUBKEY):\n", sexp);
     730           1 :       gcry_sexp_release (sexp);
     731             : 
     732           1 :       err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_SECKEY, ctx);
     733           1 :       if (gpg_err_code (err) != GPG_ERR_NO_SECKEY)
     734           0 :         fail ("gcry_pubkey_get_sexp(GET_SECKEY) returned wrong error: %s\n",
     735             :               gpg_strerror (err));
     736           1 :       gcry_sexp_release (sexp);
     737             : 
     738             :     }
     739             : 
     740             :  cleanup:
     741           1 :   gcry_ctx_release (ctx);
     742           1 :   gcry_sexp_release (keyparam);
     743           1 : }
     744             : 
     745             : 
     746             : 
     747             : 
     748             : /* Create a new point from (X,Y,Z) given as hex strings.  */
     749             : gcry_mpi_point_t
     750           1 : make_point (const char *x, const char *y, const char *z)
     751             : {
     752             :   gcry_mpi_point_t point;
     753             : 
     754           1 :   point = gcry_mpi_point_new (0);
     755           1 :   gcry_mpi_point_snatch_set (point, hex2mpi (x), hex2mpi (y), hex2mpi (z));
     756             : 
     757           1 :   return point;
     758             : }
     759             : 
     760             : 
     761             : /* This tests checks that the low-level EC API yields the same result
     762             :    as using the high level API.  The values have been taken from a
     763             :    test run using the high level API.  */
     764             : static void
     765           1 : basic_ec_math (void)
     766             : {
     767             :   gpg_error_t err;
     768             :   gcry_ctx_t ctx;
     769             :   gcry_mpi_t P, A;
     770             :   gcry_mpi_point_t G, Q;
     771             :   gcry_mpi_t d;
     772             :   gcry_mpi_t x, y, z;
     773             : 
     774           1 :   wherestr = "basic_ec_math";
     775           1 :   show ("checking basic math functions for EC\n");
     776             : 
     777           1 :   P = hex2mpi ("0xfffffffffffffffffffffffffffffffeffffffffffffffff");
     778           1 :   A = hex2mpi ("0xfffffffffffffffffffffffffffffffefffffffffffffffc");
     779           1 :   G = make_point ("188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012",
     780             :                   "7192B95FFC8DA78631011ED6B24CDD573F977A11E794811",
     781             :                   "1");
     782           1 :   d = hex2mpi ("D4EF27E32F8AD8E2A1C6DDEBB1D235A69E3CEF9BCE90273D");
     783           1 :   Q = gcry_mpi_point_new (0);
     784             : 
     785           1 :   err = ec_p_new (&ctx, P, A);
     786           1 :   if (err)
     787           0 :     die ("ec_p_new failed: %s\n", gpg_strerror (err));
     788             : 
     789           1 :   x = gcry_mpi_new (0);
     790           1 :   y = gcry_mpi_new (0);
     791           1 :   z = gcry_mpi_new (0);
     792             : 
     793             :   {
     794             :     /* A quick check that multiply by zero works.  */
     795             :     gcry_mpi_t tmp;
     796             : 
     797           1 :     tmp = gcry_mpi_new (0);
     798           1 :     gcry_mpi_ec_mul (Q, tmp, G, ctx);
     799           1 :     gcry_mpi_release (tmp);
     800           1 :     gcry_mpi_point_get (x, y, z, Q);
     801           1 :     if (gcry_mpi_cmp_ui (x, 0) || gcry_mpi_cmp_ui (y, 0)
     802           1 :         || gcry_mpi_cmp_ui (z, 0))
     803           0 :       fail ("multiply a point by zero failed\n");
     804             :   }
     805             : 
     806           1 :   gcry_mpi_ec_mul (Q, d, G, ctx);
     807           1 :   gcry_mpi_point_get (x, y, z, Q);
     808           1 :   if (cmp_mpihex (x, "222D9EC717C89D047E0898C9185B033CD11C0A981EE6DC66")
     809           1 :       || cmp_mpihex (y, "605DE0A82D70D3E0F84A127D0739ED33D657DF0D054BFDE8")
     810           1 :       || cmp_mpihex (z, "00B06B519071BC536999AC8F2D3934B3C1FC9EACCD0A31F88F"))
     811           0 :     fail ("computed public key does not match\n");
     812           1 :   if (debug)
     813             :     {
     814           0 :       print_mpi ("Q.x", x);
     815           0 :       print_mpi ("Q.y", y);
     816           0 :       print_mpi ("Q.z", z);
     817             :     }
     818             : 
     819           1 :   if (gcry_mpi_ec_get_affine (x, y, Q, ctx))
     820           0 :     fail ("failed to get affine coordinates\n");
     821           1 :   if (cmp_mpihex (x, "008532093BA023F4D55C0424FA3AF9367E05F309DC34CDC3FE")
     822           1 :       || cmp_mpihex (y, "00C13CA9E617C6C8487BFF6A726E3C4F277913D97117939966"))
     823           0 :     fail ("computed affine coordinates of public key do not match\n");
     824           1 :   if (debug)
     825             :     {
     826           0 :       print_mpi ("q.x", x);
     827           0 :       print_mpi ("q.y", y);
     828             :     }
     829             : 
     830           1 :   gcry_mpi_release (z);
     831           1 :   gcry_mpi_release (y);
     832           1 :   gcry_mpi_release (x);
     833           1 :   gcry_mpi_point_release (Q);
     834           1 :   gcry_mpi_release (d);
     835           1 :   gcry_mpi_point_release (G);
     836           1 :   gcry_mpi_release (A);
     837           1 :   gcry_mpi_release (P);
     838           1 :   gcry_ctx_release (ctx);
     839           1 : }
     840             : 
     841             : 
     842             : /* This is the same as basic_ec_math but uses more advanced
     843             :    features.  */
     844             : static void
     845           1 : basic_ec_math_simplified (void)
     846             : {
     847             :   gpg_error_t err;
     848             :   gcry_ctx_t ctx;
     849             :   gcry_mpi_point_t G, Q;
     850             :   gcry_mpi_t d;
     851             :   gcry_mpi_t x, y, z;
     852             :   gcry_sexp_t sexp;
     853             : 
     854           1 :   wherestr = "basic_ec_math_simplified";
     855           1 :   show ("checking basic math functions for EC (variant)\n");
     856             : 
     857           1 :   d = hex2mpi ("D4EF27E32F8AD8E2A1C6DDEBB1D235A69E3CEF9BCE90273D");
     858           1 :   Q = gcry_mpi_point_new (0);
     859             : 
     860           1 :   err = gcry_mpi_ec_new (&ctx, NULL, "NIST P-192");
     861           1 :   if (err)
     862           0 :     die ("gcry_mpi_ec_new failed: %s\n", gpg_strerror (err));
     863           1 :   G = gcry_mpi_ec_get_point ("g", ctx, 1);
     864           1 :   if (!G)
     865           0 :     die ("gcry_mpi_ec_get_point(G) failed\n");
     866           1 :   gcry_mpi_ec_mul (Q, d, G, ctx);
     867             : 
     868           1 :   x = gcry_mpi_new (0);
     869           1 :   y = gcry_mpi_new (0);
     870           1 :   z = gcry_mpi_new (0);
     871           1 :   gcry_mpi_point_get (x, y, z, Q);
     872           1 :   if (cmp_mpihex (x, "222D9EC717C89D047E0898C9185B033CD11C0A981EE6DC66")
     873           1 :       || cmp_mpihex (y, "605DE0A82D70D3E0F84A127D0739ED33D657DF0D054BFDE8")
     874           1 :       || cmp_mpihex (z, "00B06B519071BC536999AC8F2D3934B3C1FC9EACCD0A31F88F"))
     875           0 :     fail ("computed public key does not match\n");
     876           1 :   if (debug)
     877             :     {
     878           0 :       print_mpi ("Q.x", x);
     879           0 :       print_mpi ("Q.y", y);
     880           0 :       print_mpi ("Q.z", z);
     881             :     }
     882             : 
     883           1 :   if (gcry_mpi_ec_get_affine (x, y, Q, ctx))
     884           0 :     fail ("failed to get affine coordinates\n");
     885           1 :   if (cmp_mpihex (x, "008532093BA023F4D55C0424FA3AF9367E05F309DC34CDC3FE")
     886           1 :       || cmp_mpihex (y, "00C13CA9E617C6C8487BFF6A726E3C4F277913D97117939966"))
     887           0 :     fail ("computed affine coordinates of public key do not match\n");
     888           1 :   if (debug)
     889             :     {
     890           0 :       print_mpi ("q.x", x);
     891           0 :       print_mpi ("q.y", y);
     892             :     }
     893             : 
     894           1 :   gcry_mpi_release (z);
     895           1 :   gcry_mpi_release (y);
     896           1 :   gcry_mpi_release (x);
     897             : 
     898             :   /* Let us also check whether we can update the context.  */
     899           1 :   err = gcry_mpi_ec_set_point ("g", G, ctx);
     900           1 :   if (err)
     901           0 :     die ("gcry_mpi_ec_set_point(G) failed\n");
     902           1 :   err = gcry_mpi_ec_set_mpi ("d", d, ctx);
     903           1 :   if (err)
     904           0 :     die ("gcry_mpi_ec_set_mpi(d) failed\n");
     905             : 
     906             :   /* FIXME: Below we need to check that the returned S-expression is
     907             :      as requested.  For now we use manual inspection using --debug.  */
     908             : 
     909             :   /* Does get_sexp return the private key?  */
     910           1 :   err = gcry_pubkey_get_sexp (&sexp, 0, ctx);
     911           1 :   if (err)
     912           0 :     fail ("gcry_pubkey_get_sexp(0) failed: %s\n", gpg_strerror (err));
     913           1 :   else if (debug)
     914           0 :     print_sexp ("Result of gcry_pubkey_get_sexp (0):\n", sexp);
     915           1 :   gcry_sexp_release (sexp);
     916             : 
     917             :   /* Does get_sexp return the public key if requested?  */
     918           1 :   err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_PUBKEY, ctx);
     919           1 :   if (err)
     920           0 :     fail ("gcry_pubkey_get_sexp(GET_PUBKEY) failed: %s\n", gpg_strerror (err));
     921           1 :   else if (debug)
     922           0 :     print_sexp ("Result of gcry_pubkey_get_sexp (GET_PUBKEY):\n", sexp);
     923           1 :   gcry_sexp_release (sexp);
     924             : 
     925             :   /* Does get_sexp return the public key after d has been deleted?  */
     926           1 :   err = gcry_mpi_ec_set_mpi ("d", NULL, ctx);
     927           1 :   if (err)
     928           0 :     die ("gcry_mpi_ec_set_mpi(d=NULL) failed\n");
     929           1 :   err = gcry_pubkey_get_sexp (&sexp, 0, ctx);
     930           1 :   if (err)
     931           0 :     fail ("gcry_pubkey_get_sexp(0 w/o d) failed: %s\n", gpg_strerror (err));
     932           1 :   else if (debug)
     933           0 :     print_sexp ("Result of gcry_pubkey_get_sexp (0 w/o d):\n", sexp);
     934           1 :   gcry_sexp_release (sexp);
     935             : 
     936             :   /* Does get_sexp return an error after d has been deleted?  */
     937           1 :   err = gcry_pubkey_get_sexp (&sexp, GCRY_PK_GET_SECKEY, ctx);
     938           1 :   if (gpg_err_code (err) != GPG_ERR_NO_SECKEY)
     939           0 :     fail ("gcry_pubkey_get_sexp(GET_SECKEY) returned wrong error: %s\n",
     940             :           gpg_strerror (err));
     941           1 :   gcry_sexp_release (sexp);
     942             : 
     943             :   /* Does get_sexp return an error after d and Q have been deleted?  */
     944           1 :   err = gcry_mpi_ec_set_point ("q", NULL, ctx);
     945           1 :   if (err)
     946           0 :     die ("gcry_mpi_ec_set_point(q=NULL) failed\n");
     947           1 :   err = gcry_pubkey_get_sexp (&sexp, 0, ctx);
     948           1 :   if (gpg_err_code (err) != GPG_ERR_BAD_CRYPT_CTX)
     949           0 :     fail ("gcry_pubkey_get_sexp(0 w/o Q,d) returned wrong error: %s\n",
     950             :           gpg_strerror (err));
     951           1 :   gcry_sexp_release (sexp);
     952             : 
     953             : 
     954           1 :   gcry_mpi_point_release (Q);
     955           1 :   gcry_mpi_release (d);
     956           1 :   gcry_mpi_point_release (G);
     957           1 :   gcry_ctx_release (ctx);
     958           1 : }
     959             : 
     960             : 
     961             : /* Check the math used with Twisted Edwards curves.  */
     962             : static void
     963           1 : twistededwards_math (void)
     964             : {
     965             :   gpg_error_t err;
     966             :   gcry_ctx_t ctx;
     967             :   gcry_mpi_point_t G, Q;
     968             :   gcry_mpi_t k;
     969             :   gcry_mpi_t w, a, x, y, z, p, n, b, I;
     970             : 
     971           1 :   wherestr = "twistededwards_math";
     972           1 :   show ("checking basic Twisted Edwards math\n");
     973             : 
     974           1 :   err = gcry_mpi_ec_new (&ctx, NULL, "Ed25519");
     975           1 :   if (err)
     976           0 :     die ("gcry_mpi_ec_new failed: %s\n", gpg_strerror (err));
     977             : 
     978           1 :   k = hex2mpi
     979             :     ("2D3501E723239632802454EE5DDC406EFB0BDF18486A5BDE9C0390A9C2984004"
     980             :      "F47252B628C953625B8DEB5DBCB8DA97AA43A1892D11FA83596F42E0D89CB1B6");
     981           1 :   G = gcry_mpi_ec_get_point ("g", ctx, 1);
     982           1 :   if (!G)
     983           0 :     die ("gcry_mpi_ec_get_point(G) failed\n");
     984           1 :   Q = gcry_mpi_point_new (0);
     985             : 
     986             : 
     987           1 :   w = gcry_mpi_new (0);
     988           1 :   a = gcry_mpi_new (0);
     989           1 :   x = gcry_mpi_new (0);
     990           1 :   y = gcry_mpi_new (0);
     991           1 :   z = gcry_mpi_new (0);
     992           1 :   I = gcry_mpi_new (0);
     993           1 :   p = gcry_mpi_ec_get_mpi ("p", ctx, 1);
     994           1 :   n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
     995           1 :   b = gcry_mpi_ec_get_mpi ("b", ctx, 1);
     996             : 
     997             :   /* Check: 2^{p-1} mod p == 1 */
     998           1 :   gcry_mpi_sub_ui (a, p, 1);
     999           1 :   gcry_mpi_powm (w, GCRYMPI_CONST_TWO, a, p);
    1000           1 :   if (gcry_mpi_cmp_ui (w, 1))
    1001           0 :     fail ("failed assertion: 2^{p-1} mod p == 1\n");
    1002             : 
    1003             :   /* Check: p % 4 == 1 */
    1004           1 :   gcry_mpi_mod (w, p, GCRYMPI_CONST_FOUR);
    1005           1 :   if (gcry_mpi_cmp_ui (w, 1))
    1006           0 :     fail ("failed assertion: p % 4 == 1\n");
    1007             : 
    1008             :   /* Check: 2^{n-1} mod n == 1 */
    1009           1 :   gcry_mpi_sub_ui (a, n, 1);
    1010           1 :   gcry_mpi_powm (w, GCRYMPI_CONST_TWO, a, n);
    1011           1 :   if (gcry_mpi_cmp_ui (w, 1))
    1012           0 :     fail ("failed assertion: 2^{n-1} mod n == 1\n");
    1013             : 
    1014             :   /* Check: b^{(p-1)/2} mod p == p-1 */
    1015           1 :   gcry_mpi_sub_ui (a, p, 1);
    1016           1 :   gcry_mpi_div (x, NULL, a, GCRYMPI_CONST_TWO, -1);
    1017           1 :   gcry_mpi_powm (w, b, x, p);
    1018           1 :   gcry_mpi_abs (w);
    1019           1 :   if (gcry_mpi_cmp (w, a))
    1020           0 :     fail ("failed assertion: b^{(p-1)/2} mod p == p-1\n");
    1021             : 
    1022             :   /* I := 2^{(p-1)/4} mod p */
    1023           1 :   gcry_mpi_sub_ui (a, p, 1);
    1024           1 :   gcry_mpi_div (x, NULL, a, GCRYMPI_CONST_FOUR, -1);
    1025           1 :   gcry_mpi_powm (I, GCRYMPI_CONST_TWO, x, p);
    1026             : 
    1027             :   /* Check: I^2 mod p == p-1 */
    1028           1 :   gcry_mpi_powm (w, I, GCRYMPI_CONST_TWO, p);
    1029           1 :   if (gcry_mpi_cmp (w, a))
    1030           0 :     fail ("failed assertion: I^2 mod p == p-1\n");
    1031             : 
    1032             :   /* Check: G is on the curve */
    1033           1 :   if (!gcry_mpi_ec_curve_point (G, ctx))
    1034           0 :     fail ("failed assertion: G is on the curve\n");
    1035             : 
    1036             :   /* Check: nG == (0,1) */
    1037           1 :   gcry_mpi_ec_mul (Q, n, G, ctx);
    1038           1 :   if (gcry_mpi_ec_get_affine (x, y, Q, ctx))
    1039           0 :     fail ("failed to get affine coordinates\n");
    1040           1 :   if (gcry_mpi_cmp_ui (x, 0) || gcry_mpi_cmp_ui (y, 1))
    1041           0 :     fail ("failed assertion: nG == (0,1)\n");
    1042             : 
    1043             :   /* Now two arbitrary point operations taken from the ed25519.py
    1044             :      sample data.  */
    1045           1 :   gcry_mpi_release (a);
    1046           1 :   a = hex2mpi
    1047             :     ("4f71d012df3c371af3ea4dc38385ca5bb7272f90cb1b008b3ed601c76de1d496"
    1048             :      "e30cbf625f0a756a678d8f256d5325595cccc83466f36db18f0178eb9925edd3");
    1049           1 :   gcry_mpi_ec_mul (Q, a, G, ctx);
    1050           1 :   if (gcry_mpi_ec_get_affine (x, y, Q, ctx))
    1051           0 :     fail ("failed to get affine coordinates\n");
    1052           1 :   if (cmp_mpihex (x, ("157f7361c577aad36f67ed33e38dc7be"
    1053             :                       "00014fecc2165ca5cee9eee19fe4d2c1"))
    1054           1 :       || cmp_mpihex (y, ("5a69dbeb232276b38f3f5016547bb2a2"
    1055             :                          "4025645f0b820e72b8cad4f0a909a092")))
    1056             :     {
    1057           0 :       fail ("sample point multiply failed:\n");
    1058           0 :       print_mpi ("r", a);
    1059           0 :       print_mpi ("Rx", x);
    1060           0 :       print_mpi ("Ry", y);
    1061             :     }
    1062             : 
    1063           1 :   gcry_mpi_release (a);
    1064           1 :   a = hex2mpi
    1065             :     ("2d3501e723239632802454ee5ddc406efb0bdf18486a5bde9c0390a9c2984004"
    1066             :      "f47252b628c953625b8deb5dbcb8da97aa43a1892d11fa83596f42e0d89cb1b6");
    1067           1 :   gcry_mpi_ec_mul (Q, a, G, ctx);
    1068           1 :   if (gcry_mpi_ec_get_affine (x, y, Q, ctx))
    1069           0 :     fail ("failed to get affine coordinates\n");
    1070           1 :   if (cmp_mpihex (x, ("6218e309d40065fcc338b3127f468371"
    1071             :                       "82324bd01ce6f3cf81ab44e62959c82a"))
    1072           1 :       || cmp_mpihex (y, ("5501492265e073d874d9e5b81e7f8784"
    1073             :                          "8a826e80cce2869072ac60c3004356e5")))
    1074             :     {
    1075           0 :       fail ("sample point multiply failed:\n");
    1076           0 :       print_mpi ("r", a);
    1077           0 :       print_mpi ("Rx", x);
    1078           0 :       print_mpi ("Ry", y);
    1079             :     }
    1080             : 
    1081             : 
    1082           1 :   gcry_mpi_release (I);
    1083           1 :   gcry_mpi_release (b);
    1084           1 :   gcry_mpi_release (n);
    1085           1 :   gcry_mpi_release (p);
    1086           1 :   gcry_mpi_release (w);
    1087           1 :   gcry_mpi_release (a);
    1088           1 :   gcry_mpi_release (x);
    1089           1 :   gcry_mpi_release (y);
    1090           1 :   gcry_mpi_release (z);
    1091           1 :   gcry_mpi_point_release (Q);
    1092           1 :   gcry_mpi_point_release (G);
    1093           1 :   gcry_mpi_release (k);
    1094           1 :   gcry_ctx_release (ctx);
    1095           1 : }
    1096             : 
    1097             : 
    1098             : int
    1099           1 : main (int argc, char **argv)
    1100             : {
    1101             : 
    1102           1 :   if (argc > 1 && !strcmp (argv[1], "--verbose"))
    1103           0 :     verbose = 1;
    1104           1 :   else if (argc > 1 && !strcmp (argv[1], "--debug"))
    1105           0 :     verbose = debug = 1;
    1106             : 
    1107           1 :   if (!gcry_check_version (GCRYPT_VERSION))
    1108           0 :     die ("version mismatch\n");
    1109             : 
    1110           1 :   gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
    1111           1 :   gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
    1112           1 :   if (debug)
    1113           0 :     gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
    1114           1 :   gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
    1115             : 
    1116           1 :   set_get_point ();
    1117           1 :   context_alloc ();
    1118           1 :   context_param ();
    1119           1 :   basic_ec_math ();
    1120             : 
    1121             :   /* The tests are for P-192 and ed25519 which are not supported in
    1122             :      FIPS mode.  */
    1123           1 :   if (!gcry_fips_mode_active())
    1124             :     {
    1125           1 :       basic_ec_math_simplified ();
    1126           1 :       twistededwards_math ();
    1127             :     }
    1128             : 
    1129           1 :   show ("All tests completed. Errors: %d\n", error_count);
    1130           1 :   return error_count ? 1 : 0;
    1131             : }

Generated by: LCOV version 1.11