LCOV - code coverage report
Current view: top level - common - openpgp-oid.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 110 164 67.1 %
Date: 2016-11-29 15:00:56 Functions: 8 10 80.0 %

          Line data    Source code
       1             : /* openpgp-oids.c - OID helper for OpenPGP
       2             :  * Copyright (C) 2011 Free Software Foundation, Inc.
       3             :  * Copyright (C) 2013 Werner Koch
       4             :  *
       5             :  * This file is part of GnuPG.
       6             :  *
       7             :  * This file is free software; you can redistribute it and/or modify
       8             :  * it under the terms of either
       9             :  *
      10             :  *   - the GNU Lesser General Public License as published by the Free
      11             :  *     Software Foundation; either version 3 of the License, or (at
      12             :  *     your option) any later version.
      13             :  *
      14             :  * or
      15             :  *
      16             :  *   - the GNU General Public License as published by the Free
      17             :  *     Software Foundation; either version 2 of the License, or (at
      18             :  *     your option) any later version.
      19             :  *
      20             :  * or both in parallel, as here.
      21             :  *
      22             :  * This file is distributed in the hope that it will be useful,
      23             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      24             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      25             :  * GNU General Public License for more details.
      26             :  *
      27             :  * You should have received a copy of the GNU General Public License
      28             :  * along with this program; if not, see <https://www.gnu.org/licenses/>.
      29             :  */
      30             : 
      31             : #include <config.h>
      32             : #include <stdlib.h>
      33             : #include <errno.h>
      34             : #include <ctype.h>
      35             : #include <assert.h>
      36             : 
      37             : #include "util.h"
      38             : #include "openpgpdefs.h"
      39             : 
      40             : /* A table with all our supported OpenPGP curves.  */
      41             : static struct {
      42             :   const char *name;   /* Standard name.  */
      43             :   const char *oidstr; /* IETF formatted OID.  */
      44             :   unsigned int nbits; /* Nominal bit length of the curve.  */
      45             :   const char *alias;  /* NULL or alternative name of the curve.  */
      46             :   int pubkey_algo;    /* Required OpenPGP algo or 0 for ECDSA/ECDH.  */
      47             : } oidtable[] = {
      48             : 
      49             :   { "Curve25519", "1.3.6.1.4.1.3029.1.5.1", 255, "cv25519", PUBKEY_ALGO_ECDH },
      50             :   { "Ed25519",    "1.3.6.1.4.1.11591.15.1", 255, "ed25519", PUBKEY_ALGO_EDDSA },
      51             : 
      52             :   { "NIST P-256",      "1.2.840.10045.3.1.7",    256, "nistp256" },
      53             :   { "NIST P-384",      "1.3.132.0.34",           384, "nistp384" },
      54             :   { "NIST P-521",      "1.3.132.0.35",           521, "nistp521" },
      55             : 
      56             :   { "brainpoolP256r1", "1.3.36.3.3.2.8.1.1.7",   256 },
      57             :   { "brainpoolP384r1", "1.3.36.3.3.2.8.1.1.11",  384 },
      58             :   { "brainpoolP512r1", "1.3.36.3.3.2.8.1.1.13",  512 },
      59             : 
      60             :   { "secp256k1",       "1.3.132.0.10",           256 },
      61             : 
      62             :   { NULL, NULL, 0}
      63             : };
      64             : 
      65             : 
      66             : /* The OID for Curve Ed25519 in OpenPGP format.  */
      67             : static const char oid_ed25519[] =
      68             :   { 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xda, 0x47, 0x0f, 0x01 };
      69             : 
      70             : /* The OID for Curve25519 in OpenPGP format.  */
      71             : static const char oid_cv25519[] =
      72             :   { 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01 };
      73             : 
      74             : 
      75             : /* Helper for openpgp_oid_from_str.  */
      76             : static size_t
      77          90 : make_flagged_int (unsigned long value, char *buf, size_t buflen)
      78             : {
      79          90 :   int more = 0;
      80             :   int shift;
      81             : 
      82             :   /* fixme: figure out the number of bits in an ulong and start with
      83             :      that value as shift (after making it a multiple of 7) a more
      84             :      straigtforward implementation is to do it in reverse order using
      85             :      a temporary buffer - saves a lot of compares */
      86         450 :   for (more=0, shift=28; shift > 0; shift -= 7)
      87             :     {
      88         360 :       if (more || value >= (1<<shift))
      89             :         {
      90          15 :           buf[buflen++] = 0x80 | (value >> shift);
      91          15 :           value -= (value >> shift) << shift;
      92          15 :           more = 1;
      93             :         }
      94             :     }
      95          90 :   buf[buflen++] = value;
      96          90 :   return buflen;
      97             : }
      98             : 
      99             : 
     100             : /* Convert the OID given in dotted decimal form in STRING to an DER
     101             :  * encoding and store it as an opaque value at R_MPI.  The format of
     102             :  * the DER encoded is not a regular ASN.1 object but the modified
     103             :  * format as used by OpenPGP for the ECC curve description.  On error
     104             :  * the function returns and error code an NULL is stored at R_BUG.
     105             :  * Note that scanning STRING stops at the first white space
     106             :  * character.  */
     107             : gpg_error_t
     108          21 : openpgp_oid_from_str (const char *string, gcry_mpi_t *r_mpi)
     109             : {
     110             :   unsigned char *buf;
     111             :   size_t buflen;
     112             :   unsigned long val1, val;
     113             :   const char *endp;
     114             :   int arcno;
     115             : 
     116          21 :   *r_mpi = NULL;
     117             : 
     118          21 :   if (!string || !*string)
     119           1 :     return gpg_error (GPG_ERR_INV_VALUE);
     120             : 
     121             :   /* We can safely assume that the encoded OID is shorter than the string. */
     122          20 :   buf = xtrymalloc (1 + strlen (string) + 2);
     123          20 :   if (!buf)
     124           0 :     return gpg_error_from_syserror ();
     125             :   /* Save the first byte for the length.  */
     126          20 :   buflen = 1;
     127             : 
     128          20 :   val1 = 0; /* Avoid compiler warning.  */
     129          20 :   arcno = 0;
     130             :   do {
     131         128 :     arcno++;
     132         128 :     val = strtoul (string, (char**)&endp, 10);
     133         128 :     if (!digitp (string) || !(*endp == '.' || !*endp))
     134             :       {
     135           1 :         xfree (buf);
     136           1 :         return gpg_error (GPG_ERR_INV_OID_STRING);
     137             :       }
     138         127 :     if (*endp == '.')
     139         108 :       string = endp+1;
     140             : 
     141         127 :     if (arcno == 1)
     142             :       {
     143          19 :         if (val > 2)
     144           0 :           break; /* Not allowed, error catched below.  */
     145          19 :         val1 = val;
     146             :       }
     147         108 :     else if (arcno == 2)
     148             :       { /* Need to combine the first two arcs in one octet.  */
     149          18 :         if (val1 < 2)
     150             :           {
     151          18 :             if (val > 39)
     152             :               {
     153           0 :                 xfree (buf);
     154           0 :                 return gpg_error (GPG_ERR_INV_OID_STRING);
     155             :               }
     156          18 :             buf[buflen++] = val1*40 + val;
     157             :           }
     158             :         else
     159             :           {
     160           0 :             val += 80;
     161           0 :             buflen = make_flagged_int (val, buf, buflen);
     162             :           }
     163             :       }
     164             :     else
     165             :       {
     166          90 :         buflen = make_flagged_int (val, buf, buflen);
     167             :       }
     168         127 :   } while (*endp == '.');
     169             : 
     170          19 :   if (arcno == 1 || buflen < 2 || buflen > 254 )
     171             :     { /* It is not possible to encode only the first arc.  */
     172           1 :       xfree (buf);
     173           1 :       return gpg_error (GPG_ERR_INV_OID_STRING);
     174             :     }
     175             : 
     176          18 :   *buf = buflen - 1;
     177          18 :   *r_mpi = gcry_mpi_set_opaque (NULL, buf, buflen * 8);
     178          18 :   if (!*r_mpi)
     179             :     {
     180           0 :       xfree (buf);
     181           0 :       return gpg_error_from_syserror ();
     182             :     }
     183          18 :   return 0;
     184             : }
     185             : 
     186             : 
     187             : /* Return a malloced string represenation of the OID in the opaque MPI
     188             :    A.  In case of an error NULL is returned and ERRNO is set.  */
     189             : char *
     190         461 : openpgp_oid_to_str (gcry_mpi_t a)
     191             : {
     192             :   const unsigned char *buf;
     193             :   size_t length;
     194             :   unsigned int lengthi;
     195             :   char *string, *p;
     196         461 :   int n = 0;
     197             :   unsigned long val, valmask;
     198             : 
     199         461 :   valmask = (unsigned long)0xfe << (8 * (sizeof (valmask) - 1));
     200             : 
     201         461 :   if (!a
     202         461 :       || !gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE)
     203         461 :       || !(buf = gcry_mpi_get_opaque (a, &lengthi)))
     204             :     {
     205           0 :       gpg_err_set_errno (EINVAL);
     206           0 :       return NULL;
     207             :     }
     208             : 
     209         461 :   buf = gcry_mpi_get_opaque (a, &lengthi);
     210         461 :   length = (lengthi+7)/8;
     211             : 
     212             :   /* The first bytes gives the length; check consistency.  */
     213         461 :   if (!length || buf[0] != length -1)
     214             :     {
     215           0 :       gpg_err_set_errno (EINVAL);
     216           0 :       return NULL;
     217             :     }
     218             :   /* Skip length byte.  */
     219         461 :   length--;
     220         461 :   buf++;
     221             : 
     222             :   /* To calculate the length of the string we can safely assume an
     223             :      upper limit of 3 decimal characters per byte.  Two extra bytes
     224             :      account for the special first octect */
     225         461 :   string = p = xtrymalloc (length*(1+3)+2+1);
     226         461 :   if (!string)
     227           0 :     return NULL;
     228         461 :   if (!length)
     229             :     {
     230           0 :       *p = 0;
     231           0 :       return string;
     232             :     }
     233             : 
     234         461 :   if (buf[0] < 40)
     235           1 :     p += sprintf (p, "0.%d", buf[n]);
     236         460 :   else if (buf[0] < 80)
     237         458 :     p += sprintf (p, "1.%d", buf[n]-40);
     238             :   else {
     239           2 :     val = buf[n] & 0x7f;
     240           5 :     while ( (buf[n]&0x80) && ++n < length )
     241             :       {
     242           1 :         if ( (val & valmask) )
     243           0 :           goto badoid;  /* Overflow.  */
     244           1 :         val <<= 7;
     245           1 :         val |= buf[n] & 0x7f;
     246             :       }
     247           2 :     if (val < 80)
     248           2 :       goto badoid;
     249           0 :     val -= 80;
     250           0 :     sprintf (p, "2.%lu", val);
     251           0 :     p += strlen (p);
     252             :   }
     253        2226 :   for (n++; n < length; n++)
     254             :     {
     255        1767 :       val = buf[n] & 0x7f;
     256        4137 :       while ( (buf[n]&0x80) && ++n < length )
     257             :         {
     258         603 :           if ( (val & valmask) )
     259           0 :             goto badoid;  /* Overflow.  */
     260         603 :           val <<= 7;
     261         603 :           val |= buf[n] & 0x7f;
     262             :         }
     263        1767 :       sprintf (p, ".%lu", val);
     264        1767 :       p += strlen (p);
     265             :     }
     266             : 
     267         459 :   *p = 0;
     268         459 :   return string;
     269             : 
     270             :  badoid:
     271             :   /* Return a special OID (gnu.gnupg.badoid) to indicate the error
     272             :      case.  The OID is broken and thus we return one which can't do
     273             :      any harm.  Formally this does not need to be a bad OID but an OID
     274             :      with an arc that can't be represented in a 32 bit word is more
     275             :      than likely corrupt.  */
     276           2 :   xfree (string);
     277           2 :   return xtrystrdup ("1.3.6.1.4.1.11591.2.12242973");
     278             : }
     279             : 
     280             : 
     281             : 
     282             : /* Return true if A represents the OID for Ed25519.  */
     283             : int
     284         140 : openpgp_oid_is_ed25519 (gcry_mpi_t a)
     285             : {
     286             :   const unsigned char *buf;
     287             :   unsigned int nbits;
     288             :   size_t n;
     289             : 
     290         140 :   if (!a || !gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE))
     291          97 :     return 0;
     292             : 
     293          43 :   buf = gcry_mpi_get_opaque (a, &nbits);
     294          43 :   n = (nbits+7)/8;
     295          43 :   return (n == DIM (oid_ed25519)
     296          43 :           && !memcmp (buf, oid_ed25519, DIM (oid_ed25519)));
     297             : }
     298             : 
     299             : 
     300             : int
     301         141 : openpgp_oid_is_cv25519 (gcry_mpi_t a)
     302             : {
     303             :   const unsigned char *buf;
     304             :   unsigned int nbits;
     305             :   size_t n;
     306             : 
     307         141 :   if (!a || !gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE))
     308           0 :     return 0;
     309             : 
     310         141 :   buf = gcry_mpi_get_opaque (a, &nbits);
     311         141 :   n = (nbits+7)/8;
     312         141 :   return (n == DIM (oid_cv25519)
     313         141 :           && !memcmp (buf, oid_cv25519, DIM (oid_cv25519)));
     314             : }
     315             : 
     316             : 
     317             : /* Map the Libgcrypt ECC curve NAME to an OID.  If R_NBITS is not NULL
     318             :    store the bit size of the curve there.  Returns NULL for unknown
     319             :    curve names.  */
     320             : const char *
     321           0 : openpgp_curve_to_oid (const char *name, unsigned int *r_nbits)
     322             : {
     323             :   int i;
     324           0 :   unsigned int nbits = 0;
     325           0 :   const char *oidstr = NULL;
     326             : 
     327           0 :   if (name)
     328             :     {
     329           0 :       for (i=0; oidtable[i].name; i++)
     330           0 :         if (!strcmp (oidtable[i].name, name)
     331           0 :             || (oidtable[i].alias && !strcmp (oidtable[i].alias, name)))
     332             :           {
     333           0 :             oidstr = oidtable[i].oidstr;
     334           0 :             nbits  = oidtable[i].nbits;
     335           0 :             break;
     336             :           }
     337           0 :       if (!oidtable[i].name)
     338             :         {
     339             :           /* If not found assume the input is already an OID and check
     340             :              whether we support it.  */
     341           0 :           for (i=0; oidtable[i].name; i++)
     342           0 :             if (!strcmp (name, oidtable[i].oidstr))
     343             :               {
     344           0 :                 oidstr = oidtable[i].oidstr;
     345           0 :                 nbits  = oidtable[i].nbits;
     346           0 :                 break;
     347             :               }
     348             :         }
     349             :     }
     350             : 
     351           0 :   if (r_nbits)
     352           0 :     *r_nbits = nbits;
     353           0 :   return oidstr;
     354             : }
     355             : 
     356             : 
     357             : /* Map an OpenPGP OID to the Libgcrypt curve NAME.  Returns NULL for
     358             :    unknown curve names.  Unless CANON is set we prefer an alias name
     359             :    here which is more suitable for printing.  */
     360             : const char *
     361          12 : openpgp_oid_to_curve (const char *oidstr, int canon)
     362             : {
     363             :   int i;
     364             : 
     365          12 :   if (!oidstr)
     366           0 :     return NULL;
     367             : 
     368          48 :   for (i=0; oidtable[i].name; i++)
     369          48 :     if (!strcmp (oidtable[i].oidstr, oidstr))
     370          12 :       return !canon && oidtable[i].alias? oidtable[i].alias : oidtable[i].name;
     371             : 
     372           0 :   return NULL;
     373             : }
     374             : 
     375             : 
     376             : /* Return true if the curve with NAME is supported.  */
     377             : static int
     378           9 : curve_supported_p (const char *name)
     379             : {
     380           9 :   int result = 0;
     381             :   gcry_sexp_t keyparms;
     382             : 
     383           9 :   if (!gcry_sexp_build (&keyparms, NULL, "(public-key(ecc(curve %s)))", name))
     384             :     {
     385           9 :       result = !!gcry_pk_get_curve (keyparms, 0, NULL);
     386           9 :       gcry_sexp_release (keyparms);
     387             :     }
     388           9 :   return result;
     389             : }
     390             : 
     391             : 
     392             : /* Enumerate available and supported OpenPGP curves.  The caller needs
     393             :    to set the integer variable at ITERP to zero and keep on calling
     394             :    this function until NULL is returned.  */
     395             : const char *
     396          10 : openpgp_enum_curves (int *iterp)
     397             : {
     398          10 :   int idx = *iterp;
     399             : 
     400          20 :   while (idx >= 0 && idx < DIM (oidtable) && oidtable[idx].name)
     401             :     {
     402           9 :       if (curve_supported_p (oidtable[idx].name))
     403             :         {
     404           9 :           *iterp = idx + 1;
     405           9 :           return oidtable[idx].alias? oidtable[idx].alias : oidtable[idx].name;
     406             :         }
     407           0 :       idx++;
     408             :     }
     409           1 :   *iterp = idx;
     410           1 :   return NULL;
     411             : }
     412             : 
     413             : 
     414             : /* Return the Libgcrypt name for for the gpg curve NAME if supported.
     415             :  * If R_ALGO is not NULL the required OpenPGP public key algo or 0 is
     416             :  * stored at that address.  NULL is returned if the curev is not
     417             :  * supported. */
     418             : const char *
     419           0 : openpgp_is_curve_supported (const char *name, int *r_algo)
     420             : {
     421             :   int idx;
     422             : 
     423           0 :   if (r_algo)
     424           0 :     *r_algo = 0;
     425           0 :   for (idx = 0; idx < DIM (oidtable) && oidtable[idx].name; idx++)
     426             :     {
     427           0 :       if ((!strcmp (name, oidtable[idx].name)
     428           0 :            || (oidtable[idx].alias && !strcmp (name, (oidtable[idx].alias))))
     429           0 :           && curve_supported_p (oidtable[idx].name))
     430             :         {
     431           0 :           if (r_algo)
     432           0 :             *r_algo = oidtable[idx].pubkey_algo;
     433           0 :           return oidtable[idx].name;
     434             :         }
     435             :     }
     436           0 :   return NULL;
     437             : }

Generated by: LCOV version 1.11