LCOV - code coverage report
Current view: top level - cipher - ecc-eddsa.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 434 0.0 %
Date: 2016-12-15 12:59:22 Functions: 0 12 0.0 %

          Line data    Source code
       1             : /* ecc-eddsa.c  -  Elliptic Curve EdDSA signatures
       2             :  * Copyright (C) 2013, 2014 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             : #include <config.h>
      21             : #include <stdio.h>
      22             : #include <stdlib.h>
      23             : #include <string.h>
      24             : #include <errno.h>
      25             : 
      26             : #include "g10lib.h"
      27             : #include "mpi.h"
      28             : #include "cipher.h"
      29             : #include "context.h"
      30             : #include "ec-context.h"
      31             : #include "ecc-common.h"
      32             : 
      33             : 
      34             : 
      35             : static void
      36           0 : reverse_buffer (unsigned char *buffer, unsigned int length)
      37             : {
      38             :   unsigned int tmp, i;
      39             : 
      40           0 :   for (i=0; i < length/2; i++)
      41             :     {
      42           0 :       tmp = buffer[i];
      43           0 :       buffer[i] = buffer[length-1-i];
      44           0 :       buffer[length-1-i] = tmp;
      45             :     }
      46           0 : }
      47             : 
      48             : 
      49             : /* Helper to scan a hex string. */
      50             : static gcry_mpi_t
      51           0 : scanval (const char *string)
      52             : {
      53             :   gpg_err_code_t rc;
      54             :   gcry_mpi_t val;
      55             : 
      56           0 :   rc = _gcry_mpi_scan (&val, GCRYMPI_FMT_HEX, string, 0, NULL);
      57           0 :   if (rc)
      58           0 :     log_fatal ("scanning ECC parameter failed: %s\n", gpg_strerror (rc));
      59           0 :   return val;
      60             : }
      61             : 
      62             : 
      63             : 
      64             : /* Encode MPI using the EdDSA scheme.  MINLEN specifies the required
      65             :    length of the buffer in bytes.  On success 0 is returned an a
      66             :    malloced buffer with the encoded point is stored at R_BUFFER; the
      67             :    length of this buffer is stored at R_BUFLEN.  */
      68             : static gpg_err_code_t
      69           0 : eddsa_encodempi (gcry_mpi_t mpi, unsigned int minlen,
      70             :                  unsigned char **r_buffer, unsigned int *r_buflen)
      71             : {
      72             :   unsigned char *rawmpi;
      73             :   unsigned int rawmpilen;
      74             : 
      75           0 :   rawmpi = _gcry_mpi_get_buffer (mpi, minlen, &rawmpilen, NULL);
      76           0 :   if (!rawmpi)
      77           0 :     return gpg_err_code_from_syserror ();
      78             : 
      79           0 :   *r_buffer = rawmpi;
      80           0 :   *r_buflen = rawmpilen;
      81           0 :   return 0;
      82             : }
      83             : 
      84             : 
      85             : /* Encode (X,Y) using the EdDSA scheme.  MINLEN is the required length
      86             :    in bytes for the result.  If WITH_PREFIX is set the returned buffer
      87             :    is prefixed with a 0x40 byte.  On success 0 is returned and a
      88             :    malloced buffer with the encoded point is stored at R_BUFFER; the
      89             :    length of this buffer is stored at R_BUFLEN.  */
      90             : static gpg_err_code_t
      91           0 : eddsa_encode_x_y (gcry_mpi_t x, gcry_mpi_t y, unsigned int minlen,
      92             :                   int with_prefix,
      93             :                   unsigned char **r_buffer, unsigned int *r_buflen)
      94             : {
      95             :   unsigned char *rawmpi;
      96             :   unsigned int rawmpilen;
      97           0 :   int off = with_prefix? 1:0;
      98             : 
      99           0 :   rawmpi = _gcry_mpi_get_buffer_extra (y, minlen, off?-1:0, &rawmpilen, NULL);
     100           0 :   if (!rawmpi)
     101           0 :     return gpg_err_code_from_syserror ();
     102           0 :   if (mpi_test_bit (x, 0) && rawmpilen)
     103           0 :     rawmpi[off + rawmpilen - 1] |= 0x80;  /* Set sign bit.  */
     104           0 :   if (off)
     105           0 :     rawmpi[0] = 0x40;
     106             : 
     107           0 :   *r_buffer = rawmpi;
     108           0 :   *r_buflen = rawmpilen + off;
     109           0 :   return 0;
     110             : }
     111             : 
     112             : /* Encode POINT using the EdDSA scheme.  X and Y are either scratch
     113             :    variables supplied by the caller or NULL.  CTX is the usual
     114             :    context.  If WITH_PREFIX is set the returned buffer is prefixed
     115             :    with a 0x40 byte.  On success 0 is returned and a malloced buffer
     116             :    with the encoded point is stored at R_BUFFER; the length of this
     117             :    buffer is stored at R_BUFLEN.  */
     118             : gpg_err_code_t
     119           0 : _gcry_ecc_eddsa_encodepoint (mpi_point_t point, mpi_ec_t ec,
     120             :                              gcry_mpi_t x_in, gcry_mpi_t y_in,
     121             :                              int with_prefix,
     122             :                              unsigned char **r_buffer, unsigned int *r_buflen)
     123             : {
     124             :   gpg_err_code_t rc;
     125             :   gcry_mpi_t x, y;
     126             : 
     127           0 :   x = x_in? x_in : mpi_new (0);
     128           0 :   y = y_in? y_in : mpi_new (0);
     129             : 
     130           0 :   if (_gcry_mpi_ec_get_affine (x, y, point, ec))
     131             :     {
     132           0 :       log_error ("eddsa_encodepoint: Failed to get affine coordinates\n");
     133           0 :       rc = GPG_ERR_INTERNAL;
     134             :     }
     135             :   else
     136           0 :     rc = eddsa_encode_x_y (x, y, ec->nbits/8, with_prefix, r_buffer, r_buflen);
     137             : 
     138           0 :   if (!x_in)
     139           0 :     mpi_free (x);
     140           0 :   if (!y_in)
     141           0 :     mpi_free (y);
     142           0 :   return rc;
     143             : }
     144             : 
     145             : 
     146             : /* Make sure that the opaque MPI VALUE is in compact EdDSA format.
     147             :    This function updates MPI if needed.  */
     148             : gpg_err_code_t
     149           0 : _gcry_ecc_eddsa_ensure_compact (gcry_mpi_t value, unsigned int nbits)
     150             : {
     151             :   gpg_err_code_t rc;
     152             :   const unsigned char *buf;
     153             :   unsigned int rawmpilen;
     154             :   gcry_mpi_t x, y;
     155             :   unsigned char *enc;
     156             :   unsigned int enclen;
     157             : 
     158           0 :   if (!mpi_is_opaque (value))
     159           0 :     return GPG_ERR_INV_OBJ;
     160           0 :   buf = mpi_get_opaque (value, &rawmpilen);
     161           0 :   if (!buf)
     162           0 :     return GPG_ERR_INV_OBJ;
     163           0 :   rawmpilen = (rawmpilen + 7)/8;
     164             : 
     165           0 :   if (rawmpilen > 1 && (rawmpilen%2))
     166             :     {
     167           0 :       if (buf[0] == 0x04)
     168             :         {
     169             :           /* Buffer is in SEC1 uncompressed format.  Extract y and
     170             :              compress.  */
     171           0 :           rc = _gcry_mpi_scan (&x, GCRYMPI_FMT_STD,
     172           0 :                                buf+1, (rawmpilen-1)/2, NULL);
     173           0 :           if (rc)
     174           0 :             return rc;
     175           0 :           rc = _gcry_mpi_scan (&y, GCRYMPI_FMT_STD,
     176           0 :                                buf+1+(rawmpilen-1)/2, (rawmpilen-1)/2, NULL);
     177           0 :           if (rc)
     178             :             {
     179           0 :               mpi_free (x);
     180           0 :               return rc;
     181             :             }
     182             : 
     183           0 :           rc = eddsa_encode_x_y (x, y, nbits/8, 0, &enc, &enclen);
     184           0 :           mpi_free (x);
     185           0 :           mpi_free (y);
     186           0 :           if (rc)
     187           0 :             return rc;
     188             : 
     189           0 :           mpi_set_opaque (value, enc, 8*enclen);
     190             :         }
     191           0 :       else if (buf[0] == 0x40)
     192             :         {
     193             :           /* Buffer is compressed but with our SEC1 alike compression
     194             :              indicator.  Remove that byte.  FIXME: We should write and
     195             :              use a function to manipulate an opaque MPI in place. */
     196           0 :           if (!_gcry_mpi_set_opaque_copy (value, buf + 1, (rawmpilen - 1)*8))
     197           0 :             return gpg_err_code_from_syserror ();
     198             :         }
     199             :     }
     200             : 
     201           0 :   return 0;
     202             : }
     203             : 
     204             : 
     205             : /* Recover X from Y and SIGN (which actually is a parity bit).  */
     206             : gpg_err_code_t
     207           0 : _gcry_ecc_eddsa_recover_x (gcry_mpi_t x, gcry_mpi_t y, int sign, mpi_ec_t ec)
     208             : {
     209           0 :   gpg_err_code_t rc = 0;
     210             :   gcry_mpi_t u, v, v3, t;
     211             :   static gcry_mpi_t p58, seven;
     212             : 
     213           0 :   if (ec->dialect != ECC_DIALECT_ED25519)
     214           0 :     return GPG_ERR_NOT_IMPLEMENTED;
     215             : 
     216           0 :   if (!p58)
     217           0 :     p58 = scanval ("0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
     218             :                    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD");
     219           0 :   if (!seven)
     220           0 :     seven = mpi_set_ui (NULL, 7);
     221             : 
     222           0 :   u   = mpi_new (0);
     223           0 :   v   = mpi_new (0);
     224           0 :   v3  = mpi_new (0);
     225           0 :   t   = mpi_new (0);
     226             : 
     227             :   /* Compute u and v */
     228             :   /* u = y^2    */
     229           0 :   mpi_mulm (u, y, y, ec->p);
     230             :   /* v = b*y^2   */
     231           0 :   mpi_mulm (v, ec->b, u, ec->p);
     232             :   /* u = y^2-1  */
     233           0 :   mpi_sub_ui (u, u, 1);
     234             :   /* v = b*y^2+1 */
     235           0 :   mpi_add_ui (v, v, 1);
     236             : 
     237             :   /* Compute sqrt(u/v) */
     238             :   /* v3 = v^3 */
     239           0 :   mpi_powm (v3, v, mpi_const (MPI_C_THREE), ec->p);
     240             :   /* t = v3 * v3 * u * v = u * v^7 */
     241           0 :   mpi_powm (t, v, seven, ec->p);
     242           0 :   mpi_mulm (t, t, u, ec->p);
     243             :   /* t = t^((p-5)/8) = (u * v^7)^((p-5)/8)  */
     244           0 :   mpi_powm (t, t, p58, ec->p);
     245             :   /* x = t * u * v^3 = (u * v^3) * (u * v^7)^((p-5)/8) */
     246           0 :   mpi_mulm (t, t, u, ec->p);
     247           0 :   mpi_mulm (x, t, v3, ec->p);
     248             : 
     249             :   /* Adjust if needed.  */
     250             :   /* t = v * x^2  */
     251           0 :   mpi_mulm (t, x, x, ec->p);
     252           0 :   mpi_mulm (t, t, v, ec->p);
     253             :   /* -t == u ? x = x * sqrt(-1) */
     254           0 :   mpi_sub (t, ec->p, t);
     255           0 :   if (!mpi_cmp (t, u))
     256             :     {
     257             :       static gcry_mpi_t m1;  /* Fixme: this is not thread-safe.  */
     258           0 :       if (!m1)
     259           0 :         m1 = scanval ("2B8324804FC1DF0B2B4D00993DFBD7A7"
     260             :                       "2F431806AD2FE478C4EE1B274A0EA0B0");
     261           0 :       mpi_mulm (x, x, m1, ec->p);
     262             :       /* t = v * x^2  */
     263           0 :       mpi_mulm (t, x, x, ec->p);
     264           0 :       mpi_mulm (t, t, v, ec->p);
     265             :       /* -t == u ? x = x * sqrt(-1) */
     266           0 :       mpi_sub (t, ec->p, t);
     267           0 :       if (!mpi_cmp (t, u))
     268           0 :         rc = GPG_ERR_INV_OBJ;
     269             :     }
     270             : 
     271             :   /* Choose the desired square root according to parity */
     272           0 :   if (mpi_test_bit (x, 0) != !!sign)
     273           0 :     mpi_sub (x, ec->p, x);
     274             : 
     275           0 :   mpi_free (t);
     276           0 :   mpi_free (v3);
     277           0 :   mpi_free (v);
     278           0 :   mpi_free (u);
     279             : 
     280           0 :   return rc;
     281             : }
     282             : 
     283             : 
     284             : /* Decode the EdDSA style encoded PK and set it into RESULT.  CTX is
     285             :    the usual curve context.  If R_ENCPK is not NULL, the encoded PK is
     286             :    stored at that address; this is a new copy to be released by the
     287             :    caller.  In contrast to the supplied PK, this is not an MPI and
     288             :    thus guaranteed to be properly padded.  R_ENCPKLEN receives the
     289             :    length of that encoded key.  */
     290             : gpg_err_code_t
     291           0 : _gcry_ecc_eddsa_decodepoint (gcry_mpi_t pk, mpi_ec_t ctx, mpi_point_t result,
     292             :                              unsigned char **r_encpk, unsigned int *r_encpklen)
     293             : {
     294             :   gpg_err_code_t rc;
     295             :   unsigned char *rawmpi;
     296             :   unsigned int rawmpilen;
     297             :   int sign;
     298             : 
     299           0 :   if (mpi_is_opaque (pk))
     300           0 :     {
     301             :       const unsigned char *buf;
     302             : 
     303           0 :       buf = mpi_get_opaque (pk, &rawmpilen);
     304           0 :       if (!buf)
     305           0 :         return GPG_ERR_INV_OBJ;
     306           0 :       rawmpilen = (rawmpilen + 7)/8;
     307             : 
     308             :       /* Handle compression prefixes.  The size of the buffer will be
     309             :          odd in this case.  */
     310           0 :       if (rawmpilen > 1 && (rawmpilen%2))
     311             :         {
     312             :           /* First check whether the public key has been given in
     313             :              standard uncompressed format (SEC1).  No need to recover
     314             :              x in this case.  */
     315           0 :           if (buf[0] == 0x04)
     316             :             {
     317             :               gcry_mpi_t x, y;
     318             : 
     319           0 :               rc = _gcry_mpi_scan (&x, GCRYMPI_FMT_STD,
     320           0 :                                    buf+1, (rawmpilen-1)/2, NULL);
     321           0 :               if (rc)
     322           0 :                 return rc;
     323           0 :               rc = _gcry_mpi_scan (&y, GCRYMPI_FMT_STD,
     324           0 :                                    buf+1+(rawmpilen-1)/2, (rawmpilen-1)/2,NULL);
     325           0 :               if (rc)
     326             :                 {
     327           0 :                   mpi_free (x);
     328           0 :                   return rc;
     329             :                 }
     330             : 
     331           0 :               if (r_encpk)
     332             :                 {
     333           0 :                   rc = eddsa_encode_x_y (x, y, ctx->nbits/8, 0,
     334             :                                          r_encpk, r_encpklen);
     335           0 :                   if (rc)
     336             :                     {
     337           0 :                       mpi_free (x);
     338           0 :                       mpi_free (y);
     339           0 :                       return rc;
     340             :                     }
     341             :                 }
     342           0 :               mpi_snatch (result->x, x);
     343           0 :               mpi_snatch (result->y, y);
     344           0 :               mpi_set_ui (result->z, 1);
     345           0 :               return 0;
     346             :             }
     347             : 
     348             :           /* Check whether the public key has been prefixed with a 0x40
     349             :              byte to explicitly indicate compressed format using a SEC1
     350             :              alike prefix byte.  This is a Libgcrypt extension.  */
     351           0 :           if (buf[0] == 0x40)
     352             :             {
     353           0 :               rawmpilen--;
     354           0 :               buf++;
     355             :             }
     356             :         }
     357             : 
     358             :       /* EdDSA compressed point.  */
     359           0 :       rawmpi = xtrymalloc (rawmpilen? rawmpilen:1);
     360           0 :       if (!rawmpi)
     361           0 :         return gpg_err_code_from_syserror ();
     362           0 :       memcpy (rawmpi, buf, rawmpilen);
     363           0 :       reverse_buffer (rawmpi, rawmpilen);
     364             :     }
     365             :   else
     366             :     {
     367             :       /* Note: Without using an opaque MPI it is not reliable possible
     368             :          to find out whether the public key has been given in
     369             :          uncompressed format.  Thus we expect native EdDSA format.  */
     370           0 :       rawmpi = _gcry_mpi_get_buffer (pk, ctx->nbits/8, &rawmpilen, NULL);
     371           0 :       if (!rawmpi)
     372           0 :         return gpg_err_code_from_syserror ();
     373             :     }
     374             : 
     375           0 :   if (rawmpilen)
     376             :     {
     377           0 :       sign = !!(rawmpi[0] & 0x80);
     378           0 :       rawmpi[0] &= 0x7f;
     379             :     }
     380             :   else
     381           0 :     sign = 0;
     382           0 :   _gcry_mpi_set_buffer (result->y, rawmpi, rawmpilen, 0);
     383           0 :   if (r_encpk)
     384             :     {
     385             :       /* Revert to little endian.  */
     386           0 :       if (sign && rawmpilen)
     387           0 :         rawmpi[0] |= 0x80;
     388           0 :       reverse_buffer (rawmpi, rawmpilen);
     389           0 :       *r_encpk = rawmpi;
     390           0 :       if (r_encpklen)
     391           0 :         *r_encpklen = rawmpilen;
     392             :     }
     393             :   else
     394           0 :     xfree (rawmpi);
     395             : 
     396           0 :   rc = _gcry_ecc_eddsa_recover_x (result->x, result->y, sign, ctx);
     397           0 :   mpi_set_ui (result->z, 1);
     398             : 
     399           0 :   return rc;
     400             : }
     401             : 
     402             : 
     403             : /* Compute the A value as used by EdDSA.  The caller needs to provide
     404             :    the context EC and the actual secret D as an MPI.  The function
     405             :    returns a newly allocated 64 byte buffer at r_digest; the first 32
     406             :    bytes represent the A value.  NULL is returned on error and NULL
     407             :    stored at R_DIGEST.  */
     408             : gpg_err_code_t
     409           0 : _gcry_ecc_eddsa_compute_h_d (unsigned char **r_digest,
     410             :                              gcry_mpi_t d, mpi_ec_t ec)
     411             : {
     412             :   gpg_err_code_t rc;
     413           0 :   unsigned char *rawmpi = NULL;
     414             :   unsigned int rawmpilen;
     415             :   unsigned char *digest;
     416             :   gcry_buffer_t hvec[2];
     417             :   int hashalgo, b;
     418             : 
     419           0 :   *r_digest = NULL;
     420             : 
     421           0 :   hashalgo = GCRY_MD_SHA512;
     422           0 :   if (hashalgo != GCRY_MD_SHA512)
     423           0 :     return GPG_ERR_DIGEST_ALGO;
     424             : 
     425           0 :   b = (ec->nbits+7)/8;
     426           0 :   if (b != 256/8)
     427           0 :     return GPG_ERR_INTERNAL; /* We only support 256 bit. */
     428             : 
     429             :   /* Note that we clear DIGEST so we can use it as input to left pad
     430             :      the key with zeroes for hashing.  */
     431           0 :   digest = xtrycalloc_secure (2, b);
     432           0 :   if (!digest)
     433           0 :     return gpg_err_code_from_syserror ();
     434             : 
     435           0 :   memset (hvec, 0, sizeof hvec);
     436             : 
     437           0 :   rawmpi = _gcry_mpi_get_buffer (d, 0, &rawmpilen, NULL);
     438           0 :   if (!rawmpi)
     439             :     {
     440           0 :       xfree (digest);
     441           0 :       return gpg_err_code_from_syserror ();
     442             :     }
     443             : 
     444           0 :   hvec[0].data = digest;
     445           0 :   hvec[0].off = 0;
     446           0 :   hvec[0].len = b > rawmpilen? b - rawmpilen : 0;
     447           0 :   hvec[1].data = rawmpi;
     448           0 :   hvec[1].off = 0;
     449           0 :   hvec[1].len = rawmpilen;
     450           0 :   rc = _gcry_md_hash_buffers (hashalgo, 0, digest, hvec, 2);
     451           0 :   xfree (rawmpi);
     452           0 :   if (rc)
     453             :     {
     454           0 :       xfree (digest);
     455           0 :       return rc;
     456             :     }
     457             : 
     458             :   /* Compute the A value.  */
     459           0 :   reverse_buffer (digest, 32);  /* Only the first half of the hash.  */
     460           0 :   digest[0]   = (digest[0] & 0x7f) | 0x40;
     461           0 :   digest[31] &= 0xf8;
     462             : 
     463           0 :   *r_digest = digest;
     464           0 :   return 0;
     465             : }
     466             : 
     467             : 
     468             : /**
     469             :  * _gcry_ecc_eddsa_genkey - EdDSA version of the key generation.
     470             :  *
     471             :  * @sk:  A struct to receive the secret key.
     472             :  * @E:   Parameters of the curve.
     473             :  * @ctx: Elliptic curve computation context.
     474             :  * @flags: Flags controlling aspects of the creation.
     475             :  *
     476             :  * Return: An error code.
     477             :  *
     478             :  * The only @flags bit used by this function is %PUBKEY_FLAG_TRANSIENT
     479             :  * to use a faster RNG.
     480             :  */
     481             : gpg_err_code_t
     482           0 : _gcry_ecc_eddsa_genkey (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx,
     483             :                         int flags)
     484             : {
     485             :   gpg_err_code_t rc;
     486           0 :   int b = 256/8;             /* The only size we currently support.  */
     487             :   gcry_mpi_t a, x, y;
     488             :   mpi_point_struct Q;
     489             :   gcry_random_level_t random_level;
     490             :   char *dbuf;
     491             :   size_t dlen;
     492             :   gcry_buffer_t hvec[1];
     493           0 :   unsigned char *hash_d = NULL;
     494             : 
     495           0 :   point_init (&Q);
     496           0 :   memset (hvec, 0, sizeof hvec);
     497             : 
     498           0 :   if ((flags & PUBKEY_FLAG_TRANSIENT_KEY))
     499           0 :     random_level = GCRY_STRONG_RANDOM;
     500             :   else
     501           0 :     random_level = GCRY_VERY_STRONG_RANDOM;
     502             : 
     503           0 :   a = mpi_snew (0);
     504           0 :   x = mpi_new (0);
     505           0 :   y = mpi_new (0);
     506             : 
     507             :   /* Generate a secret.  */
     508           0 :   hash_d = xtrymalloc_secure (2*b);
     509           0 :   if (!hash_d)
     510             :     {
     511           0 :       rc = gpg_err_code_from_syserror ();
     512           0 :       goto leave;
     513             :     }
     514           0 :   dlen = b;
     515           0 :   dbuf = _gcry_random_bytes_secure (dlen, random_level);
     516             : 
     517             :   /* Compute the A value.  */
     518           0 :   hvec[0].data = dbuf;
     519           0 :   hvec[0].len = dlen;
     520           0 :   rc = _gcry_md_hash_buffers (GCRY_MD_SHA512, 0, hash_d, hvec, 1);
     521           0 :   if (rc)
     522           0 :     goto leave;
     523           0 :   sk->d = _gcry_mpi_set_opaque (NULL, dbuf, dlen*8);
     524           0 :   dbuf = NULL;
     525           0 :   reverse_buffer (hash_d, 32);  /* Only the first half of the hash.  */
     526           0 :   hash_d[0] = (hash_d[0] & 0x7f) | 0x40;
     527           0 :   hash_d[31] &= 0xf8;
     528           0 :   _gcry_mpi_set_buffer (a, hash_d, 32, 0);
     529           0 :   xfree (hash_d); hash_d = NULL;
     530             :   /* log_printmpi ("ecgen         a", a); */
     531             : 
     532             :   /* Compute Q.  */
     533           0 :   _gcry_mpi_ec_mul_point (&Q, a, &E->G, ctx);
     534           0 :   if (DBG_CIPHER)
     535           0 :     log_printpnt ("ecgen      pk", &Q, ctx);
     536             : 
     537             :   /* Copy the stuff to the key structures. */
     538           0 :   sk->E.model = E->model;
     539           0 :   sk->E.dialect = E->dialect;
     540           0 :   sk->E.p = mpi_copy (E->p);
     541           0 :   sk->E.a = mpi_copy (E->a);
     542           0 :   sk->E.b = mpi_copy (E->b);
     543           0 :   point_init (&sk->E.G);
     544           0 :   point_set (&sk->E.G, &E->G);
     545           0 :   sk->E.n = mpi_copy (E->n);
     546           0 :   sk->E.h = mpi_copy (E->h);
     547           0 :   point_init (&sk->Q);
     548           0 :   point_set (&sk->Q, &Q);
     549             : 
     550             :  leave:
     551           0 :   point_free (&Q);
     552           0 :   _gcry_mpi_release (a);
     553           0 :   _gcry_mpi_release (x);
     554           0 :   _gcry_mpi_release (y);
     555           0 :   xfree (hash_d);
     556           0 :   return rc;
     557             : }
     558             : 
     559             : 
     560             : /* Compute an EdDSA signature. See:
     561             :  *   [ed25519] 23pp. (PDF) Daniel J. Bernstein, Niels Duif, Tanja
     562             :  *   Lange, Peter Schwabe, Bo-Yin Yang. High-speed high-security
     563             :  *   signatures.  Journal of Cryptographic Engineering 2 (2012), 77-89.
     564             :  *   Document ID: a1a62a2f76d23f65d622484ddd09caf8.
     565             :  *   URL: http://cr.yp.to/papers.html#ed25519. Date: 2011.09.26.
     566             :  *
     567             :  * Despite that this function requires the specification of a hash
     568             :  * algorithm, we only support what has been specified by the paper.
     569             :  * This may change in the future.  Note that we don't check the used
     570             :  * curve; the user is responsible to use Ed25519.
     571             :  *
     572             :  * Return the signature struct (r,s) from the message hash.  The caller
     573             :  * must have allocated R_R and S.
     574             :  */
     575             : gpg_err_code_t
     576           0 : _gcry_ecc_eddsa_sign (gcry_mpi_t input, ECC_secret_key *skey,
     577             :                       gcry_mpi_t r_r, gcry_mpi_t s, int hashalgo, gcry_mpi_t pk)
     578             : {
     579             :   int rc;
     580           0 :   mpi_ec_t ctx = NULL;
     581             :   int b;
     582             :   unsigned int tmp;
     583           0 :   unsigned char *digest = NULL;
     584             :   gcry_buffer_t hvec[3];
     585             :   const void *mbuf;
     586             :   size_t mlen;
     587           0 :   unsigned char *rawmpi = NULL;
     588             :   unsigned int rawmpilen;
     589           0 :   unsigned char *encpk = NULL; /* Encoded public key.  */
     590             :   unsigned int encpklen;
     591             :   mpi_point_struct I;          /* Intermediate value.  */
     592             :   mpi_point_struct Q;          /* Public key.  */
     593             :   gcry_mpi_t a, x, y, r;
     594             : 
     595           0 :   memset (hvec, 0, sizeof hvec);
     596             : 
     597           0 :   if (!mpi_is_opaque (input))
     598           0 :     return GPG_ERR_INV_DATA;
     599             : 
     600             :   /* Initialize some helpers.  */
     601           0 :   point_init (&I);
     602           0 :   point_init (&Q);
     603           0 :   a = mpi_snew (0);
     604           0 :   x = mpi_new (0);
     605           0 :   y = mpi_new (0);
     606           0 :   r = mpi_new (0);
     607           0 :   ctx = _gcry_mpi_ec_p_internal_new (skey->E.model, skey->E.dialect, 0,
     608             :                                      skey->E.p, skey->E.a, skey->E.b);
     609           0 :   b = (ctx->nbits+7)/8;
     610           0 :   if (b != 256/8) {
     611           0 :     rc = GPG_ERR_INTERNAL; /* We only support 256 bit. */
     612           0 :     goto leave;
     613             :   }
     614             : 
     615           0 :   rc = _gcry_ecc_eddsa_compute_h_d (&digest, skey->d, ctx);
     616           0 :   if (rc)
     617           0 :     goto leave;
     618           0 :   _gcry_mpi_set_buffer (a, digest, 32, 0);
     619             : 
     620             :   /* Compute the public key if it has not been supplied as optional
     621             :      parameter.  */
     622           0 :   if (pk)
     623             :     {
     624           0 :       rc = _gcry_ecc_eddsa_decodepoint (pk, ctx, &Q,  &encpk, &encpklen);
     625           0 :       if (rc)
     626           0 :         goto leave;
     627           0 :       if (DBG_CIPHER)
     628           0 :         log_printhex ("* e_pk", encpk, encpklen);
     629           0 :       if (!_gcry_mpi_ec_curve_point (&Q, ctx))
     630             :         {
     631           0 :           rc = GPG_ERR_BROKEN_PUBKEY;
     632           0 :           goto leave;
     633             :         }
     634             :     }
     635             :   else
     636             :     {
     637           0 :       _gcry_mpi_ec_mul_point (&Q, a, &skey->E.G, ctx);
     638           0 :       rc = _gcry_ecc_eddsa_encodepoint (&Q, ctx, x, y, 0, &encpk, &encpklen);
     639           0 :       if (rc)
     640           0 :         goto leave;
     641           0 :       if (DBG_CIPHER)
     642           0 :         log_printhex ("  e_pk", encpk, encpklen);
     643             :     }
     644             : 
     645             :   /* Compute R.  */
     646           0 :   mbuf = mpi_get_opaque (input, &tmp);
     647           0 :   mlen = (tmp +7)/8;
     648           0 :   if (DBG_CIPHER)
     649           0 :     log_printhex ("     m", mbuf, mlen);
     650             : 
     651           0 :   hvec[0].data = digest;
     652           0 :   hvec[0].off  = 32;
     653           0 :   hvec[0].len  = 32;
     654           0 :   hvec[1].data = (char*)mbuf;
     655           0 :   hvec[1].len  = mlen;
     656           0 :   rc = _gcry_md_hash_buffers (hashalgo, 0, digest, hvec, 2);
     657           0 :   if (rc)
     658           0 :     goto leave;
     659           0 :   reverse_buffer (digest, 64);
     660           0 :   if (DBG_CIPHER)
     661           0 :     log_printhex ("     r", digest, 64);
     662           0 :   _gcry_mpi_set_buffer (r, digest, 64, 0);
     663           0 :   _gcry_mpi_ec_mul_point (&I, r, &skey->E.G, ctx);
     664           0 :   if (DBG_CIPHER)
     665           0 :     log_printpnt ("   r", &I, ctx);
     666             : 
     667             :   /* Convert R into affine coordinates and apply encoding.  */
     668           0 :   rc = _gcry_ecc_eddsa_encodepoint (&I, ctx, x, y, 0, &rawmpi, &rawmpilen);
     669           0 :   if (rc)
     670           0 :     goto leave;
     671           0 :   if (DBG_CIPHER)
     672           0 :     log_printhex ("   e_r", rawmpi, rawmpilen);
     673             : 
     674             :   /* S = r + a * H(encodepoint(R) + encodepoint(pk) + m) mod n  */
     675           0 :   hvec[0].data = rawmpi;  /* (this is R) */
     676           0 :   hvec[0].off  = 0;
     677           0 :   hvec[0].len  = rawmpilen;
     678           0 :   hvec[1].data = encpk;
     679           0 :   hvec[1].off  = 0;
     680           0 :   hvec[1].len  = encpklen;
     681           0 :   hvec[2].data = (char*)mbuf;
     682           0 :   hvec[2].off  = 0;
     683           0 :   hvec[2].len  = mlen;
     684           0 :   rc = _gcry_md_hash_buffers (hashalgo, 0, digest, hvec, 3);
     685           0 :   if (rc)
     686           0 :     goto leave;
     687             : 
     688             :   /* No more need for RAWMPI thus we now transfer it to R_R.  */
     689           0 :   mpi_set_opaque (r_r, rawmpi, rawmpilen*8);
     690           0 :   rawmpi = NULL;
     691             : 
     692           0 :   reverse_buffer (digest, 64);
     693           0 :   if (DBG_CIPHER)
     694           0 :     log_printhex (" H(R+)", digest, 64);
     695           0 :   _gcry_mpi_set_buffer (s, digest, 64, 0);
     696           0 :   mpi_mulm (s, s, a, skey->E.n);
     697           0 :   mpi_addm (s, s, r, skey->E.n);
     698           0 :   rc = eddsa_encodempi (s, b, &rawmpi, &rawmpilen);
     699           0 :   if (rc)
     700           0 :     goto leave;
     701           0 :   if (DBG_CIPHER)
     702           0 :     log_printhex ("   e_s", rawmpi, rawmpilen);
     703           0 :   mpi_set_opaque (s, rawmpi, rawmpilen*8);
     704           0 :   rawmpi = NULL;
     705             : 
     706           0 :   rc = 0;
     707             : 
     708             :  leave:
     709           0 :   _gcry_mpi_release (a);
     710           0 :   _gcry_mpi_release (x);
     711           0 :   _gcry_mpi_release (y);
     712           0 :   _gcry_mpi_release (r);
     713           0 :   xfree (digest);
     714           0 :   _gcry_mpi_ec_free (ctx);
     715           0 :   point_free (&I);
     716           0 :   point_free (&Q);
     717           0 :   xfree (encpk);
     718           0 :   xfree (rawmpi);
     719           0 :   return rc;
     720             : }
     721             : 
     722             : 
     723             : /* Verify an EdDSA signature.  See sign_eddsa for the reference.
     724             :  * Check if R_IN and S_IN verifies INPUT.  PKEY has the curve
     725             :  * parameters and PK is the EdDSA style encoded public key.
     726             :  */
     727             : gpg_err_code_t
     728           0 : _gcry_ecc_eddsa_verify (gcry_mpi_t input, ECC_public_key *pkey,
     729             :                         gcry_mpi_t r_in, gcry_mpi_t s_in, int hashalgo,
     730             :                         gcry_mpi_t pk)
     731             : {
     732             :   int rc;
     733           0 :   mpi_ec_t ctx = NULL;
     734             :   int b;
     735             :   unsigned int tmp;
     736             :   mpi_point_struct Q;          /* Public key.  */
     737           0 :   unsigned char *encpk = NULL; /* Encoded public key.  */
     738             :   unsigned int encpklen;
     739             :   const void *mbuf, *rbuf;
     740           0 :   unsigned char *tbuf = NULL;
     741             :   size_t mlen, rlen;
     742             :   unsigned int tlen;
     743             :   unsigned char digest[64];
     744             :   gcry_buffer_t hvec[3];
     745             :   gcry_mpi_t h, s;
     746             :   mpi_point_struct Ia, Ib;
     747             : 
     748           0 :   if (!mpi_is_opaque (input) || !mpi_is_opaque (r_in) || !mpi_is_opaque (s_in))
     749           0 :     return GPG_ERR_INV_DATA;
     750           0 :   if (hashalgo != GCRY_MD_SHA512)
     751           0 :     return GPG_ERR_DIGEST_ALGO;
     752             : 
     753           0 :   point_init (&Q);
     754           0 :   point_init (&Ia);
     755           0 :   point_init (&Ib);
     756           0 :   h = mpi_new (0);
     757           0 :   s = mpi_new (0);
     758             : 
     759           0 :   ctx = _gcry_mpi_ec_p_internal_new (pkey->E.model, pkey->E.dialect, 0,
     760             :                                      pkey->E.p, pkey->E.a, pkey->E.b);
     761           0 :   b = ctx->nbits/8;
     762           0 :   if (b != 256/8)
     763           0 :     return GPG_ERR_INTERNAL; /* We only support 256 bit. */
     764             : 
     765             :   /* Decode and check the public key.  */
     766           0 :   rc = _gcry_ecc_eddsa_decodepoint (pk, ctx, &Q, &encpk, &encpklen);
     767           0 :   if (rc)
     768           0 :     goto leave;
     769           0 :   if (!_gcry_mpi_ec_curve_point (&Q, ctx))
     770             :     {
     771           0 :       rc = GPG_ERR_BROKEN_PUBKEY;
     772           0 :       goto leave;
     773             :     }
     774           0 :   if (DBG_CIPHER)
     775           0 :     log_printhex ("  e_pk", encpk, encpklen);
     776           0 :   if (encpklen != b)
     777             :     {
     778           0 :       rc = GPG_ERR_INV_LENGTH;
     779           0 :       goto leave;
     780             :     }
     781             : 
     782             :   /* Convert the other input parameters.  */
     783           0 :   mbuf = mpi_get_opaque (input, &tmp);
     784           0 :   mlen = (tmp +7)/8;
     785           0 :   if (DBG_CIPHER)
     786           0 :     log_printhex ("     m", mbuf, mlen);
     787           0 :   rbuf = mpi_get_opaque (r_in, &tmp);
     788           0 :   rlen = (tmp +7)/8;
     789           0 :   if (DBG_CIPHER)
     790           0 :     log_printhex ("     r", rbuf, rlen);
     791           0 :   if (rlen != b)
     792             :     {
     793           0 :       rc = GPG_ERR_INV_LENGTH;
     794           0 :       goto leave;
     795             :     }
     796             : 
     797             :   /* h = H(encodepoint(R) + encodepoint(pk) + m)  */
     798           0 :   hvec[0].data = (char*)rbuf;
     799           0 :   hvec[0].off  = 0;
     800           0 :   hvec[0].len  = rlen;
     801           0 :   hvec[1].data = encpk;
     802           0 :   hvec[1].off  = 0;
     803           0 :   hvec[1].len  = encpklen;
     804           0 :   hvec[2].data = (char*)mbuf;
     805           0 :   hvec[2].off  = 0;
     806           0 :   hvec[2].len  = mlen;
     807           0 :   rc = _gcry_md_hash_buffers (hashalgo, 0, digest, hvec, 3);
     808           0 :   if (rc)
     809           0 :     goto leave;
     810           0 :   reverse_buffer (digest, 64);
     811           0 :   if (DBG_CIPHER)
     812           0 :     log_printhex (" H(R+)", digest, 64);
     813           0 :   _gcry_mpi_set_buffer (h, digest, 64, 0);
     814             : 
     815             :   /* According to the paper the best way for verification is:
     816             :          encodepoint(sG - h·Q) = encodepoint(r)
     817             :      because we don't need to decode R. */
     818             :   {
     819             :     void *sbuf;
     820             :     unsigned int slen;
     821             : 
     822           0 :     sbuf = _gcry_mpi_get_opaque_copy (s_in, &tmp);
     823           0 :     slen = (tmp +7)/8;
     824           0 :     reverse_buffer (sbuf, slen);
     825           0 :     if (DBG_CIPHER)
     826           0 :       log_printhex ("     s", sbuf, slen);
     827           0 :     _gcry_mpi_set_buffer (s, sbuf, slen, 0);
     828           0 :     xfree (sbuf);
     829           0 :     if (slen != b)
     830             :       {
     831           0 :         rc = GPG_ERR_INV_LENGTH;
     832           0 :         goto leave;
     833             :       }
     834             :   }
     835             : 
     836           0 :   _gcry_mpi_ec_mul_point (&Ia, s, &pkey->E.G, ctx);
     837           0 :   _gcry_mpi_ec_mul_point (&Ib, h, &Q, ctx);
     838           0 :   _gcry_mpi_sub (Ib.x, ctx->p, Ib.x);
     839           0 :   _gcry_mpi_ec_add_points (&Ia, &Ia, &Ib, ctx);
     840           0 :   rc = _gcry_ecc_eddsa_encodepoint (&Ia, ctx, s, h, 0, &tbuf, &tlen);
     841           0 :   if (rc)
     842           0 :     goto leave;
     843           0 :   if (tlen != rlen || memcmp (tbuf, rbuf, tlen))
     844             :     {
     845           0 :       rc = GPG_ERR_BAD_SIGNATURE;
     846           0 :       goto leave;
     847             :     }
     848             : 
     849           0 :   rc = 0;
     850             : 
     851             :  leave:
     852           0 :   xfree (encpk);
     853           0 :   xfree (tbuf);
     854           0 :   _gcry_mpi_ec_free (ctx);
     855           0 :   _gcry_mpi_release (s);
     856           0 :   _gcry_mpi_release (h);
     857           0 :   point_free (&Ia);
     858           0 :   point_free (&Ib);
     859           0 :   point_free (&Q);
     860           0 :   return rc;
     861             : }

Generated by: LCOV version 1.12