LCOV - code coverage report
Current view: top level - cipher - ecc-curves.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 399 481 83.0 %
Date: 2017-03-02 16:44:37 Functions: 14 14 100.0 %

          Line data    Source code
       1             : /* ecc-curves.c  -  Elliptic Curve parameter mangement
       2             :  * Copyright (C) 2007, 2008, 2010, 2011 Free Software Foundation, Inc.
       3             :  * Copyright (C) 2013 g10 Code GmbH
       4             :  *
       5             :  * This file is part of Libgcrypt.
       6             :  *
       7             :  * Libgcrypt is free software; you can redistribute it and/or modify
       8             :  * it under the terms of the GNU Lesser General Public License as
       9             :  * published by the Free Software Foundation; either version 2.1 of
      10             :  * the License, or (at your option) any later version.
      11             :  *
      12             :  * Libgcrypt is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :  * GNU Lesser General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU Lesser General Public
      18             :  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
      19             :  */
      20             : 
      21             : #include <config.h>
      22             : #include <stdio.h>
      23             : #include <stdlib.h>
      24             : #include <string.h>
      25             : #include <errno.h>
      26             : 
      27             : #include "g10lib.h"
      28             : #include "mpi.h"
      29             : #include "cipher.h"
      30             : #include "context.h"
      31             : #include "ec-context.h"
      32             : #include "pubkey-internal.h"
      33             : #include "ecc-common.h"
      34             : 
      35             : 
      36             : /* This tables defines aliases for curve names.  */
      37             : static const struct
      38             : {
      39             :   const char *name;  /* Our name.  */
      40             :   const char *other; /* Other name. */
      41             : } curve_aliases[] =
      42             :   {
      43             :     { "Curve25519", "1.3.6.1.4.1.3029.1.5.1" },
      44             :     { "Ed25519",    "1.3.6.1.4.1.11591.15.1" },
      45             : 
      46             :     { "NIST P-192", "1.2.840.10045.3.1.1" }, /* X9.62 OID  */
      47             :     { "NIST P-192", "prime192v1" },          /* X9.62 name.  */
      48             :     { "NIST P-192", "secp192r1"  },          /* SECP name.  */
      49             :     { "NIST P-192", "nistp192"   },          /* rfc5656.  */
      50             : 
      51             :     { "NIST P-224", "secp224r1" },
      52             :     { "NIST P-224", "1.3.132.0.33" },        /* SECP OID.  */
      53             :     { "NIST P-224", "nistp224"   },          /* rfc5656.  */
      54             : 
      55             :     { "NIST P-256", "1.2.840.10045.3.1.7" }, /* From NIST SP 800-78-1.  */
      56             :     { "NIST P-256", "prime256v1" },
      57             :     { "NIST P-256", "secp256r1"  },
      58             :     { "NIST P-256", "nistp256"   },          /* rfc5656.  */
      59             : 
      60             :     { "NIST P-384", "secp384r1" },
      61             :     { "NIST P-384", "1.3.132.0.34" },
      62             :     { "NIST P-384", "nistp384"   },          /* rfc5656.  */
      63             : 
      64             :     { "NIST P-521", "secp521r1" },
      65             :     { "NIST P-521", "1.3.132.0.35" },
      66             :     { "NIST P-521", "nistp521"   },          /* rfc5656.  */
      67             : 
      68             :     { "brainpoolP160r1", "1.3.36.3.3.2.8.1.1.1" },
      69             :     { "brainpoolP192r1", "1.3.36.3.3.2.8.1.1.3" },
      70             :     { "brainpoolP224r1", "1.3.36.3.3.2.8.1.1.5" },
      71             :     { "brainpoolP256r1", "1.3.36.3.3.2.8.1.1.7" },
      72             :     { "brainpoolP320r1", "1.3.36.3.3.2.8.1.1.9" },
      73             :     { "brainpoolP384r1", "1.3.36.3.3.2.8.1.1.11"},
      74             :     { "brainpoolP512r1", "1.3.36.3.3.2.8.1.1.13"},
      75             : 
      76             :     { "GOST2001-test", "1.2.643.2.2.35.0" },
      77             :     { "GOST2001-CryptoPro-A", "1.2.643.2.2.35.1" },
      78             :     { "GOST2001-CryptoPro-B", "1.2.643.2.2.35.2" },
      79             :     { "GOST2001-CryptoPro-C", "1.2.643.2.2.35.3" },
      80             :     { "GOST2001-CryptoPro-A", "GOST2001-CryptoPro-XchA" },
      81             :     { "GOST2001-CryptoPro-C", "GOST2001-CryptoPro-XchB" },
      82             :     { "GOST2001-CryptoPro-A", "1.2.643.2.2.36.0" },
      83             :     { "GOST2001-CryptoPro-C", "1.2.643.2.2.36.1" },
      84             : 
      85             :     { "GOST2012-tc26-A", "1.2.643.7.1.2.1.2.1" },
      86             :     { "GOST2012-tc26-B", "1.2.643.7.1.2.1.2.2" },
      87             : 
      88             :     { "secp256k1", "1.3.132.0.10" },
      89             : 
      90             :     { NULL, NULL}
      91             :   };
      92             : 
      93             : 
      94             : typedef struct
      95             : {
      96             :   const char *desc;           /* Description of the curve.  */
      97             :   unsigned int nbits;         /* Number of bits.  */
      98             :   unsigned int fips:1;        /* True if this is a FIPS140-2 approved curve. */
      99             : 
     100             :   /* The model describing this curve.  This is mainly used to select
     101             :      the group equation. */
     102             :   enum gcry_mpi_ec_models model;
     103             : 
     104             :   /* The actual ECC dialect used.  This is used for curve specific
     105             :      optimizations and to select encodings etc. */
     106             :   enum ecc_dialects dialect;
     107             : 
     108             :   const char *p;              /* The prime defining the field.  */
     109             :   const char *a, *b;          /* The coefficients.  For Twisted Edwards
     110             :                                  Curves b is used for d.  For Montgomery
     111             :                                  Curves (a,b) has ((A-2)/4,B^-1).  */
     112             :   const char *n;              /* The order of the base point.  */
     113             :   const char *g_x, *g_y;      /* Base point.  */
     114             :   const char *h;              /* Cofactor.  */
     115             : } ecc_domain_parms_t;
     116             : 
     117             : 
     118             : /* This static table defines all available curves.  */
     119             : static const ecc_domain_parms_t domain_parms[] =
     120             :   {
     121             :     {
     122             :       /* (-x^2 + y^2 = 1 + dx^2y^2) */
     123             :       "Ed25519", 256, 0,
     124             :       MPI_EC_EDWARDS, ECC_DIALECT_ED25519,
     125             :       "0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED",
     126             :       "-0x01",
     127             :       "-0x2DFC9311D490018C7338BF8688861767FF8FF5B2BEBE27548A14B235ECA6874A",
     128             :       "0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED",
     129             :       "0x216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A",
     130             :       "0x6666666666666666666666666666666666666666666666666666666666666658",
     131             :       "0x08"
     132             :     },
     133             :     {
     134             :       /* (y^2 = x^3 + 486662*x^2 + x) */
     135             :       "Curve25519", 256, 0,
     136             :       MPI_EC_MONTGOMERY, ECC_DIALECT_STANDARD,
     137             :       "0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED",
     138             :       "0x01DB41",
     139             :       "0x01",
     140             :       "0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED",
     141             :       "0x0000000000000000000000000000000000000000000000000000000000000009",
     142             :       "0x20AE19A1B8A086B4E01EDD2C7748D14C923D4D7E6D7C61B229E9C5A27ECED3D9",
     143             :       "0x08"
     144             :     },
     145             : #if 0 /* No real specs yet found.  */
     146             :     {
     147             :       /* x^2 + y^2 = 1 + 3617x^2y^2 mod 2^414 - 17 */
     148             :       "Curve3617",
     149             :       "0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
     150             :       "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF",
     151             :       MPI_EC_EDWARDS, 0,
     152             :       "0x01",
     153             :       "0x0e21",
     154             :       "0x07FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEB3CC92414CF"
     155             :       "706022B36F1C0338AD63CF181B0E71A5E106AF79",
     156             :       "0x1A334905141443300218C0631C326E5FCD46369F44C03EC7F57FF35498A4AB4D"
     157             :       "6D6BA111301A73FAA8537C64C4FD3812F3CBC595",
     158             :       "0x22",
     159             :       "0x08"
     160             :     },
     161             : #endif /*0*/
     162             :     {
     163             :       "NIST P-192", 192, 0,
     164             :       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
     165             :       "0xfffffffffffffffffffffffffffffffeffffffffffffffff",
     166             :       "0xfffffffffffffffffffffffffffffffefffffffffffffffc",
     167             :       "0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1",
     168             :       "0xffffffffffffffffffffffff99def836146bc9b1b4d22831",
     169             : 
     170             :       "0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012",
     171             :       "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811",
     172             :       "0x01"
     173             :     },
     174             :     {
     175             :       "NIST P-224", 224, 1,
     176             :       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
     177             :       "0xffffffffffffffffffffffffffffffff000000000000000000000001",
     178             :       "0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe",
     179             :       "0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4",
     180             :       "0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d" ,
     181             : 
     182             :       "0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
     183             :       "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34",
     184             :       "0x01"
     185             :     },
     186             :     {
     187             :       "NIST P-256", 256, 1,
     188             :       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
     189             :       "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
     190             :       "0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc",
     191             :       "0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
     192             :       "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
     193             : 
     194             :       "0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
     195             :       "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5",
     196             :       "0x01"
     197             :     },
     198             :     {
     199             :       "NIST P-384", 384, 1,
     200             :       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
     201             :       "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
     202             :       "ffffffff0000000000000000ffffffff",
     203             :       "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
     204             :       "ffffffff0000000000000000fffffffc",
     205             :       "0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875a"
     206             :       "c656398d8a2ed19d2a85c8edd3ec2aef",
     207             :       "0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf"
     208             :       "581a0db248b0a77aecec196accc52973",
     209             : 
     210             :       "0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a38"
     211             :       "5502f25dbf55296c3a545e3872760ab7",
     212             :       "0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c0"
     213             :       "0a60b1ce1d7e819d7a431d7c90ea0e5f",
     214             :       "0x01"
     215             :     },
     216             :     {
     217             :       "NIST P-521", 521, 1,
     218             :       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
     219             :       "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
     220             :       "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
     221             :       "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
     222             :       "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc",
     223             :       "0x051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef10"
     224             :       "9e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00",
     225             :       "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
     226             :       "ffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409",
     227             : 
     228             :       "0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d"
     229             :       "3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66",
     230             :       "0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e"
     231             :       "662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650",
     232             :       "0x01"
     233             :     },
     234             : 
     235             :     { "brainpoolP160r1", 160, 0,
     236             :       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
     237             :       "0xe95e4a5f737059dc60dfc7ad95b3d8139515620f",
     238             :       "0x340e7be2a280eb74e2be61bada745d97e8f7c300",
     239             :       "0x1e589a8595423412134faa2dbdec95c8d8675e58",
     240             :       "0xe95e4a5f737059dc60df5991d45029409e60fc09",
     241             :       "0xbed5af16ea3f6a4f62938c4631eb5af7bdbcdbc3",
     242             :       "0x1667cb477a1a8ec338f94741669c976316da6321",
     243             :       "0x01"
     244             :     },
     245             : 
     246             :     { "brainpoolP192r1", 192, 0,
     247             :       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
     248             :       "0xc302f41d932a36cda7a3463093d18db78fce476de1a86297",
     249             :       "0x6a91174076b1e0e19c39c031fe8685c1cae040e5c69a28ef",
     250             :       "0x469a28ef7c28cca3dc721d044f4496bcca7ef4146fbf25c9",
     251             :       "0xc302f41d932a36cda7a3462f9e9e916b5be8f1029ac4acc1",
     252             :       "0xc0a0647eaab6a48753b033c56cb0f0900a2f5c4853375fd6",
     253             :       "0x14b690866abd5bb88b5f4828c1490002e6773fa2fa299b8f",
     254             :       "0x01"
     255             :     },
     256             : 
     257             :     { "brainpoolP224r1", 224, 0,
     258             :       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
     259             :       "0xd7c134aa264366862a18302575d1d787b09f075797da89f57ec8c0ff",
     260             :       "0x68a5e62ca9ce6c1c299803a6c1530b514e182ad8b0042a59cad29f43",
     261             :       "0x2580f63ccfe44138870713b1a92369e33e2135d266dbb372386c400b",
     262             :       "0xd7c134aa264366862a18302575d0fb98d116bc4b6ddebca3a5a7939f",
     263             :       "0x0d9029ad2c7e5cf4340823b2a87dc68c9e4ce3174c1e6efdee12c07d",
     264             :       "0x58aa56f772c0726f24c6b89e4ecdac24354b9e99caa3f6d3761402cd",
     265             :       "0x01"
     266             :     },
     267             : 
     268             :     { "brainpoolP256r1", 256, 0,
     269             :       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
     270             :       "0xa9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377",
     271             :       "0x7d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9",
     272             :       "0x26dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b6",
     273             :       "0xa9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a7",
     274             :       "0x8bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262",
     275             :       "0x547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997",
     276             :       "0x01"
     277             :     },
     278             : 
     279             :     { "brainpoolP320r1", 320, 0,
     280             :       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
     281             :       "0xd35e472036bc4fb7e13c785ed201e065f98fcfa6f6f40def4f92b9ec7893ec28"
     282             :       "fcd412b1f1b32e27",
     283             :       "0x3ee30b568fbab0f883ccebd46d3f3bb8a2a73513f5eb79da66190eb085ffa9f4"
     284             :       "92f375a97d860eb4",
     285             :       "0x520883949dfdbc42d3ad198640688a6fe13f41349554b49acc31dccd88453981"
     286             :       "6f5eb4ac8fb1f1a6",
     287             :       "0xd35e472036bc4fb7e13c785ed201e065f98fcfa5b68f12a32d482ec7ee8658e9"
     288             :       "8691555b44c59311",
     289             :       "0x43bd7e9afb53d8b85289bcc48ee5bfe6f20137d10a087eb6e7871e2a10a599c7"
     290             :       "10af8d0d39e20611",
     291             :       "0x14fdd05545ec1cc8ab4093247f77275e0743ffed117182eaa9c77877aaac6ac7"
     292             :       "d35245d1692e8ee1",
     293             :       "0x01"
     294             :     },
     295             : 
     296             :     { "brainpoolP384r1", 384, 0,
     297             :       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
     298             :       "0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b412b1da197fb71123"
     299             :       "acd3a729901d1a71874700133107ec53",
     300             :       "0x7bc382c63d8c150c3c72080ace05afa0c2bea28e4fb22787139165efba91f90f"
     301             :       "8aa5814a503ad4eb04a8c7dd22ce2826",
     302             :       "0x04a8c7dd22ce28268b39b55416f0447c2fb77de107dcd2a62e880ea53eeb62d5"
     303             :       "7cb4390295dbc9943ab78696fa504c11",
     304             :       "0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b31f166e6cac0425a7"
     305             :       "cf3ab6af6b7fc3103b883202e9046565",
     306             :       "0x1d1c64f068cf45ffa2a63a81b7c13f6b8847a3e77ef14fe3db7fcafe0cbd10e8"
     307             :       "e826e03436d646aaef87b2e247d4af1e",
     308             :       "0x8abe1d7520f9c2a45cb1eb8e95cfd55262b70b29feec5864e19c054ff9912928"
     309             :       "0e4646217791811142820341263c5315",
     310             :       "0x01"
     311             :     },
     312             : 
     313             :     { "brainpoolP512r1", 512, 0,
     314             :       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
     315             :       "0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330871"
     316             :       "7d4d9b009bc66842aecda12ae6a380e62881ff2f2d82c68528aa6056583a48f3",
     317             :       "0x7830a3318b603b89e2327145ac234cc594cbdd8d3df91610a83441caea9863bc"
     318             :       "2ded5d5aa8253aa10a2ef1c98b9ac8b57f1117a72bf2c7b9e7c1ac4d77fc94ca",
     319             :       "0x3df91610a83441caea9863bc2ded5d5aa8253aa10a2ef1c98b9ac8b57f1117a7"
     320             :       "2bf2c7b9e7c1ac4d77fc94cadc083e67984050b75ebae5dd2809bd638016f723",
     321             :       "0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330870"
     322             :       "553e5c414ca92619418661197fac10471db1d381085ddaddb58796829ca90069",
     323             :       "0x81aee4bdd82ed9645a21322e9c4c6a9385ed9f70b5d916c1b43b62eef4d0098e"
     324             :       "ff3b1f78e2d0d48d50d1687b93b97d5f7c6d5047406a5e688b352209bcb9f822",
     325             :       "0x7dde385d566332ecc0eabfa9cf7822fdf209f70024a57b1aa000c55b881f8111"
     326             :       "b2dcde494a5f485e5bca4bd88a2763aed1ca2b2fa8f0540678cd1e0f3ad80892",
     327             :       "0x01"
     328             :     },
     329             :     {
     330             :       "GOST2001-test", 256, 0,
     331             :       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
     332             :       "0x8000000000000000000000000000000000000000000000000000000000000431",
     333             :       "0x0000000000000000000000000000000000000000000000000000000000000007",
     334             :       "0x5fbff498aa938ce739b8e022fbafef40563f6e6a3472fc2a514c0ce9dae23b7e",
     335             :       "0x8000000000000000000000000000000150fe8a1892976154c59cfc193accf5b3",
     336             : 
     337             :       "0x0000000000000000000000000000000000000000000000000000000000000002",
     338             :       "0x08e2a8a0e65147d4bd6316030e16d19c85c97f0a9ca267122b96abbcea7e8fc8",
     339             :       "0x01"
     340             :     },
     341             :     {
     342             :       "GOST2001-CryptoPro-A", 256, 0,
     343             :       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
     344             :       "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd97",
     345             :       "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd94",
     346             :       "0x00000000000000000000000000000000000000000000000000000000000000a6",
     347             :       "0xffffffffffffffffffffffffffffffff6c611070995ad10045841b09b761b893",
     348             :       "0x0000000000000000000000000000000000000000000000000000000000000001",
     349             :       "0x8d91e471e0989cda27df505a453f2b7635294f2ddf23e3b122acc99c9e9f1e14",
     350             :       "0x01"
     351             :     },
     352             :     {
     353             :       "GOST2001-CryptoPro-B", 256, 0,
     354             :       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
     355             :       "0x8000000000000000000000000000000000000000000000000000000000000c99",
     356             :       "0x8000000000000000000000000000000000000000000000000000000000000c96",
     357             :       "0x3e1af419a269a5f866a7d3c25c3df80ae979259373ff2b182f49d4ce7e1bbc8b",
     358             :       "0x800000000000000000000000000000015f700cfff1a624e5e497161bcc8a198f",
     359             :       "0x0000000000000000000000000000000000000000000000000000000000000001",
     360             :       "0x3fa8124359f96680b83d1c3eb2c070e5c545c9858d03ecfb744bf8d717717efc",
     361             :       "0x01"
     362             :     },
     363             :     {
     364             :       "GOST2001-CryptoPro-C", 256, 0,
     365             :       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
     366             :       "0x9b9f605f5a858107ab1ec85e6b41c8aacf846e86789051d37998f7b9022d759b",
     367             :       "0x9b9f605f5a858107ab1ec85e6b41c8aacf846e86789051d37998f7b9022d7598",
     368             :       "0x000000000000000000000000000000000000000000000000000000000000805a",
     369             :       "0x9b9f605f5a858107ab1ec85e6b41c8aa582ca3511eddfb74f02f3a6598980bb9",
     370             :       "0x0000000000000000000000000000000000000000000000000000000000000000",
     371             :       "0x41ece55743711a8c3cbf3783cd08c0ee4d4dc440d4641a8f366e550dfdb3bb67",
     372             :       "0x01"
     373             :     },
     374             :     {
     375             :       "GOST2012-test", 511, 0,
     376             :       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
     377             :       "0x4531acd1fe0023c7550d267b6b2fee80922b14b2ffb90f04d4eb7c09b5d2d15d"
     378             :       "f1d852741af4704a0458047e80e4546d35b8336fac224dd81664bbf528be6373",
     379             :       "0x0000000000000000000000000000000000000000000000000000000000000007",
     380             :       "0x1cff0806a31116da29d8cfa54e57eb748bc5f377e49400fdd788b649eca1ac4"
     381             :       "361834013b2ad7322480a89ca58e0cf74bc9e540c2add6897fad0a3084f302adc",
     382             :       "0x4531acd1fe0023c7550d267b6b2fee80922b14b2ffb90f04d4eb7c09b5d2d15d"
     383             :       "a82f2d7ecb1dbac719905c5eecc423f1d86e25edbe23c595d644aaf187e6e6df",
     384             : 
     385             :       "0x24d19cc64572ee30f396bf6ebbfd7a6c5213b3b3d7057cc825f91093a68cd762"
     386             :       "fd60611262cd838dc6b60aa7eee804e28bc849977fac33b4b530f1b120248a9a",
     387             :       "0x2bb312a43bd2ce6e0d020613c857acddcfbf061e91e5f2c3f32447c259f39b2"
     388             :       "c83ab156d77f1496bf7eb3351e1ee4e43dc1a18b91b24640b6dbb92cb1add371e",
     389             :       "0x01"
     390             :     },
     391             :     {
     392             :       "GOST2012-tc26-A", 512, 0,
     393             :       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
     394             :       "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
     395             :         "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc7",
     396             :       "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
     397             :         "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc4",
     398             :       "0xe8c2505dedfc86ddc1bd0b2b6667f1da34b82574761cb0e879bd081cfd0b6265"
     399             :         "ee3cb090f30d27614cb4574010da90dd862ef9d4ebee4761503190785a71c760",
     400             :       "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
     401             :         "27e69532f48d89116ff22b8d4e0560609b4b38abfad2b85dcacdb1411f10b275",
     402             :       "0x0000000000000000000000000000000000000000000000000000000000000000"
     403             :         "0000000000000000000000000000000000000000000000000000000000000003",
     404             :       "0x7503cfe87a836ae3a61b8816e25450e6ce5e1c93acf1abc1778064fdcbefa921"
     405             :         "df1626be4fd036e93d75e6a50e3a41e98028fe5fc235f5b889a589cb5215f2a4",
     406             :       "0x01"
     407             :     },
     408             :     {
     409             :       "GOST2012-tc26-B", 512, 0,
     410             :       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
     411             :       "0x8000000000000000000000000000000000000000000000000000000000000000"
     412             :         "000000000000000000000000000000000000000000000000000000000000006f",
     413             :       "0x8000000000000000000000000000000000000000000000000000000000000000"
     414             :         "000000000000000000000000000000000000000000000000000000000000006c",
     415             :       "0x687d1b459dc841457e3e06cf6f5e2517b97c7d614af138bcbf85dc806c4b289f"
     416             :         "3e965d2db1416d217f8b276fad1ab69c50f78bee1fa3106efb8ccbc7c5140116",
     417             :       "0x8000000000000000000000000000000000000000000000000000000000000001"
     418             :         "49a1ec142565a545acfdb77bd9d40cfa8b996712101bea0ec6346c54374f25bd",
     419             :       "0x0000000000000000000000000000000000000000000000000000000000000000"
     420             :         "0000000000000000000000000000000000000000000000000000000000000002",
     421             :       "0x1a8f7eda389b094c2c071e3647a8940f3c123b697578c213be6dd9e6c8ec7335"
     422             :         "dcb228fd1edf4a39152cbcaaf8c0398828041055f94ceeec7e21340780fe41bd",
     423             :       "0x01"
     424             :     },
     425             : 
     426             :     {
     427             :       "secp256k1", 256, 0,
     428             :       MPI_EC_WEIERSTRASS, ECC_DIALECT_STANDARD,
     429             :       "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F",
     430             :       "0x0000000000000000000000000000000000000000000000000000000000000000",
     431             :       "0x0000000000000000000000000000000000000000000000000000000000000007",
     432             :       "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141",
     433             :       "0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798",
     434             :       "0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8",
     435             :       "0x01"
     436             :     },
     437             : 
     438             :     { NULL, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL }
     439             :   };
     440             : 
     441             : 
     442             : 
     443             : 
     444             : /* Return a copy of POINT.  */
     445             : static gcry_mpi_point_t
     446          12 : point_copy (gcry_mpi_point_t point)
     447             : {
     448             :   gcry_mpi_point_t newpoint;
     449             : 
     450          12 :   if (point)
     451             :     {
     452          11 :       newpoint = mpi_point_new (0);
     453          11 :       point_set (newpoint, point);
     454             :     }
     455             :   else
     456           1 :     newpoint = NULL;
     457          12 :   return newpoint;
     458             : }
     459             : 
     460             : 
     461             : /* Helper to scan a hex string. */
     462             : static gcry_mpi_t
     463       17425 : scanval (const char *string)
     464             : {
     465             :   gpg_err_code_t rc;
     466             :   gcry_mpi_t val;
     467             : 
     468       17425 :   rc = _gcry_mpi_scan (&val, GCRYMPI_FMT_HEX, string, 0, NULL);
     469       17425 :   if (rc)
     470           0 :     log_fatal ("scanning ECC parameter failed: %s\n", gpg_strerror (rc));
     471       17425 :   return val;
     472             : }
     473             : 
     474             : 
     475             : /* Return the index of the domain_parms table for a curve with NAME.
     476             :    Return -1 if not found.  */
     477             : static int
     478        3739 : find_domain_parms_idx (const char *name)
     479             : {
     480             :   int idx, aliasno;
     481             : 
     482             :   /* First check our native curves.  */
     483        9397 :   for (idx = 0; domain_parms[idx].desc; idx++)
     484        9301 :     if (!strcmp (name, domain_parms[idx].desc))
     485        3643 :       return idx;
     486             : 
     487             :   /* If not found consult the alias table.  */
     488          96 :   if (!domain_parms[idx].desc)
     489             :     {
     490         904 :       for (aliasno = 0; curve_aliases[aliasno].name; aliasno++)
     491         904 :         if (!strcmp (name, curve_aliases[aliasno].other))
     492          96 :           break;
     493          96 :       if (curve_aliases[aliasno].name)
     494             :         {
     495         386 :           for (idx = 0; domain_parms[idx].desc; idx++)
     496         386 :             if (!strcmp (curve_aliases[aliasno].name, domain_parms[idx].desc))
     497          96 :               return idx;
     498             :         }
     499             :     }
     500             : 
     501           0 :   return -1;
     502             : }
     503             : 
     504             : 
     505             : /* Generate the crypto system setup.  This function takes the NAME of
     506             :    a curve or the desired number of bits and stores at R_CURVE the
     507             :    parameters of the named curve or those of a suitable curve.  If
     508             :    R_NBITS is not NULL, the chosen number of bits is stored there.
     509             :    NULL may be given for R_CURVE, if the value is not required and for
     510             :    example only a quick test for availability is desired.  Note that
     511             :    the curve fields should be initialized to zero because fields which
     512             :    are not NULL are skipped.  */
     513             : gpg_err_code_t
     514        3736 : _gcry_ecc_fill_in_curve (unsigned int nbits, const char *name,
     515             :                          elliptic_curve_t *curve, unsigned int *r_nbits)
     516             : {
     517             :   int idx;
     518        3736 :   const char *resname = NULL; /* Set to a found curve name.  */
     519             : 
     520        3736 :   if (name)
     521        3731 :     idx = find_domain_parms_idx (name);
     522             :   else
     523             :     {
     524          25 :       for (idx = 0; domain_parms[idx].desc; idx++)
     525          25 :         if (nbits == domain_parms[idx].nbits
     526           7 :             && domain_parms[idx].model == MPI_EC_WEIERSTRASS)
     527           5 :           break;
     528           5 :       if (!domain_parms[idx].desc)
     529           0 :         idx = -1;
     530             :     }
     531        3736 :   if (idx < 0)
     532           0 :     return GPG_ERR_UNKNOWN_CURVE;
     533             : 
     534        3736 :   resname = domain_parms[idx].desc;
     535             : 
     536             :   /* In fips mode we only support NIST curves.  Note that it is
     537             :      possible to bypass this check by specifying the curve parameters
     538             :      directly.  */
     539        3736 :   if (fips_mode () && !domain_parms[idx].fips )
     540           0 :     return GPG_ERR_NOT_SUPPORTED;
     541             : 
     542        3736 :   switch (domain_parms[idx].model)
     543             :     {
     544             :     case MPI_EC_WEIERSTRASS:
     545             :     case MPI_EC_EDWARDS:
     546             :     case MPI_EC_MONTGOMERY:
     547        3736 :       break;
     548             :     default:
     549           0 :       return GPG_ERR_BUG;
     550             :     }
     551             : 
     552             : 
     553        3736 :   if (r_nbits)
     554        1275 :     *r_nbits = domain_parms[idx].nbits;
     555             : 
     556        3736 :   if (curve)
     557             :     {
     558        2481 :       curve->model = domain_parms[idx].model;
     559        2481 :       curve->dialect = domain_parms[idx].dialect;
     560        2481 :       if (!curve->p)
     561        2473 :         curve->p = scanval (domain_parms[idx].p);
     562        2481 :       if (!curve->a)
     563             :         {
     564        2473 :           curve->a = scanval (domain_parms[idx].a);
     565        2473 :           if (curve->a->sign)
     566        2093 :             mpi_add (curve->a, curve->p, curve->a);
     567             :         }
     568        2481 :       if (!curve->b)
     569             :         {
     570        2473 :           curve->b = scanval (domain_parms[idx].b);
     571        2473 :           if (curve->b->sign)
     572        2093 :             mpi_add (curve->b, curve->p, curve->b);
     573             :         }
     574        2481 :       if (!curve->n)
     575        2473 :         curve->n = scanval (domain_parms[idx].n);
     576        2481 :       if (!curve->h)
     577        2473 :         curve->h = scanval (domain_parms[idx].h);
     578        2481 :       if (!curve->G.x)
     579        2481 :         curve->G.x = scanval (domain_parms[idx].g_x);
     580        2481 :       if (!curve->G.y)
     581        2481 :         curve->G.y = scanval (domain_parms[idx].g_y);
     582        2481 :       if (!curve->G.z)
     583        2481 :         curve->G.z = mpi_alloc_set_ui (1);
     584        2481 :       if (!curve->name)
     585        2481 :         curve->name = resname;
     586             :     }
     587             : 
     588        3736 :   return 0;
     589             : }
     590             : 
     591             : 
     592             : /* Give the name of the curve NAME, store the curve parameters into P,
     593             :    A, B, G, N, and H if they point to NULL value.  Note that G is returned
     594             :    in standard uncompressed format.  Also update MODEL and DIALECT if
     595             :    they are not NULL. */
     596             : gpg_err_code_t
     597           8 : _gcry_ecc_update_curve_param (const char *name,
     598             :                               enum gcry_mpi_ec_models *model,
     599             :                               enum ecc_dialects *dialect,
     600             :                               gcry_mpi_t *p, gcry_mpi_t *a, gcry_mpi_t *b,
     601             :                               gcry_mpi_t *g, gcry_mpi_t *n, gcry_mpi_t *h)
     602             : {
     603             :   int idx;
     604             : 
     605           8 :   idx = find_domain_parms_idx (name);
     606           8 :   if (idx < 0)
     607           0 :     return GPG_ERR_UNKNOWN_CURVE;
     608             : 
     609           8 :   if (g)
     610             :     {
     611             :       char *buf;
     612             :       size_t len;
     613             : 
     614           8 :       len = 4;
     615           8 :       len += strlen (domain_parms[idx].g_x+2);
     616           8 :       len += strlen (domain_parms[idx].g_y+2);
     617           8 :       len++;
     618           8 :       buf = xtrymalloc (len);
     619           8 :       if (!buf)
     620           0 :         return gpg_err_code_from_syserror ();
     621           8 :       strcpy (stpcpy (stpcpy (buf, "0x04"), domain_parms[idx].g_x+2),
     622           8 :               domain_parms[idx].g_y+2);
     623           8 :       _gcry_mpi_release (*g);
     624           8 :       *g = scanval (buf);
     625           8 :       xfree (buf);
     626             :     }
     627           8 :   if (model)
     628           8 :     *model = domain_parms[idx].model;
     629           8 :   if (dialect)
     630           8 :     *dialect = domain_parms[idx].dialect;
     631           8 :   if (p)
     632             :     {
     633           8 :       _gcry_mpi_release (*p);
     634           8 :       *p = scanval (domain_parms[idx].p);
     635             :     }
     636           8 :   if (a)
     637             :     {
     638           8 :       _gcry_mpi_release (*a);
     639           8 :       *a = scanval (domain_parms[idx].a);
     640             :     }
     641           8 :   if (b)
     642             :     {
     643           8 :       _gcry_mpi_release (*b);
     644           8 :       *b = scanval (domain_parms[idx].b);
     645             :     }
     646           8 :   if (n)
     647             :     {
     648           8 :       _gcry_mpi_release (*n);
     649           8 :       *n = scanval (domain_parms[idx].n);
     650             :     }
     651           8 :   if (h)
     652             :     {
     653           8 :       _gcry_mpi_release (*h);
     654           8 :       *h = scanval (domain_parms[idx].h);
     655             :     }
     656           8 :   return 0;
     657             : }
     658             : 
     659             : 
     660             : /* Return the name matching the parameters in PKEY.  This works only
     661             :    with curves described by the Weierstrass equation. */
     662             : const char *
     663          28 : _gcry_ecc_get_curve (gcry_sexp_t keyparms, int iterator, unsigned int *r_nbits)
     664             : {
     665             :   gpg_err_code_t rc;
     666          28 :   const char *result = NULL;
     667             :   elliptic_curve_t E;
     668          28 :   gcry_mpi_t mpi_g = NULL;
     669          28 :   gcry_mpi_t tmp = NULL;
     670             :   int idx;
     671             : 
     672          28 :   memset (&E, 0, sizeof E);
     673             : 
     674          28 :   if (r_nbits)
     675          25 :     *r_nbits = 0;
     676             : 
     677          28 :   if (!keyparms)
     678             :     {
     679          24 :       idx = iterator;
     680          24 :       if (idx >= 0 && idx < DIM (domain_parms))
     681             :         {
     682          23 :           result = domain_parms[idx].desc;
     683          23 :           if (r_nbits)
     684          23 :             *r_nbits = domain_parms[idx].nbits;
     685             :         }
     686          24 :       return result;
     687             :     }
     688             : 
     689             : 
     690             :   /*
     691             :    * Extract the curve parameters..
     692             :    */
     693           4 :   rc = gpg_err_code (sexp_extract_param (keyparms, NULL, "-pabgnh",
     694             :                                          &E.p, &E.a, &E.b, &mpi_g, &E.n, &E.h,
     695             :                                          NULL));
     696           4 :   if (rc == GPG_ERR_NO_OBJ)
     697             :     {
     698             :       /* This might be the second use case of checking whether a
     699             :          specific curve given by name is supported.  */
     700             :       gcry_sexp_t l1;
     701             :       char *name;
     702             : 
     703           0 :       l1 = sexp_find_token (keyparms, "curve", 5);
     704           0 :       if (!l1)
     705           0 :         goto leave;  /* No curve name parameter.  */
     706             : 
     707           0 :       name = sexp_nth_string (l1, 1);
     708           0 :       sexp_release (l1);
     709           0 :       if (!name)
     710           0 :         goto leave;  /* Name missing or out of core. */
     711             : 
     712           0 :       idx = find_domain_parms_idx (name);
     713           0 :       xfree (name);
     714           0 :       if (idx >= 0)  /* Curve found.  */
     715             :         {
     716           0 :           result = domain_parms[idx].desc;
     717           0 :           if (r_nbits)
     718           0 :             *r_nbits = domain_parms[idx].nbits;
     719             :         }
     720           0 :       return result;
     721             :     }
     722             : 
     723           4 :   if (rc)
     724           0 :     goto leave;
     725             : 
     726           4 :   if (mpi_g)
     727             :     {
     728           4 :       _gcry_mpi_point_init (&E.G);
     729           4 :       if (_gcry_ecc_os2ec (&E.G, mpi_g))
     730           0 :         goto leave;
     731             :     }
     732             : 
     733          26 :   for (idx = 0; domain_parms[idx].desc; idx++)
     734             :     {
     735          26 :       mpi_free (tmp);
     736          26 :       tmp = scanval (domain_parms[idx].p);
     737          26 :       if (!mpi_cmp (tmp, E.p))
     738             :         {
     739           4 :           mpi_free (tmp);
     740           4 :           tmp = scanval (domain_parms[idx].a);
     741           4 :           if (!mpi_cmp (tmp, E.a))
     742             :             {
     743           4 :               mpi_free (tmp);
     744           4 :               tmp = scanval (domain_parms[idx].b);
     745           4 :               if (!mpi_cmp (tmp, E.b))
     746             :                 {
     747           4 :                   mpi_free (tmp);
     748           4 :                   tmp = scanval (domain_parms[idx].n);
     749           4 :                   if (!mpi_cmp (tmp, E.n))
     750             :                     {
     751           4 :                       mpi_free (tmp);
     752           4 :                       tmp = scanval (domain_parms[idx].h);
     753           4 :                       if (!mpi_cmp (tmp, E.h))
     754             :                         {
     755           4 :                           mpi_free (tmp);
     756           4 :                           tmp = scanval (domain_parms[idx].g_x);
     757           4 :                           if (!mpi_cmp (tmp, E.G.x))
     758             :                             {
     759           4 :                               mpi_free (tmp);
     760           4 :                               tmp = scanval (domain_parms[idx].g_y);
     761           4 :                               if (!mpi_cmp (tmp, E.G.y))
     762             :                                 {
     763           4 :                                   result = domain_parms[idx].desc;
     764           4 :                                   if (r_nbits)
     765           2 :                                     *r_nbits = domain_parms[idx].nbits;
     766           4 :                                   goto leave;
     767             :                                 }
     768             :                             }
     769             :                         }
     770             :                     }
     771             :                 }
     772             :             }
     773             :         }
     774             :     }
     775             : 
     776             :  leave:
     777           4 :   _gcry_mpi_release (tmp);
     778           4 :   _gcry_mpi_release (E.p);
     779           4 :   _gcry_mpi_release (E.a);
     780           4 :   _gcry_mpi_release (E.b);
     781           4 :   _gcry_mpi_release (mpi_g);
     782           4 :   _gcry_mpi_point_free_parts (&E.G);
     783           4 :   _gcry_mpi_release (E.n);
     784           4 :   _gcry_mpi_release (E.h);
     785           4 :   return result;
     786             : }
     787             : 
     788             : 
     789             : /* Helper to extract an MPI from key parameters.  */
     790             : static gpg_err_code_t
     791          42 : mpi_from_keyparam (gcry_mpi_t *r_a, gcry_sexp_t keyparam, const char *name)
     792             : {
     793          42 :   gcry_err_code_t ec = 0;
     794             :   gcry_sexp_t l1;
     795             : 
     796          42 :   l1 = sexp_find_token (keyparam, name, 0);
     797          42 :   if (l1)
     798             :     {
     799           5 :       *r_a = sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
     800           5 :       sexp_release (l1);
     801           5 :       if (!*r_a)
     802           0 :         ec = GPG_ERR_INV_OBJ;
     803             :     }
     804          42 :   return ec;
     805             : }
     806             : 
     807             : /* Helper to extract a point from key parameters.  If no parameter
     808             :    with NAME is found, the functions tries to find a non-encoded point
     809             :    by appending ".x", ".y" and ".z" to NAME.  ".z" is in this case
     810             :    optional and defaults to 1.  EC is the context which at this point
     811             :    may not be fully initialized. */
     812             : static gpg_err_code_t
     813           8 : point_from_keyparam (gcry_mpi_point_t *r_a,
     814             :                      gcry_sexp_t keyparam, const char *name, mpi_ec_t ec)
     815             : {
     816             :   gcry_err_code_t rc;
     817             :   gcry_sexp_t l1;
     818             :   gcry_mpi_point_t point;
     819             : 
     820           8 :   l1 = sexp_find_token (keyparam, name, 0);
     821           8 :   if (l1)
     822             :     {
     823             :       gcry_mpi_t a;
     824             : 
     825           2 :       a = sexp_nth_mpi (l1, 1, GCRYMPI_FMT_OPAQUE);
     826           2 :       sexp_release (l1);
     827           2 :       if (!a)
     828           0 :         return GPG_ERR_INV_OBJ;
     829             : 
     830           2 :       point = mpi_point_new (0);
     831           2 :       if (ec && ec->dialect == ECC_DIALECT_ED25519)
     832           1 :         rc = _gcry_ecc_eddsa_decodepoint (a, ec, point, NULL, NULL);
     833             :       else
     834           1 :         rc = _gcry_ecc_os2ec (point, a);
     835           2 :       mpi_free (a);
     836           2 :       if (rc)
     837             :         {
     838           0 :           mpi_point_release (point);
     839           0 :           return rc;
     840             :         }
     841             :     }
     842             :   else
     843             :     {
     844             :       char *tmpname;
     845           6 :       gcry_mpi_t x = NULL;
     846           6 :       gcry_mpi_t y = NULL;
     847           6 :       gcry_mpi_t z = NULL;
     848             : 
     849           6 :       tmpname = xtrymalloc (strlen (name) + 2 + 1);
     850           6 :       if (!tmpname)
     851           0 :         return gpg_err_code_from_syserror ();
     852           6 :       strcpy (stpcpy (tmpname, name), ".x");
     853           6 :       rc = mpi_from_keyparam (&x, keyparam, tmpname);
     854           6 :       if (rc)
     855             :         {
     856           0 :           xfree (tmpname);
     857           0 :           return rc;
     858             :         }
     859           6 :       strcpy (stpcpy (tmpname, name), ".y");
     860           6 :       rc = mpi_from_keyparam (&y, keyparam, tmpname);
     861           6 :       if (rc)
     862             :         {
     863           0 :           mpi_free (x);
     864           0 :           xfree (tmpname);
     865           0 :           return rc;
     866             :         }
     867           6 :       strcpy (stpcpy (tmpname, name), ".z");
     868           6 :       rc = mpi_from_keyparam (&z, keyparam, tmpname);
     869           6 :       if (rc)
     870             :         {
     871           0 :           mpi_free (y);
     872           0 :           mpi_free (x);
     873           0 :           xfree (tmpname);
     874           0 :           return rc;
     875             :         }
     876           6 :       if (!z)
     877           6 :         z = mpi_set_ui (NULL, 1);
     878           6 :       if (x && y)
     879           0 :         point = mpi_point_snatch_set (NULL, x, y, z);
     880             :       else
     881             :         {
     882           6 :           mpi_free (x);
     883           6 :           mpi_free (y);
     884           6 :           mpi_free (z);
     885           6 :           point = NULL;
     886             :         }
     887           6 :       xfree (tmpname);
     888             :     }
     889             : 
     890           8 :   if (point)
     891           2 :     *r_a = point;
     892           8 :   return 0;
     893             : }
     894             : 
     895             : 
     896             : /* This function creates a new context for elliptic curve operations.
     897             :    Either KEYPARAM or CURVENAME must be given.  If both are given and
     898             :    KEYPARAM has no curve parameter, CURVENAME is used to add missing
     899             :    parameters.  On success 0 is returned and the new context stored at
     900             :    R_CTX.  On error NULL is stored at R_CTX and an error code is
     901             :    returned.  The context needs to be released using
     902             :    gcry_ctx_release.  */
     903             : gpg_err_code_t
     904          16 : _gcry_mpi_ec_new (gcry_ctx_t *r_ctx,
     905             :                   gcry_sexp_t keyparam, const char *curvename)
     906             : {
     907             :   gpg_err_code_t errc;
     908          16 :   gcry_ctx_t ctx = NULL;
     909          16 :   enum gcry_mpi_ec_models model = MPI_EC_WEIERSTRASS;
     910          16 :   enum ecc_dialects dialect = ECC_DIALECT_STANDARD;
     911          16 :   gcry_mpi_t p = NULL;
     912          16 :   gcry_mpi_t a = NULL;
     913          16 :   gcry_mpi_t b = NULL;
     914          16 :   gcry_mpi_point_t G = NULL;
     915          16 :   gcry_mpi_t n = NULL;
     916          16 :   gcry_mpi_t h = NULL;
     917          16 :   gcry_mpi_point_t Q = NULL;
     918          16 :   gcry_mpi_t d = NULL;
     919          16 :   int flags = 0;
     920             :   gcry_sexp_t l1;
     921             : 
     922          16 :   *r_ctx = NULL;
     923             : 
     924          16 :   if (keyparam)
     925             :     {
     926             :       /* Parse an optional flags list.  */
     927           6 :       l1 = sexp_find_token (keyparam, "flags", 0);
     928           6 :       if (l1)
     929             :         {
     930           1 :           errc = _gcry_pk_util_parse_flaglist (l1, &flags, NULL);
     931           1 :           sexp_release (l1);
     932           1 :           l1 = NULL;
     933           1 :           if (errc)
     934           0 :             goto leave;
     935             :         }
     936             : 
     937             :       /* Check whether a curve name was given.  */
     938           6 :       l1 = sexp_find_token (keyparam, "curve", 5);
     939             : 
     940             :       /* If we don't have a curve name or if override parameters have
     941             :          explicitly been requested, parse them.  */
     942           6 :       if (!l1 || (flags & PUBKEY_FLAG_PARAM))
     943             :         {
     944           4 :           errc = mpi_from_keyparam (&p, keyparam, "p");
     945           4 :           if (errc)
     946           0 :             goto leave;
     947           4 :           errc = mpi_from_keyparam (&a, keyparam, "a");
     948           4 :           if (errc)
     949           0 :             goto leave;
     950           4 :           errc = mpi_from_keyparam (&b, keyparam, "b");
     951           4 :           if (errc)
     952           0 :             goto leave;
     953           4 :           errc = point_from_keyparam (&G, keyparam, "g", NULL);
     954           4 :           if (errc)
     955           0 :             goto leave;
     956           4 :           errc = mpi_from_keyparam (&n, keyparam, "n");
     957           4 :           if (errc)
     958           0 :             goto leave;
     959           4 :           errc = mpi_from_keyparam (&h, keyparam, "h");
     960           4 :           if (errc)
     961           0 :             goto leave;
     962             :         }
     963             :     }
     964             :   else
     965          10 :     l1 = NULL; /* No curvename.  */
     966             : 
     967             :   /* Check whether a curve parameter is available and use that to fill
     968             :      in missing values.  If no curve parameter is available try an
     969             :      optional provided curvename.  If only the curvename has been
     970             :      given use that one. */
     971          16 :   if (l1 || curvename)
     972             :     {
     973             :       char *name;
     974             :       elliptic_curve_t *E;
     975             : 
     976          12 :       if (l1)
     977             :         {
     978           2 :           name = sexp_nth_string (l1, 1);
     979           2 :           sexp_release (l1);
     980           2 :           if (!name)
     981             :             {
     982           0 :               errc = GPG_ERR_INV_OBJ; /* Name missing or out of core. */
     983           0 :               goto leave;
     984             :             }
     985             :         }
     986             :       else
     987          10 :         name = NULL;
     988             : 
     989          12 :       E = xtrycalloc (1, sizeof *E);
     990          12 :       if (!E)
     991             :         {
     992           0 :           errc = gpg_err_code_from_syserror ();
     993           0 :           xfree (name);
     994           0 :           goto leave;
     995             :         }
     996             : 
     997          12 :       errc = _gcry_ecc_fill_in_curve (0, name? name : curvename, E, NULL);
     998          12 :       xfree (name);
     999          12 :       if (errc)
    1000             :         {
    1001           0 :           xfree (E);
    1002           0 :           goto leave;
    1003             :         }
    1004             : 
    1005          12 :       model = E->model;
    1006          12 :       dialect = E->dialect;
    1007             : 
    1008          12 :       if (!p)
    1009             :         {
    1010          12 :           p = E->p;
    1011          12 :           E->p = NULL;
    1012             :         }
    1013          12 :       if (!a)
    1014             :         {
    1015          12 :           a = E->a;
    1016          12 :           E->a = NULL;
    1017             :         }
    1018          12 :       if (!b)
    1019             :         {
    1020          12 :           b = E->b;
    1021          12 :           E->b = NULL;
    1022             :         }
    1023          12 :       if (!G)
    1024             :         {
    1025          12 :           G = mpi_point_snatch_set (NULL, E->G.x, E->G.y, E->G.z);
    1026          12 :           E->G.x = NULL;
    1027          12 :           E->G.y = NULL;
    1028          12 :           E->G.z = NULL;
    1029             :         }
    1030          12 :       if (!n)
    1031             :         {
    1032          12 :           n = E->n;
    1033          12 :           E->n = NULL;
    1034             :         }
    1035          12 :       if (!h)
    1036             :         {
    1037          12 :           h = E->h;
    1038          12 :           E->h = NULL;
    1039             :         }
    1040          12 :       _gcry_ecc_curve_free (E);
    1041          12 :       xfree (E);
    1042             :     }
    1043             : 
    1044             : 
    1045          16 :   errc = _gcry_mpi_ec_p_new (&ctx, model, dialect, flags, p, a, b);
    1046          16 :   if (!errc)
    1047             :     {
    1048          14 :       mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC);
    1049             : 
    1050          14 :       if (b)
    1051             :         {
    1052          12 :           mpi_free (ec->b);
    1053          12 :           ec->b = b;
    1054          12 :           b = NULL;
    1055             :         }
    1056          14 :       if (G)
    1057             :         {
    1058          12 :           ec->G = G;
    1059          12 :           G = NULL;
    1060             :         }
    1061          14 :       if (n)
    1062             :         {
    1063          12 :           ec->n = n;
    1064          12 :           n = NULL;
    1065             :         }
    1066          14 :       if (h)
    1067             :         {
    1068          12 :           ec->h = h;
    1069          12 :           h = NULL;
    1070             :         }
    1071             : 
    1072             :       /* Now that we know the curve name we can look for the public key
    1073             :          Q.  point_from_keyparam needs to know the curve parameters so
    1074             :          that it is able to use the correct decompression.  Parsing
    1075             :          the private key D could have been done earlier but it is less
    1076             :          surprising if we do it here as well.  */
    1077          14 :       if (keyparam)
    1078             :         {
    1079           4 :           errc = point_from_keyparam (&Q, keyparam, "q", ec);
    1080           4 :           if (errc)
    1081           0 :             goto leave;
    1082           4 :           errc = mpi_from_keyparam (&d, keyparam, "d");
    1083           4 :           if (errc)
    1084           0 :             goto leave;
    1085             :         }
    1086             : 
    1087          14 :       if (Q)
    1088             :         {
    1089           2 :           ec->Q = Q;
    1090           2 :           Q = NULL;
    1091             :         }
    1092          14 :       if (d)
    1093             :         {
    1094           0 :           ec->d = d;
    1095           0 :           d = NULL;
    1096             :         }
    1097             : 
    1098          14 :       *r_ctx = ctx;
    1099          14 :       ctx = NULL;
    1100             :     }
    1101             : 
    1102             :  leave:
    1103          16 :   _gcry_ctx_release (ctx);
    1104          16 :   mpi_free (p);
    1105          16 :   mpi_free (a);
    1106          16 :   mpi_free (b);
    1107          16 :   _gcry_mpi_point_release (G);
    1108          16 :   mpi_free (n);
    1109          16 :   mpi_free (h);
    1110          16 :   _gcry_mpi_point_release (Q);
    1111          16 :   mpi_free (d);
    1112          16 :   return errc;
    1113             : }
    1114             : 
    1115             : 
    1116             : /* Return the parameters of the curve NAME as an S-expression.  */
    1117             : gcry_sexp_t
    1118           2 : _gcry_ecc_get_param_sexp (const char *name)
    1119             : {
    1120             :   unsigned int nbits;
    1121             :   elliptic_curve_t E;
    1122             :   mpi_ec_t ctx;
    1123             :   gcry_mpi_t g_x, g_y;
    1124             :   gcry_mpi_t pkey[7];
    1125             :   gcry_sexp_t result;
    1126             :   int i;
    1127             : 
    1128           2 :   memset (&E, 0, sizeof E);
    1129           2 :   if (_gcry_ecc_fill_in_curve (0, name, &E, &nbits))
    1130           0 :     return NULL;
    1131             : 
    1132           2 :   g_x = mpi_new (0);
    1133           2 :   g_y = mpi_new (0);
    1134           2 :   ctx = _gcry_mpi_ec_p_internal_new (MPI_EC_WEIERSTRASS,
    1135             :                                      ECC_DIALECT_STANDARD,
    1136             :                                      0,
    1137             :                                      E.p, E.a, NULL);
    1138           2 :   if (_gcry_mpi_ec_get_affine (g_x, g_y, &E.G, ctx))
    1139           0 :     log_fatal ("ecc get param: Failed to get affine coordinates\n");
    1140           2 :   _gcry_mpi_ec_free (ctx);
    1141           2 :   _gcry_mpi_point_free_parts (&E.G);
    1142             : 
    1143           2 :   pkey[0] = E.p;
    1144           2 :   pkey[1] = E.a;
    1145           2 :   pkey[2] = E.b;
    1146           2 :   pkey[3] = _gcry_ecc_ec2os (g_x, g_y, E.p);
    1147           2 :   pkey[4] = E.n;
    1148           2 :   pkey[5] = E.h;
    1149           2 :   pkey[6] = NULL;
    1150             : 
    1151           2 :   mpi_free (g_x);
    1152           2 :   mpi_free (g_y);
    1153             : 
    1154           2 :   if (sexp_build (&result, NULL,
    1155             :                   "(public-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)(h%m)))",
    1156             :                   pkey[0], pkey[1], pkey[2], pkey[3], pkey[4], pkey[5]))
    1157           0 :     result = NULL;
    1158             : 
    1159          14 :   for (i=0; pkey[i]; i++)
    1160          12 :     _gcry_mpi_release (pkey[i]);
    1161             : 
    1162           2 :   return result;
    1163             : }
    1164             : 
    1165             : 
    1166             : /* Return an MPI (or opaque MPI) described by NAME and the context EC.
    1167             :    If COPY is true a copy is returned, if not a const MPI may be
    1168             :    returned.  In any case mpi_free must be used.  */
    1169             : gcry_mpi_t
    1170          53 : _gcry_ecc_get_mpi (const char *name, mpi_ec_t ec, int copy)
    1171             : {
    1172          53 :   if (!*name)
    1173           0 :     return NULL;
    1174             : 
    1175          53 :   if (!strcmp (name, "p") && ec->p)
    1176           7 :     return mpi_is_const (ec->p) && !copy? ec->p : mpi_copy (ec->p);
    1177          46 :   if (!strcmp (name, "a") && ec->a)
    1178           6 :     return mpi_is_const (ec->a) && !copy? ec->a : mpi_copy (ec->a);
    1179          40 :   if (!strcmp (name, "b") && ec->b)
    1180           7 :     return mpi_is_const (ec->b) && !copy? ec->b : mpi_copy (ec->b);
    1181          33 :   if (!strcmp (name, "n") && ec->n)
    1182           7 :     return mpi_is_const (ec->n) && !copy? ec->n : mpi_copy (ec->n);
    1183          26 :   if (!strcmp (name, "h") && ec->h)
    1184           6 :     return mpi_is_const (ec->h) && !copy? ec->h : mpi_copy (ec->h);
    1185          20 :   if (!strcmp (name, "d") && ec->d)
    1186           0 :     return mpi_is_const (ec->d) && !copy? ec->d : mpi_copy (ec->d);
    1187             : 
    1188             :   /* Return a requested point coordinate.  */
    1189          20 :   if (!strcmp (name, "g.x") && ec->G && ec->G->x)
    1190           6 :     return mpi_is_const (ec->G->x) && !copy? ec->G->x : mpi_copy (ec->G->x);
    1191          14 :   if (!strcmp (name, "g.y") && ec->G && ec->G->y)
    1192           6 :     return mpi_is_const (ec->G->y) && !copy? ec->G->y : mpi_copy (ec->G->y);
    1193           8 :   if (!strcmp (name, "q.x") && ec->Q && ec->Q->x)
    1194           0 :     return mpi_is_const (ec->Q->x) && !copy? ec->Q->x : mpi_copy (ec->Q->x);
    1195           8 :   if (!strcmp (name, "q.y") && ec->Q && ec->Q->y)
    1196           0 :     return mpi_is_const (ec->G->y) && !copy? ec->Q->y : mpi_copy (ec->Q->y);
    1197             : 
    1198             :   /* If the base point has been requested, return it in standard
    1199             :      encoding.  */
    1200           8 :   if (!strcmp (name, "g") && ec->G)
    1201           0 :     return _gcry_mpi_ec_ec2os (ec->G, ec);
    1202             : 
    1203             :   /* If the public key has been requested, return it by default in
    1204             :      standard uncompressed encoding or if requested in other
    1205             :      encodings.  */
    1206           8 :   if (*name == 'q' && (!name[1] || name[1] == '@'))
    1207             :     {
    1208             :       /* If only the private key is given, compute the public key.  */
    1209           8 :       if (!ec->Q)
    1210           3 :         ec->Q = _gcry_ecc_compute_public (NULL, ec, NULL, NULL);
    1211             : 
    1212           8 :       if (!ec->Q)
    1213           2 :         return NULL;
    1214             : 
    1215           6 :       if (name[1] != '@')
    1216           5 :         return _gcry_mpi_ec_ec2os (ec->Q, ec);
    1217             : 
    1218           1 :       if (!strcmp (name+2, "eddsa") && ec->model == MPI_EC_EDWARDS)
    1219             :         {
    1220             :           unsigned char *encpk;
    1221             :           unsigned int encpklen;
    1222             : 
    1223           1 :           if (!_gcry_ecc_eddsa_encodepoint (ec->Q, ec, NULL, NULL, 0,
    1224             :                                             &encpk, &encpklen))
    1225           1 :             return mpi_set_opaque (NULL, encpk, encpklen*8);
    1226             :         }
    1227             :     }
    1228             : 
    1229           0 :   return NULL;
    1230             : }
    1231             : 
    1232             : 
    1233             : /* Return a point described by NAME and the context EC.  */
    1234             : gcry_mpi_point_t
    1235          10 : _gcry_ecc_get_point (const char *name, mpi_ec_t ec)
    1236             : {
    1237          10 :   if (!strcmp (name, "g") && ec->G)
    1238           8 :     return point_copy (ec->G);
    1239           2 :   if (!strcmp (name, "q"))
    1240             :     {
    1241             :       /* If only the private key is given, compute the public key.  */
    1242           2 :       if (!ec->Q)
    1243           0 :         ec->Q = _gcry_ecc_compute_public (NULL, ec, NULL, NULL);
    1244             : 
    1245           2 :       if (ec->Q)
    1246           2 :         return point_copy (ec->Q);
    1247             :     }
    1248             : 
    1249           0 :   return NULL;
    1250             : }
    1251             : 
    1252             : 
    1253             : /* Store the MPI NEWVALUE into the context EC under NAME. */
    1254             : gpg_err_code_t
    1255           8 : _gcry_ecc_set_mpi (const char *name, gcry_mpi_t newvalue, mpi_ec_t ec)
    1256             : {
    1257           8 :   gpg_err_code_t rc = 0;
    1258             : 
    1259           8 :   if (!*name)
    1260             :     ;
    1261           8 :   else if (!strcmp (name, "p"))
    1262             :     {
    1263           0 :       mpi_free (ec->p);
    1264           0 :       ec->p = mpi_copy (newvalue);
    1265           0 :       _gcry_mpi_ec_get_reset (ec);
    1266             :     }
    1267           8 :   else if (!strcmp (name, "a"))
    1268             :     {
    1269           0 :       mpi_free (ec->a);
    1270           0 :       ec->a = mpi_copy (newvalue);
    1271           0 :       _gcry_mpi_ec_get_reset (ec);
    1272             :     }
    1273           8 :   else if (!strcmp (name, "b"))
    1274             :     {
    1275           0 :       mpi_free (ec->b);
    1276           0 :       ec->b = mpi_copy (newvalue);
    1277             :     }
    1278           8 :   else if (!strcmp (name, "n"))
    1279             :     {
    1280           0 :       mpi_free (ec->n);
    1281           0 :       ec->n = mpi_copy (newvalue);
    1282             :     }
    1283           8 :   else if (!strcmp (name, "h"))
    1284             :     {
    1285           0 :       mpi_free (ec->h);
    1286           0 :       ec->h = mpi_copy (newvalue);
    1287             :     }
    1288           8 :   else if (*name == 'q' && (!name[1] || name[1] == '@'))
    1289             :     {
    1290           3 :       if (newvalue)
    1291             :         {
    1292           2 :           if (!ec->Q)
    1293           2 :             ec->Q = mpi_point_new (0);
    1294           2 :           if (ec->dialect == ECC_DIALECT_ED25519)
    1295           1 :             rc = _gcry_ecc_eddsa_decodepoint (newvalue, ec, ec->Q, NULL, NULL);
    1296             :           else
    1297           1 :             rc = _gcry_ecc_os2ec (ec->Q, newvalue);
    1298             :         }
    1299           6 :       if (rc || !newvalue)
    1300             :         {
    1301           1 :           _gcry_mpi_point_release (ec->Q);
    1302           1 :           ec->Q = NULL;
    1303             :         }
    1304             :       /* Note: We assume that Q matches d and thus do not reset d.  */
    1305             :     }
    1306           5 :   else if (!strcmp (name, "d"))
    1307             :     {
    1308           5 :       mpi_free (ec->d);
    1309           5 :       ec->d = mpi_copy (newvalue);
    1310           5 :       if (ec->d)
    1311             :         {
    1312             :           /* We need to reset the public key because it may not
    1313             :              anymore match.  */
    1314           3 :           _gcry_mpi_point_release (ec->Q);
    1315           3 :           ec->Q = NULL;
    1316             :         }
    1317             :     }
    1318             :   else
    1319           0 :    rc = GPG_ERR_UNKNOWN_NAME;
    1320             : 
    1321           8 :   return rc;
    1322             : }
    1323             : 
    1324             : 
    1325             : /* Store the point NEWVALUE into the context EC under NAME.  */
    1326             : gpg_err_code_t
    1327           2 : _gcry_ecc_set_point (const char *name, gcry_mpi_point_t newvalue, mpi_ec_t ec)
    1328             : {
    1329           2 :   if (!strcmp (name, "g"))
    1330             :     {
    1331           1 :       _gcry_mpi_point_release (ec->G);
    1332           1 :       ec->G = point_copy (newvalue);
    1333             :     }
    1334           1 :   else if (!strcmp (name, "q"))
    1335             :     {
    1336           1 :       _gcry_mpi_point_release (ec->Q);
    1337           1 :       ec->Q = point_copy (newvalue);
    1338             :     }
    1339             :   else
    1340           0 :     return GPG_ERR_UNKNOWN_NAME;
    1341             : 
    1342           2 :   return 0;
    1343             : }

Generated by: LCOV version 1.13