LCOV - code coverage report
Current view: top level - tests - t-mpi-point.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 390 543 71.8 %
Date: 2017-03-02 16:44:37 Functions: 15 19 78.9 %

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

Generated by: LCOV version 1.13