LCOV - code coverage report
Current view: top level - common - sexputil.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 173 307 56.4 %
Date: 2016-09-12 12:29:17 Functions: 8 14 57.1 %

          Line data    Source code
       1             : /* sexputil.c - Utility functions for S-expressions.
       2             :  * Copyright (C) 2005, 2007, 2009 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 <http://www.gnu.org/licenses/>.
      29             :  */
      30             : 
      31             : /* This file implements a few utility functions useful when working
      32             :    with canonical encrypted S-expresions (i.e. not the S-exprssion
      33             :    objects from libgcrypt).  */
      34             : 
      35             : #include <config.h>
      36             : #include <stdio.h>
      37             : #include <stdlib.h>
      38             : #include <string.h>
      39             : #include <unistd.h>
      40             : #include <errno.h>
      41             : #ifdef HAVE_LOCALE_H
      42             : #include <locale.h>
      43             : #endif
      44             : 
      45             : #include "util.h"
      46             : #include "tlv.h"
      47             : #include "sexp-parse.h"
      48             : #include "openpgpdefs.h"  /* for pubkey_algo_t */
      49             : 
      50             : 
      51             : /* Return a malloced string with the S-expression CANON in advanced
      52             :    format.  Returns NULL on error.  */
      53             : static char *
      54           0 : sexp_to_string (gcry_sexp_t sexp)
      55             : {
      56             :   size_t n;
      57             :   char *result;
      58             : 
      59           0 :   if (!sexp)
      60           0 :     return NULL;
      61           0 :   n = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0);
      62           0 :   if (!n)
      63           0 :     return NULL;
      64           0 :   result = xtrymalloc (n);
      65           0 :   if (!result)
      66           0 :     return NULL;
      67           0 :   n = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, result, n);
      68           0 :   if (!n)
      69           0 :     BUG ();
      70             : 
      71           0 :   return result;
      72             : }
      73             : 
      74             : 
      75             : /* Return a malloced string with the S-expression CANON in advanced
      76             :    format.  Returns NULL on error.  */
      77             : char *
      78           0 : canon_sexp_to_string (const unsigned char *canon, size_t canonlen)
      79             : {
      80             :   size_t n;
      81             :   gcry_sexp_t sexp;
      82             :   char *result;
      83             : 
      84           0 :   n = gcry_sexp_canon_len (canon, canonlen, NULL, NULL);
      85           0 :   if (!n)
      86           0 :     return NULL;
      87           0 :   if (gcry_sexp_sscan (&sexp, NULL, canon, n))
      88           0 :     return NULL;
      89           0 :   result = sexp_to_string (sexp);
      90           0 :   gcry_sexp_release (sexp);
      91           0 :   return result;
      92             : }
      93             : 
      94             : 
      95             : /* Print the canonical encoded S-expression in SEXP in advanced
      96             :    format.  SEXPLEN may be passed as 0 is SEXP is known to be valid.
      97             :    With TEXT of NULL print just the raw S-expression, with TEXT just
      98             :    an empty string, print a trailing linefeed, otherwise print an
      99             :    entire debug line. */
     100             : void
     101           0 : log_printcanon (const char *text, const unsigned char *sexp, size_t sexplen)
     102             : {
     103           0 :   if (text && *text)
     104           0 :     log_debug ("%s ", text);
     105           0 :   if (sexp)
     106             :     {
     107           0 :       char *buf = canon_sexp_to_string (sexp, sexplen);
     108           0 :       log_printf ("%s", buf? buf : "[invalid S-expression]");
     109           0 :       xfree (buf);
     110             :     }
     111           0 :   if (text)
     112           0 :     log_printf ("\n");
     113           0 : }
     114             : 
     115             : 
     116             : /* Print the gcryp S-expression in SEXP in advanced format.  With TEXT
     117             :    of NULL print just the raw S-expression, with TEXT just an empty
     118             :    string, print a trailing linefeed, otherwise print an entire debug
     119             :    line. */
     120             : void
     121           0 : log_printsexp (const char *text, gcry_sexp_t sexp)
     122             : {
     123           0 :   if (text && *text)
     124           0 :     log_debug ("%s ", text);
     125           0 :   if (sexp)
     126             :     {
     127           0 :       char *buf = sexp_to_string (sexp);
     128           0 :       log_printf ("%s", buf? buf : "[invalid S-expression]");
     129           0 :       xfree (buf);
     130             :     }
     131           0 :   if (text)
     132           0 :     log_printf ("\n");
     133           0 : }
     134             : 
     135             : 
     136             : /* Helper function to create a canonical encoded S-expression from a
     137             :    Libgcrypt S-expression object.  The function returns 0 on success
     138             :    and the malloced canonical S-expression is stored at R_BUFFER and
     139             :    the allocated length at R_BUFLEN.  On error an error code is
     140             :    returned and (NULL, 0) stored at R_BUFFER and R_BUFLEN.  If the
     141             :    allocated buffer length is not required, NULL by be used for
     142             :    R_BUFLEN.  */
     143             : gpg_error_t
     144         688 : make_canon_sexp (gcry_sexp_t sexp, unsigned char **r_buffer, size_t *r_buflen)
     145             : {
     146             :   size_t len;
     147             :   unsigned char *buf;
     148             : 
     149         688 :   *r_buffer = NULL;
     150         688 :   if (r_buflen)
     151         688 :     *r_buflen = 0;;
     152             : 
     153         688 :   len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, NULL, 0);
     154         688 :   if (!len)
     155           0 :     return gpg_error (GPG_ERR_BUG);
     156         688 :   buf = xtrymalloc (len);
     157         688 :   if (!buf)
     158           0 :     return gpg_error_from_syserror ();
     159         688 :   len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, buf, len);
     160         688 :   if (!len)
     161           0 :     return gpg_error (GPG_ERR_BUG);
     162             : 
     163         688 :   *r_buffer = buf;
     164         688 :   if (r_buflen)
     165         688 :     *r_buflen = len;
     166             : 
     167         688 :   return 0;
     168             : }
     169             : 
     170             : 
     171             : /* Same as make_canon_sexp but pad the buffer to multiple of 64
     172             :    bits.  If SECURE is set, secure memory will be allocated.  */
     173             : gpg_error_t
     174          63 : make_canon_sexp_pad (gcry_sexp_t sexp, int secure,
     175             :                      unsigned char **r_buffer, size_t *r_buflen)
     176             : {
     177             :   size_t len;
     178             :   unsigned char *buf;
     179             : 
     180          63 :   *r_buffer = NULL;
     181          63 :   if (r_buflen)
     182          36 :     *r_buflen = 0;;
     183             : 
     184          63 :   len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, NULL, 0);
     185          63 :   if (!len)
     186           0 :     return gpg_error (GPG_ERR_BUG);
     187          63 :   len += (8 - len % 8) % 8;
     188          63 :   buf = secure? xtrycalloc_secure (1, len) : xtrycalloc (1, len);
     189          63 :   if (!buf)
     190           0 :     return gpg_error_from_syserror ();
     191          63 :   if (!gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, buf, len))
     192           0 :     return gpg_error (GPG_ERR_BUG);
     193             : 
     194          63 :   *r_buffer = buf;
     195          63 :   if (r_buflen)
     196          36 :     *r_buflen = len;
     197             : 
     198          63 :   return 0;
     199             : }
     200             : 
     201             : /* Return the so called "keygrip" which is the SHA-1 hash of the
     202             :    public key parameters expressed in a way depended on the algorithm.
     203             : 
     204             :    KEY is expected to be an canonical encoded S-expression with a
     205             :    public or private key. KEYLEN is the length of that buffer.
     206             : 
     207             :    GRIP must be at least 20 bytes long.  On success 0 is returned, on
     208             :    error an error code. */
     209             : gpg_error_t
     210          21 : keygrip_from_canon_sexp (const unsigned char *key, size_t keylen,
     211             :                          unsigned char *grip)
     212             : {
     213             :   gpg_error_t err;
     214             :   gcry_sexp_t sexp;
     215             : 
     216          21 :   if (!grip)
     217           0 :     return gpg_error (GPG_ERR_INV_VALUE);
     218          21 :   err = gcry_sexp_sscan (&sexp, NULL, (const char *)key, keylen);
     219          21 :   if (err)
     220           0 :     return err;
     221          21 :   if (!gcry_pk_get_keygrip (sexp, grip))
     222          21 :     err = gpg_error (GPG_ERR_INTERNAL);
     223          21 :   gcry_sexp_release (sexp);
     224          21 :   return err;
     225             : }
     226             : 
     227             : 
     228             : /* Compare two simple S-expressions like "(3:foo)".  Returns 0 if they
     229             :    are identical or !0 if they are not.  Note that this function can't
     230             :    be used for sorting. */
     231             : int
     232           6 : cmp_simple_canon_sexp (const unsigned char *a_orig,
     233             :                        const unsigned char *b_orig)
     234             : {
     235           6 :   const char *a = (const char *)a_orig;
     236           6 :   const char *b = (const char *)b_orig;
     237             :   unsigned long n1, n2;
     238             :   char *endp;
     239             : 
     240           6 :   if (!a && !b)
     241           0 :     return 0; /* Both are NULL, they are identical. */
     242           6 :   if (!a || !b)
     243           0 :     return 1; /* One is NULL, they are not identical. */
     244           6 :   if (*a != '(' || *b != '(')
     245           0 :     log_bug ("invalid S-exp in cmp_simple_canon_sexp\n");
     246             : 
     247           6 :   a++;
     248           6 :   n1 = strtoul (a, &endp, 10);
     249           6 :   a = endp;
     250           6 :   b++;
     251           6 :   n2 = strtoul (b, &endp, 10);
     252           6 :   b = endp;
     253             : 
     254           6 :   if (*a != ':' || *b != ':' )
     255           0 :     log_bug ("invalid S-exp in cmp_simple_canon_sexp\n");
     256           6 :   if (n1 != n2)
     257           0 :     return 1; /* Not the same. */
     258             : 
     259          12 :   for (a++, b++; n1; n1--, a++, b++)
     260           6 :     if (*a != *b)
     261           0 :       return 1; /* Not the same. */
     262           6 :   return 0;
     263             : }
     264             : 
     265             : 
     266             : /* Create a simple S-expression from the hex string at LINE.  Returns
     267             :    a newly allocated buffer with that canonical encoded S-expression
     268             :    or NULL in case of an error.  On return the number of characters
     269             :    scanned in LINE will be stored at NSCANNED.  This fucntions stops
     270             :    converting at the first character not representing a hexdigit. Odd
     271             :    numbers of hex digits are allowed; a leading zero is then
     272             :    assumed. If no characters have been found, NULL is returned.*/
     273             : unsigned char *
     274           0 : make_simple_sexp_from_hexstr (const char *line, size_t *nscanned)
     275             : {
     276             :   size_t n, len;
     277             :   const char *s;
     278             :   unsigned char *buf;
     279             :   unsigned char *p;
     280             :   char numbuf[50], *numbufp;
     281             :   size_t numbuflen;
     282             : 
     283           0 :   for (n=0, s=line; hexdigitp (s); s++, n++)
     284             :     ;
     285           0 :   if (nscanned)
     286           0 :     *nscanned = n;
     287           0 :   if (!n)
     288           0 :     return NULL;
     289           0 :   len = ((n+1) & ~0x01)/2;
     290           0 :   numbufp = smklen (numbuf, sizeof numbuf, len, &numbuflen);
     291           0 :   buf = xtrymalloc (1 + numbuflen + len + 1 + 1);
     292           0 :   if (!buf)
     293           0 :     return NULL;
     294           0 :   buf[0] = '(';
     295           0 :   p = (unsigned char *)stpcpy ((char *)buf+1, numbufp);
     296           0 :   s = line;
     297           0 :   if ((n&1))
     298             :     {
     299           0 :       *p++ = xtoi_1 (s);
     300           0 :       s++;
     301           0 :       n--;
     302             :     }
     303           0 :   for (; n > 1; n -=2, s += 2)
     304           0 :     *p++ = xtoi_2 (s);
     305           0 :   *p++ = ')';
     306           0 :   *p = 0; /* (Not really neaded.) */
     307             : 
     308           0 :   return buf;
     309             : }
     310             : 
     311             : 
     312             : /* Return the hash algorithm from a KSBA sig-val. SIGVAL is a
     313             :    canonical encoded S-expression.  Return 0 if the hash algorithm is
     314             :    not encoded in SIG-VAL or it is not supported by libgcrypt.  */
     315             : int
     316           2 : hash_algo_from_sigval (const unsigned char *sigval)
     317             : {
     318           2 :   const unsigned char *s = sigval;
     319             :   size_t n;
     320             :   int depth;
     321             :   char buffer[50];
     322             : 
     323           2 :   if (!s || *s != '(')
     324           0 :     return 0; /* Invalid S-expression.  */
     325           2 :   s++;
     326           2 :   n = snext (&s);
     327           2 :   if (!n)
     328           0 :     return 0; /* Invalid S-expression.  */
     329           2 :   if (!smatch (&s, n, "sig-val"))
     330           0 :     return 0; /* Not a sig-val.  */
     331           2 :   if (*s != '(')
     332           0 :     return 0; /* Invalid S-expression.  */
     333           2 :   s++;
     334             :   /* Skip over the algo+parameter list.  */
     335           2 :   depth = 1;
     336           2 :   if (sskip (&s, &depth) || depth)
     337           0 :     return 0; /* Invalid S-expression.  */
     338           2 :   if (*s != '(')
     339           1 :     return 0; /* No further list.  */
     340             :   /* Check whether this is (hash ALGO).  */
     341           1 :   s++;
     342           1 :   n = snext (&s);
     343           1 :   if (!n)
     344           0 :     return 0; /* Invalid S-expression.  */
     345           1 :   if (!smatch (&s, n, "hash"))
     346           0 :     return 0; /* Not a "hash" keyword.  */
     347           1 :   n = snext (&s);
     348           1 :   if (!n || n+1 >= sizeof (buffer))
     349           0 :     return 0; /* Algorithm string is missing or too long.  */
     350           1 :   memcpy (buffer, s, n);
     351           1 :   buffer[n] = 0;
     352             : 
     353           1 :   return gcry_md_map_name (buffer);
     354             : }
     355             : 
     356             : 
     357             : /* Create a public key S-expression for an RSA public key from the
     358             :    modulus M with length MLEN and the public exponent E with length
     359             :    ELEN.  Returns a newly allocated buffer of NULL in case of a memory
     360             :    allocation problem.  If R_LEN is not NULL, the length of the
     361             :    canonical S-expression is stored there. */
     362             : unsigned char *
     363           3 : make_canon_sexp_from_rsa_pk (const void *m_arg, size_t mlen,
     364             :                              const void *e_arg, size_t elen,
     365             :                              size_t *r_len)
     366             : {
     367           3 :   const unsigned char *m = m_arg;
     368           3 :   const unsigned char *e = e_arg;
     369           3 :   int m_extra = 0;
     370           3 :   int e_extra = 0;
     371             :   char mlen_str[35];
     372             :   char elen_str[35];
     373             :   unsigned char *keybuf, *p;
     374           3 :   const char part1[] = "(10:public-key(3:rsa(1:n";
     375           3 :   const char part2[] = ")(1:e";
     376           3 :   const char part3[] = ")))";
     377             : 
     378             :   /* Remove leading zeroes.  */
     379           3 :   for (; mlen && !*m; mlen--, m++)
     380             :     ;
     381           3 :   for (; elen && !*e; elen--, e++)
     382             :     ;
     383             : 
     384             :   /* Insert a leading zero if the number would be zero or interpreted
     385             :      as negative.  */
     386           3 :   if (!mlen || (m[0] & 0x80))
     387           2 :     m_extra = 1;
     388           3 :   if (!elen || (e[0] & 0x80))
     389           1 :     e_extra = 1;
     390             : 
     391             :   /* Build the S-expression.  */
     392           3 :   snprintf (mlen_str, sizeof mlen_str, "%u:", (unsigned int)mlen+m_extra);
     393           3 :   snprintf (elen_str, sizeof elen_str, "%u:", (unsigned int)elen+e_extra);
     394             : 
     395           3 :   keybuf = xtrymalloc (strlen (part1) + strlen (mlen_str) + mlen + m_extra
     396             :                        + strlen (part2) + strlen (elen_str) + elen + e_extra
     397             :                        + strlen (part3) + 1);
     398           3 :   if (!keybuf)
     399           0 :     return NULL;
     400             : 
     401           3 :   p = stpcpy (keybuf, part1);
     402           3 :   p = stpcpy (p, mlen_str);
     403           3 :   if (m_extra)
     404           2 :     *p++ = 0;
     405           3 :   memcpy (p, m, mlen);
     406           3 :   p += mlen;
     407           3 :   p = stpcpy (p, part2);
     408           3 :   p = stpcpy (p, elen_str);
     409           3 :   if (e_extra)
     410           1 :     *p++ = 0;
     411           3 :   memcpy (p, e, elen);
     412           3 :   p += elen;
     413           3 :   p = stpcpy (p, part3);
     414             : 
     415           3 :   if (r_len)
     416           3 :     *r_len = p - keybuf;
     417             : 
     418           3 :   return keybuf;
     419             : }
     420             : 
     421             : 
     422             : /* Return the parameters of a public RSA key expressed as an
     423             :    canonical encoded S-expression.  */
     424             : gpg_error_t
     425           3 : get_rsa_pk_from_canon_sexp (const unsigned char *keydata, size_t keydatalen,
     426             :                             unsigned char const **r_n, size_t *r_nlen,
     427             :                             unsigned char const **r_e, size_t *r_elen)
     428             : {
     429             :   gpg_error_t err;
     430             :   const unsigned char *buf, *tok;
     431             :   size_t buflen, toklen;
     432             :   int depth, last_depth1, last_depth2;
     433           3 :   const unsigned char *rsa_n = NULL;
     434           3 :   const unsigned char *rsa_e = NULL;
     435             :   size_t rsa_n_len, rsa_e_len;
     436             : 
     437           3 :   *r_n = NULL;
     438           3 :   *r_nlen = 0;
     439           3 :   *r_e = NULL;
     440           3 :   *r_elen = 0;
     441             : 
     442           3 :   buf = keydata;
     443           3 :   buflen = keydatalen;
     444           3 :   depth = 0;
     445           3 :   if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
     446           0 :     return err;
     447           3 :   if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
     448           0 :     return err;
     449           3 :   if (!tok || toklen != 10 || memcmp ("public-key", tok, toklen))
     450           0 :     return gpg_error (GPG_ERR_BAD_PUBKEY);
     451           3 :   if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
     452           0 :     return err;
     453           3 :   if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
     454           0 :     return err;
     455           3 :   if (!tok || toklen != 3 || memcmp ("rsa", tok, toklen))
     456           0 :     return gpg_error (GPG_ERR_WRONG_PUBKEY_ALGO);
     457             : 
     458           3 :   last_depth1 = depth;
     459          12 :   while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))
     460           9 :          && depth && depth >= last_depth1)
     461             :     {
     462           6 :       if (tok)
     463           0 :         return gpg_error (GPG_ERR_UNKNOWN_SEXP);
     464           6 :       if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
     465           0 :         return err;
     466           6 :       if (tok && toklen == 1)
     467             :         {
     468             :           const unsigned char **mpi;
     469             :           size_t *mpi_len;
     470             : 
     471           6 :           switch (*tok)
     472             :             {
     473           3 :             case 'n': mpi = &rsa_n; mpi_len = &rsa_n_len; break;
     474           3 :             case 'e': mpi = &rsa_e; mpi_len = &rsa_e_len; break;
     475           0 :             default:  mpi = NULL;   mpi_len = NULL; break;
     476             :             }
     477           6 :           if (mpi && *mpi)
     478           0 :             return gpg_error (GPG_ERR_DUP_VALUE);
     479             : 
     480           6 :           if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
     481           0 :             return err;
     482           6 :           if (tok && mpi)
     483             :             {
     484             :               /* Strip off leading zero bytes and save. */
     485           6 :               for (;toklen && !*tok; toklen--, tok++)
     486             :                 ;
     487           6 :               *mpi = tok;
     488           6 :               *mpi_len = toklen;
     489             :             }
     490             :         }
     491             : 
     492             :       /* Skip to the end of the list. */
     493           6 :       last_depth2 = depth;
     494           6 :       while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))
     495           6 :              && depth && depth >= last_depth2)
     496             :         ;
     497           6 :       if (err)
     498           0 :         return err;
     499             :     }
     500             : 
     501           3 :   if (err)
     502           0 :     return err;
     503             : 
     504           3 :   if (!rsa_n || !rsa_n_len || !rsa_e || !rsa_e_len)
     505           1 :     return gpg_error (GPG_ERR_BAD_PUBKEY);
     506             : 
     507           2 :   *r_n = rsa_n;
     508           2 :   *r_nlen = rsa_n_len;
     509           2 :   *r_e = rsa_e;
     510           2 :   *r_elen = rsa_e_len;
     511           2 :   return 0;
     512             : }
     513             : 
     514             : 
     515             : /* Return the algo of a public RSA expressed as an canonical encoded
     516             :    S-expression.  The return value is a statically allocated
     517             :    string.  On error that string is set to NULL. */
     518             : gpg_error_t
     519           0 : get_pk_algo_from_canon_sexp (const unsigned char *keydata, size_t keydatalen,
     520             :                              const char **r_algo)
     521             : {
     522             :   gpg_error_t err;
     523             :   const unsigned char *buf, *tok;
     524             :   size_t buflen, toklen;
     525             :   int depth;
     526             : 
     527           0 :   *r_algo = NULL;
     528             : 
     529           0 :   buf = keydata;
     530           0 :   buflen = keydatalen;
     531           0 :   depth = 0;
     532           0 :   if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
     533           0 :     return err;
     534           0 :   if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
     535           0 :     return err;
     536           0 :   if (!tok || toklen != 10 || memcmp ("public-key", tok, toklen))
     537           0 :     return gpg_error (GPG_ERR_BAD_PUBKEY);
     538           0 :   if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
     539           0 :     return err;
     540           0 :   if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
     541           0 :     return err;
     542           0 :   if (!tok)
     543           0 :     return gpg_error (GPG_ERR_BAD_PUBKEY);
     544             : 
     545           0 :   if (toklen == 3 && !memcmp ("rsa", tok, toklen))
     546           0 :     *r_algo = "rsa";
     547           0 :   else if (toklen == 3 && !memcmp ("dsa", tok, toklen))
     548           0 :     *r_algo = "dsa";
     549           0 :   else if (toklen == 3 && !memcmp ("elg", tok, toklen))
     550           0 :     *r_algo = "elg";
     551           0 :   else if (toklen == 5 && !memcmp ("ecdsa", tok, toklen))
     552           0 :     *r_algo = "ecdsa";
     553           0 :   else if (toklen == 5 && !memcmp ("eddsa", tok, toklen))
     554           0 :     *r_algo = "eddsa";
     555             :   else
     556           0 :     return gpg_error (GPG_ERR_PUBKEY_ALGO);
     557             : 
     558           0 :   return 0;
     559             : }
     560             : 
     561             : 
     562             : /* Return the algo of a public KEY of SEXP. */
     563             : int
     564          11 : get_pk_algo_from_key (gcry_sexp_t key)
     565             : {
     566             :   gcry_sexp_t list;
     567             :   const char *s;
     568             :   size_t n;
     569             :   char algoname[6];
     570          11 :   int algo = 0;
     571             : 
     572          11 :   list = gcry_sexp_nth (key, 1);
     573          11 :   if (!list)
     574           0 :     goto out;
     575          11 :   s = gcry_sexp_nth_data (list, 0, &n);
     576          11 :   if (!s)
     577           0 :     goto out;
     578          11 :   if (n >= sizeof (algoname))
     579           0 :     goto out;
     580          11 :   memcpy (algoname, s, n);
     581          11 :   algoname[n] = 0;
     582             : 
     583          11 :   algo = gcry_pk_map_name (algoname);
     584          11 :   if (algo == GCRY_PK_ECC)
     585             :     {
     586           3 :       gcry_sexp_t l1 = gcry_sexp_find_token (list, "flags", 0);
     587             :       int i;
     588             : 
     589           3 :       for (i = l1 ? gcry_sexp_length (l1)-1 : 0; i > 0; i--)
     590             :         {
     591           1 :           s = gcry_sexp_nth_data (l1, i, &n);
     592           1 :           if (!s)
     593           0 :             continue; /* Not a data element. */
     594             : 
     595           1 :           if (n == 5 && !memcmp (s, "eddsa", 5))
     596             :             {
     597           1 :               algo = GCRY_PK_EDDSA;
     598           1 :               break;
     599             :             }
     600             :         }
     601           3 :       gcry_sexp_release (l1);
     602             :     }
     603             : 
     604             :  out:
     605          11 :   gcry_sexp_release (list);
     606             : 
     607          11 :   return algo;
     608             : }

Generated by: LCOV version 1.11