Coverage Report

Created: 2026-01-09 06:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gnupg/common/sexputil.c
Line
Count
Source
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 <https://www.gnu.org/licenses/>.
29
 */
30
31
/* This file implements a few utility functions useful when working
32
   with canonical encrypted S-expressions (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
sexp_to_string (gcry_sexp_t sexp)
55
0
{
56
0
  size_t n;
57
0
  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
0
}
73
74
75
/* Return a malloced string with the S-expression CANON in advanced
76
   format.  Returns NULL on error.  */
77
char *
78
canon_sexp_to_string (const unsigned char *canon, size_t canonlen)
79
0
{
80
0
  size_t n;
81
0
  gcry_sexp_t sexp;
82
0
  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
0
}
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
log_printcanon (const char *text, const unsigned char *sexp, size_t sexplen)
102
0
{
103
0
  if (text && *text)
104
0
    log_debug ("%s ", text);
105
0
  if (sexp)
106
0
    {
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
0
    }
111
0
  if (text)
112
0
    log_printf ("\n");
113
0
}
114
115
116
/* Print the gcrypt S-expression 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
log_printsexp (const char *text, gcry_sexp_t sexp)
122
0
{
123
0
  if (text && *text)
124
0
    log_debug ("%s ", text);
125
0
  if (sexp)
126
0
    {
127
0
      char *buf = sexp_to_string (sexp);
128
0
      log_printf ("%s", buf? buf : "[invalid S-expression]");
129
0
      xfree (buf);
130
0
    }
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
make_canon_sexp (gcry_sexp_t sexp, unsigned char **r_buffer, size_t *r_buflen)
145
0
{
146
0
  size_t len;
147
0
  unsigned char *buf;
148
149
0
  *r_buffer = NULL;
150
0
  if (r_buflen)
151
0
    *r_buflen = 0;;
152
153
0
  len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, NULL, 0);
154
0
  if (!len)
155
0
    return gpg_error (GPG_ERR_BUG);
156
0
  buf = gcry_is_secure (sexp)? xtrymalloc_secure (len) : xtrymalloc (len);
157
0
  if (!buf)
158
0
    return gpg_error_from_syserror ();
159
0
  len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, buf, len);
160
0
  if (!len)
161
0
    return gpg_error (GPG_ERR_BUG);
162
163
0
  *r_buffer = buf;
164
0
  if (r_buflen)
165
0
    *r_buflen = len;
166
167
0
  return 0;
168
0
}
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
make_canon_sexp_pad (gcry_sexp_t sexp, int secure,
175
                     unsigned char **r_buffer, size_t *r_buflen)
176
0
{
177
0
  size_t len;
178
0
  unsigned char *buf;
179
180
0
  *r_buffer = NULL;
181
0
  if (r_buflen)
182
0
    *r_buflen = 0;;
183
184
0
  len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, NULL, 0);
185
0
  if (!len)
186
0
    return gpg_error (GPG_ERR_BUG);
187
0
  len += (8 - len % 8) % 8;
188
0
  buf = secure? xtrycalloc_secure (1, len) : xtrycalloc (1, len);
189
0
  if (!buf)
190
0
    return gpg_error_from_syserror ();
191
0
  if (!gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, buf, len))
192
0
    return gpg_error (GPG_ERR_BUG);
193
194
0
  *r_buffer = buf;
195
0
  if (r_buflen)
196
0
    *r_buflen = len;
197
198
0
  return 0;
199
0
}
200
201
/* Return the so called "keygrip" which is the SHA-1 hash of the
202
   public key parameters expressed in a way dependent 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
keygrip_from_canon_sexp (const unsigned char *key, size_t keylen,
211
                         unsigned char *grip)
212
0
{
213
0
  gpg_error_t err;
214
0
  gcry_sexp_t sexp;
215
216
0
  if (!grip)
217
0
    return gpg_error (GPG_ERR_INV_VALUE);
218
0
  err = gcry_sexp_sscan (&sexp, NULL, (const char *)key, keylen);
219
0
  if (err)
220
0
    return err;
221
0
  if (!gcry_pk_get_keygrip (sexp, grip))
222
0
    err = gpg_error (GPG_ERR_INTERNAL);
223
0
  gcry_sexp_release (sexp);
224
0
  return err;
225
0
}
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
cmp_simple_canon_sexp (const unsigned char *a_orig,
233
                       const unsigned char *b_orig)
234
0
{
235
0
  const char *a = (const char *)a_orig;
236
0
  const char *b = (const char *)b_orig;
237
0
  unsigned long n1, n2;
238
0
  char *endp;
239
240
0
  if (!a && !b)
241
0
    return 0; /* Both are NULL, they are identical. */
242
0
  if (!a || !b)
243
0
    return 1; /* One is NULL, they are not identical. */
244
0
  if (*a != '(' || *b != '(')
245
0
    log_bug ("invalid S-exp in cmp_simple_canon_sexp\n");
246
247
0
  a++;
248
0
  n1 = strtoul (a, &endp, 10);
249
0
  a = endp;
250
0
  b++;
251
0
  n2 = strtoul (b, &endp, 10);
252
0
  b = endp;
253
254
0
  if (*a != ':' || *b != ':' )
255
0
    log_bug ("invalid S-exp in cmp_simple_canon_sexp\n");
256
0
  if (n1 != n2)
257
0
    return 1; /* Not the same. */
258
259
0
  for (a++, b++; n1; n1--, a++, b++)
260
0
    if (*a != *b)
261
0
      return 1; /* Not the same. */
262
0
  return 0;
263
0
}
264
265
266
267
/* Helper for cmp_canon_sexp.  */
268
static int
269
cmp_canon_sexp_def_tcmp (void *ctx, int depth,
270
                         const unsigned char *aval, size_t alen,
271
                         const unsigned char *bval, size_t blen)
272
0
{
273
0
  (void)ctx;
274
0
  (void)depth;
275
276
0
  if (alen > blen)
277
0
    return 1;
278
0
  else if (alen < blen)
279
0
    return -1;
280
0
  else
281
0
    return memcmp (aval, bval, alen);
282
0
}
283
284
285
/* Compare the two canonical encoded s-expressions A with maximum
286
 * length ALEN and B with maximum length BLEN.
287
 *
288
 * Returns 0 if they match.
289
 *
290
 * If TCMP is NULL, this is not different really different from a
291
 * memcmp but does not consider any garbage after the last closing
292
 * parentheses.
293
 *
294
 * If TCMP is not NULL, it is expected to be a function to compare the
295
 * values of each token.  TCMP is called for each token while parsing
296
 * the s-expressions until TCMP return a non-zero value.  Here the CTX
297
 * receives the provided value TCMPCTX, DEPTH is the number of
298
 * currently open parentheses and (AVAL,ALEN) and (BVAL,BLEN) the
299
 * values of the current token.  TCMP needs to return zero to indicate
300
 * that the tokens match.  */
301
int
302
cmp_canon_sexp (const unsigned char *a, size_t alen,
303
                const unsigned char *b, size_t blen,
304
                int (*tcmp)(void *ctx, int depth,
305
                            const unsigned char *aval, size_t avallen,
306
                            const unsigned char *bval, size_t bvallen),
307
                void *tcmpctx)
308
0
{
309
0
  const unsigned char *a_buf, *a_tok;
310
0
  const unsigned char *b_buf, *b_tok;
311
0
  size_t a_buflen, a_toklen;
312
0
  size_t b_buflen, b_toklen;
313
0
  int a_depth, b_depth, ret;
314
315
0
  if ((!a && !b) || (!alen && !blen))
316
0
    return 0; /* Both are NULL, they are identical. */
317
0
  if (!a || !b)
318
0
    return !!a - !!b; /* One is NULL, they are not identical. */
319
0
  if (*a != '(' || *b != '(')
320
0
    log_bug ("invalid S-exp in %s\n", __func__);
321
322
0
  if (!tcmp)
323
0
    tcmp = cmp_canon_sexp_def_tcmp;
324
325
0
  a_depth = 0;
326
0
  a_buf = a;
327
0
  a_buflen = alen;
328
0
  b_depth = 0;
329
0
  b_buf = b;
330
0
  b_buflen = blen;
331
332
0
  for (;;)
333
0
    {
334
0
      if (parse_sexp (&a_buf, &a_buflen, &a_depth, &a_tok, &a_toklen))
335
0
        return -1;  /* A is invalid.  */
336
0
      if (parse_sexp (&b_buf, &b_buflen, &b_depth, &b_tok, &b_toklen))
337
0
        return -1;  /* B is invalid.  */
338
0
      if (!a_depth && !b_depth)
339
0
        return 0; /* End of both expressions - they match.  */
340
0
      if (a_depth != b_depth)
341
0
        return a_depth - b_depth; /* Not the same structure   */
342
0
      if (!a_tok && !b_tok)
343
0
        ; /* parens */
344
0
      else if (a_tok && b_tok)
345
0
        {
346
0
          ret = tcmp (tcmpctx, a_depth, a_tok, a_toklen, b_tok, b_toklen);
347
0
          if (ret)
348
0
            return ret;  /* Mismatch */
349
0
        }
350
0
      else /* One has a paren other has not.  */
351
0
        return !!a_tok - !!b_tok;
352
0
    }
353
0
}
354
355
356
/* Create a simple S-expression from the hex string at LINE.  Returns
357
   a newly allocated buffer with that canonical encoded S-expression
358
   or NULL in case of an error.  On return the number of characters
359
   scanned in LINE will be stored at NSCANNED.  This functions stops
360
   converting at the first character not representing a hexdigit. Odd
361
   numbers of hex digits are allowed; a leading zero is then
362
   assumed. If no characters have been found, NULL is returned.*/
363
unsigned char *
364
make_simple_sexp_from_hexstr (const char *line, size_t *nscanned)
365
0
{
366
0
  size_t n, len;
367
0
  const char *s;
368
0
  unsigned char *buf;
369
0
  unsigned char *p;
370
0
  char numbuf[50], *numbufp;
371
0
  size_t numbuflen;
372
373
0
  for (n=0, s=line; hexdigitp (s); s++, n++)
374
0
    ;
375
0
  if (nscanned)
376
0
    *nscanned = n;
377
0
  if (!n)
378
0
    return NULL;
379
0
  len = ((n+1) & ~0x01)/2;
380
0
  numbufp = smklen (numbuf, sizeof numbuf, len, &numbuflen);
381
0
  buf = xtrymalloc (1 + numbuflen + len + 1 + 1);
382
0
  if (!buf)
383
0
    return NULL;
384
0
  buf[0] = '(';
385
0
  p = (unsigned char *)stpcpy ((char *)buf+1, numbufp);
386
0
  s = line;
387
0
  if ((n&1))
388
0
    {
389
0
      *p++ = xtoi_1 (s);
390
0
      s++;
391
0
      n--;
392
0
    }
393
0
  for (; n > 1; n -=2, s += 2)
394
0
    *p++ = xtoi_2 (s);
395
0
  *p++ = ')';
396
0
  *p = 0; /* (Not really needed.) */
397
398
0
  return buf;
399
0
}
400
401
402
/* Return the hash algorithm from a KSBA sig-val. SIGVAL is a
403
   canonical encoded S-expression.  Return 0 if the hash algorithm is
404
   not encoded in SIG-VAL or it is not supported by libgcrypt.  */
405
int
406
hash_algo_from_sigval (const unsigned char *sigval)
407
0
{
408
0
  const unsigned char *s = sigval;
409
0
  size_t n;
410
0
  int depth;
411
0
  char buffer[50];
412
413
0
  if (!s || *s != '(')
414
0
    return 0; /* Invalid S-expression.  */
415
0
  s++;
416
0
  n = snext (&s);
417
0
  if (!n)
418
0
    return 0; /* Invalid S-expression.  */
419
0
  if (!smatch (&s, n, "sig-val"))
420
0
    return 0; /* Not a sig-val.  */
421
0
  if (*s != '(')
422
0
    return 0; /* Invalid S-expression.  */
423
0
  s++;
424
  /* Skip over the algo+parameter list.  */
425
0
  depth = 1;
426
0
  if (sskip (&s, &depth) || depth)
427
0
    return 0; /* Invalid S-expression.  */
428
0
  if (*s != '(')
429
0
    return 0; /* No further list.  */
430
  /* Check whether this is (hash ALGO).  */
431
0
  s++;
432
0
  n = snext (&s);
433
0
  if (!n)
434
0
    return 0; /* Invalid S-expression.  */
435
0
  if (!smatch (&s, n, "hash"))
436
0
    return 0; /* Not a "hash" keyword.  */
437
0
  n = snext (&s);
438
0
  if (!n || n+1 >= sizeof (buffer))
439
0
    return 0; /* Algorithm string is missing or too long.  */
440
0
  memcpy (buffer, s, n);
441
0
  buffer[n] = 0;
442
443
0
  return gcry_md_map_name (buffer);
444
0
}
445
446
447
/* Create a public key S-expression for an RSA public key from the
448
   modulus M with length MLEN and the public exponent E with length
449
   ELEN.  Returns a newly allocated buffer of NULL in case of a memory
450
   allocation problem.  If R_LEN is not NULL, the length of the
451
   canonical S-expression is stored there. */
452
unsigned char *
453
make_canon_sexp_from_rsa_pk (const void *m_arg, size_t mlen,
454
                             const void *e_arg, size_t elen,
455
                             size_t *r_len)
456
0
{
457
0
  const unsigned char *m = m_arg;
458
0
  const unsigned char *e = e_arg;
459
0
  int m_extra = 0;
460
0
  int e_extra = 0;
461
0
  char mlen_str[35];
462
0
  char elen_str[35];
463
0
  unsigned char *keybuf, *p;
464
0
  const char part1[] = "(10:public-key(3:rsa(1:n";
465
0
  const char part2[] = ")(1:e";
466
0
  const char part3[] = ")))";
467
468
  /* Remove leading zeroes.  */
469
0
  for (; mlen && !*m; mlen--, m++)
470
0
    ;
471
0
  for (; elen && !*e; elen--, e++)
472
0
    ;
473
474
  /* Insert a leading zero if the number would be zero or interpreted
475
     as negative.  */
476
0
  if (!mlen || (m[0] & 0x80))
477
0
    m_extra = 1;
478
0
  if (!elen || (e[0] & 0x80))
479
0
    e_extra = 1;
480
481
  /* Build the S-expression.  */
482
0
  snprintf (mlen_str, sizeof mlen_str, "%u:", (unsigned int)mlen+m_extra);
483
0
  snprintf (elen_str, sizeof elen_str, "%u:", (unsigned int)elen+e_extra);
484
485
0
  keybuf = xtrymalloc (strlen (part1) + strlen (mlen_str) + mlen + m_extra
486
0
                       + strlen (part2) + strlen (elen_str) + elen + e_extra
487
0
                       + strlen (part3) + 1);
488
0
  if (!keybuf)
489
0
    return NULL;
490
491
0
  p = stpcpy (keybuf, part1);
492
0
  p = stpcpy (p, mlen_str);
493
0
  if (m_extra)
494
0
    *p++ = 0;
495
0
  memcpy (p, m, mlen);
496
0
  p += mlen;
497
0
  p = stpcpy (p, part2);
498
0
  p = stpcpy (p, elen_str);
499
0
  if (e_extra)
500
0
    *p++ = 0;
501
0
  memcpy (p, e, elen);
502
0
  p += elen;
503
0
  p = stpcpy (p, part3);
504
505
0
  if (r_len)
506
0
    *r_len = p - keybuf;
507
508
0
  return keybuf;
509
0
}
510
511
512
/* Return the parameters of a public RSA key expressed as an
513
   canonical encoded S-expression.  */
514
gpg_error_t
515
get_rsa_pk_from_canon_sexp (const unsigned char *keydata, size_t keydatalen,
516
                            unsigned char const **r_n, size_t *r_nlen,
517
                            unsigned char const **r_e, size_t *r_elen)
518
0
{
519
0
  gpg_error_t err;
520
0
  const unsigned char *buf, *tok;
521
0
  size_t buflen, toklen;
522
0
  int depth, last_depth1, last_depth2;
523
0
  const unsigned char *rsa_n = NULL;
524
0
  const unsigned char *rsa_e = NULL;
525
0
  size_t rsa_n_len, rsa_e_len;
526
527
0
  *r_n = NULL;
528
0
  *r_nlen = 0;
529
0
  *r_e = NULL;
530
0
  *r_elen = 0;
531
532
0
  buf = keydata;
533
0
  buflen = keydatalen;
534
0
  depth = 0;
535
0
  if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
536
0
    return err;
537
0
  if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
538
0
    return err;
539
0
  if (!tok || !((toklen == 10 && !memcmp ("public-key", tok, toklen))
540
0
                || (toklen == 11 && !memcmp ("private-key", tok, toklen))))
541
0
    return gpg_error (GPG_ERR_BAD_PUBKEY);
542
0
  if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
543
0
    return err;
544
0
  if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
545
0
    return err;
546
0
  if (!tok || toklen != 3 || memcmp ("rsa", tok, toklen))
547
0
    return gpg_error (GPG_ERR_WRONG_PUBKEY_ALGO);
548
549
0
  last_depth1 = depth;
550
0
  while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))
551
0
         && depth && depth >= last_depth1)
552
0
    {
553
0
      if (tok)
554
0
        return gpg_error (GPG_ERR_UNKNOWN_SEXP);
555
0
      if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
556
0
        return err;
557
0
      if (tok && toklen == 1)
558
0
        {
559
0
          const unsigned char **mpi;
560
0
          size_t *mpi_len;
561
562
0
          switch (*tok)
563
0
            {
564
0
            case 'n': mpi = &rsa_n; mpi_len = &rsa_n_len; break;
565
0
            case 'e': mpi = &rsa_e; mpi_len = &rsa_e_len; break;
566
0
            default:  mpi = NULL;   mpi_len = NULL; break;
567
0
            }
568
0
          if (mpi && *mpi)
569
0
            return gpg_error (GPG_ERR_DUP_VALUE);
570
571
0
          if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
572
0
            return err;
573
0
          if (tok && mpi)
574
0
            {
575
              /* Strip off leading zero bytes and save. */
576
0
              for (;toklen && !*tok; toklen--, tok++)
577
0
                ;
578
0
              *mpi = tok;
579
0
              *mpi_len = toklen;
580
0
            }
581
0
        }
582
583
      /* Skip to the end of the list. */
584
0
      last_depth2 = depth;
585
0
      while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))
586
0
             && depth && depth >= last_depth2)
587
0
        ;
588
0
      if (err)
589
0
        return err;
590
0
    }
591
592
0
  if (err)
593
0
    return err;
594
595
0
  if (!rsa_n || !rsa_n_len || !rsa_e || !rsa_e_len)
596
0
    return gpg_error (GPG_ERR_BAD_PUBKEY);
597
598
0
  *r_n = rsa_n;
599
0
  *r_nlen = rsa_n_len;
600
0
  *r_e = rsa_e;
601
0
  *r_elen = rsa_e_len;
602
0
  return 0;
603
0
}
604
605
606
/* Return the public key parameter Q of a public RSA or ECC key
607
 * expressed as an canonical encoded S-expression.  */
608
gpg_error_t
609
get_ecc_q_from_canon_sexp (const unsigned char *keydata, size_t keydatalen,
610
                           unsigned char const **r_q, size_t *r_qlen)
611
0
{
612
0
  gpg_error_t err;
613
0
  const unsigned char *buf, *tok;
614
0
  size_t buflen, toklen;
615
0
  int depth, last_depth1, last_depth2;
616
0
  const unsigned char *ecc_q = NULL;
617
0
  size_t ecc_q_len = 0;
618
619
0
  *r_q = NULL;
620
0
  *r_qlen = 0;
621
622
0
  buf = keydata;
623
0
  buflen = keydatalen;
624
0
  depth = 0;
625
0
  if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
626
0
    return err;
627
0
  if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
628
0
    return err;
629
0
  if (!tok || toklen != 10 || memcmp ("public-key", tok, toklen))
630
0
    return gpg_error (GPG_ERR_BAD_PUBKEY);
631
0
  if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
632
0
    return err;
633
0
  if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
634
0
    return err;
635
0
  if (tok && toklen == 3 && !memcmp ("ecc", tok, toklen))
636
0
    ;
637
0
  else if (tok && toklen == 5 && (!memcmp ("ecdsa", tok, toklen)
638
0
                                  || !memcmp ("eddsa", tok, toklen)))
639
0
    ;
640
0
  else
641
0
    return gpg_error (GPG_ERR_WRONG_PUBKEY_ALGO);
642
643
0
  last_depth1 = depth;
644
0
  while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))
645
0
         && depth && depth >= last_depth1)
646
0
    {
647
0
      if (tok)
648
0
        return gpg_error (GPG_ERR_UNKNOWN_SEXP);
649
0
      if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
650
0
        return err;
651
0
      if (tok && toklen == 1)
652
0
        {
653
0
          const unsigned char **mpi;
654
0
          size_t *mpi_len;
655
656
0
          switch (*tok)
657
0
            {
658
0
            case 'q': mpi = &ecc_q; mpi_len = &ecc_q_len; break;
659
0
            default:  mpi = NULL;   mpi_len = NULL; break;
660
0
            }
661
0
          if (mpi && *mpi)
662
0
            return gpg_error (GPG_ERR_DUP_VALUE);
663
664
0
          if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
665
0
            return err;
666
0
          if (tok && mpi)
667
0
            {
668
0
              *mpi = tok;
669
0
              *mpi_len = toklen;
670
0
            }
671
0
        }
672
673
      /* Skip to the end of the list. */
674
0
      last_depth2 = depth;
675
0
      while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))
676
0
             && depth && depth >= last_depth2)
677
0
        ;
678
0
      if (err)
679
0
        return err;
680
0
    }
681
682
0
  if (err)
683
0
    return err;
684
685
0
  if (!ecc_q || !ecc_q_len)
686
0
    return gpg_error (GPG_ERR_BAD_PUBKEY);
687
688
0
  *r_q = ecc_q;
689
0
  *r_qlen = ecc_q_len;
690
0
  return 0;
691
0
}
692
693
694
/* Return an uncompressed point (X,Y) in P at R_BUF as a malloced
695
 * buffer with its byte length stored at R_BUFLEN.  May not be used
696
 * for sensitive data. */
697
static gpg_error_t
698
ec2os (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t p,
699
       unsigned char **r_buf, unsigned int *r_buflen)
700
0
{
701
0
  gpg_error_t err;
702
0
  int pbytes = (mpi_get_nbits (p)+7)/8;
703
0
  size_t n;
704
0
  unsigned char *buf, *ptr;
705
706
0
  *r_buf = NULL;
707
0
  *r_buflen = 0;
708
709
0
  buf = xtrymalloc (1 + 2*pbytes);
710
0
  if (!buf)
711
0
    return gpg_error_from_syserror ();
712
0
  *buf = 04; /* Uncompressed point.  */
713
0
  ptr = buf+1;
714
0
  err = gcry_mpi_print (GCRYMPI_FMT_USG, ptr, pbytes, &n, x);
715
0
  if (err)
716
0
    {
717
0
      xfree (buf);
718
0
      return err;
719
0
    }
720
0
  if (n < pbytes)
721
0
    {
722
0
      memmove (ptr+(pbytes-n), ptr, n);
723
0
      memset (ptr, 0, (pbytes-n));
724
0
    }
725
0
  ptr += pbytes;
726
0
  err = gcry_mpi_print (GCRYMPI_FMT_USG, ptr, pbytes, &n, y);
727
0
  if (err)
728
0
    {
729
0
      xfree (buf);
730
0
      return err;
731
0
    }
732
0
  if (n < pbytes)
733
0
    {
734
0
      memmove (ptr+(pbytes-n), ptr, n);
735
0
      memset (ptr, 0, (pbytes-n));
736
0
    }
737
738
0
  *r_buf = buf;
739
0
  *r_buflen = 1 + 2*pbytes;
740
0
  return 0;
741
0
}
742
743
744
/* Convert the ECC parameter Q in the canonical s-expression
745
 * (KEYDATA,KEYDATALEN) to uncompressed form.  On success and if a
746
 * conversion was done, the new canonical encoded s-expression is
747
 * returned at (R_NEWKEYDAT,R_NEWKEYDATALEN); if a conversion was not
748
 * required (NULL,0) is stored there.  On error an error code is
749
 * returned.  The function may take any kind of key but will only do
750
 * the conversion for ECC curves where compression is supported.  */
751
gpg_error_t
752
uncompress_ecc_q_in_canon_sexp (const unsigned char *keydata,
753
                                size_t keydatalen,
754
                                unsigned char **r_newkeydata,
755
                                size_t *r_newkeydatalen)
756
0
{
757
0
  gpg_error_t err;
758
0
  const unsigned char *buf, *tok;
759
0
  size_t buflen, toklen, n;
760
0
  int depth, last_depth1, last_depth2;
761
0
  const unsigned char *q_ptr;     /* Points to the value of "q".      */
762
0
  size_t q_ptrlen;                /* Remaining length in KEYDATA.     */
763
0
  size_t q_toklen;                /* Q's length including prefix.     */
764
0
  const unsigned char *curve_ptr; /* Points to the value of "curve".  */
765
0
  size_t curve_ptrlen;            /* Remaining length in KEYDATA.     */
766
0
  gcry_mpi_t x, y;                /* Point Q            */
767
0
  gcry_mpi_t p, a, b;             /* Curve parameters.  */
768
0
  gcry_mpi_t x3, t, p1_4;         /* Helper             */
769
0
  int y_bit;
770
0
  unsigned char *qvalue;          /* Q in uncompressed form.  */
771
0
  unsigned int   qvaluelen;
772
0
  unsigned char *dst;             /* Helper */
773
0
  char lenstr[35];                /* Helper for a length prefix.  */
774
775
0
  *r_newkeydata = NULL;
776
0
  *r_newkeydatalen = 0;
777
778
0
  buf = keydata;
779
0
  buflen = keydatalen;
780
0
  depth = 0;
781
0
  if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
782
0
    return err;
783
0
  if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
784
0
    return err;
785
0
  if (!tok)
786
0
    return gpg_error (GPG_ERR_BAD_PUBKEY);
787
0
  else if (toklen == 10 && !memcmp ("public-key", tok, toklen))
788
0
    ;
789
0
  else if (toklen == 11 && !memcmp ("private-key", tok, toklen))
790
0
    ;
791
0
  else if (toklen == 20 && !memcmp ("shadowed-private-key", tok, toklen))
792
0
    ;
793
0
  else
794
0
    return gpg_error (GPG_ERR_BAD_PUBKEY);
795
796
0
  if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
797
0
    return err;
798
0
  if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
799
0
    return err;
800
801
0
  if (tok && toklen == 3 && !memcmp ("ecc", tok, toklen))
802
0
    ;
803
0
  else if (tok && toklen == 5 && !memcmp ("ecdsa", tok, toklen))
804
0
    ;
805
0
  else
806
0
    return 0; /* Other algo - no need for conversion.  */
807
808
0
  last_depth1 = depth;
809
0
  q_ptr = curve_ptr = NULL;
810
0
  q_ptrlen = 0; /*(silence cc warning)*/
811
0
  while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))
812
0
         && depth && depth >= last_depth1)
813
0
    {
814
0
      if (tok)
815
0
        return gpg_error (GPG_ERR_UNKNOWN_SEXP);
816
0
      if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
817
0
        return err;
818
0
      if (tok && toklen == 1 && *tok == 'q' && !q_ptr)
819
0
        {
820
0
          q_ptr = buf;
821
0
          q_ptrlen = buflen;
822
0
        }
823
0
      else if (tok && toklen == 5 && !memcmp (tok, "curve", 5) && !curve_ptr)
824
0
        {
825
0
          curve_ptr = buf;
826
0
          curve_ptrlen = buflen;
827
0
        }
828
829
0
      if (q_ptr && curve_ptr)
830
0
        break;  /* We got all what we need.  */
831
832
      /* Skip to the end of the list. */
833
0
      last_depth2 = depth;
834
0
      while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))
835
0
             && depth && depth >= last_depth2)
836
0
        ;
837
0
      if (err)
838
0
        return err;
839
0
    }
840
0
  if (err)
841
0
    return err;
842
843
0
  if (!q_ptr)
844
0
    return 0;  /* No Q - nothing to do.  */
845
846
  /* Get Q's value and check whether uncompressing is at all required.  */
847
0
  buf = q_ptr;
848
0
  buflen = q_ptrlen;
849
0
  if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
850
0
    return err;
851
0
  if (toklen < 2 || !(*tok == 0x02 || *tok == 0x03))
852
0
    return 0;  /* Invalid length or not compressed.  */
853
0
  q_toklen = buf - q_ptr;  /* We want the length with the prefix.  */
854
855
  /* Put the x-coordinate of q into X and remember the y bit */
856
0
  y_bit = (*tok == 0x03);
857
0
  err = gcry_mpi_scan (&x, GCRYMPI_FMT_USG, tok+1, toklen-1, NULL);
858
0
  if (err)
859
0
    return err;
860
861
  /* For uncompressing we need to know the curve.  */
862
0
  if (!curve_ptr)
863
0
    {
864
0
      gcry_mpi_release (x);
865
0
      return gpg_error (GPG_ERR_INV_CURVE);
866
0
    }
867
0
  buf = curve_ptr;
868
0
  buflen = curve_ptrlen;
869
0
  if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
870
0
    {
871
0
      gcry_mpi_release (x);
872
0
      return err;
873
0
    }
874
875
0
  {
876
0
    char name[50];
877
0
    gcry_sexp_t curveparam;
878
879
0
    if (toklen + 1 > sizeof name)
880
0
      {
881
0
        gcry_mpi_release (x);
882
0
        return gpg_error (GPG_ERR_TOO_LARGE);
883
0
      }
884
0
    mem2str (name, tok, toklen+1);
885
0
    curveparam = gcry_pk_get_param (GCRY_PK_ECC, name);
886
0
    if (!curveparam)
887
0
      {
888
0
        gcry_mpi_release (x);
889
0
        return gpg_error (GPG_ERR_UNKNOWN_CURVE);
890
0
      }
891
892
0
    err = gcry_sexp_extract_param (curveparam, NULL, "pab", &p, &a, &b, NULL);
893
0
    gcry_sexp_release (curveparam);
894
0
    if (err)
895
0
      {
896
0
        gcry_mpi_release (x);
897
0
        return gpg_error (GPG_ERR_INTERNAL);
898
0
      }
899
0
  }
900
901
0
  if (!mpi_test_bit (p, 1))
902
0
    {
903
      /* No support for point compression for this curve.  */
904
0
      gcry_mpi_release (x);
905
0
      gcry_mpi_release (p);
906
0
      gcry_mpi_release (a);
907
0
      gcry_mpi_release (b);
908
0
      return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
909
0
    }
910
911
  /*
912
   * Recover Y.  The Weierstrass curve: y^2 = x^3 + a*x + b
913
   */
914
915
0
  x3 = mpi_new (0);
916
0
  t = mpi_new (0);
917
0
  p1_4 = mpi_new (0);
918
0
  y = mpi_new (0);
919
920
  /* Compute right hand side.  */
921
0
  mpi_powm (x3, x, GCRYMPI_CONST_THREE, p);
922
0
  mpi_mul (t, a, x);
923
0
  mpi_mod (t, t, p);
924
0
  mpi_add (t, t, b);
925
0
  mpi_mod (t, t, p);
926
0
  mpi_add (t, t, x3);
927
0
  mpi_mod (t, t, p);
928
929
  /*
930
   * When p mod 4 = 3, modular square root of A can be computed by
931
   * A^((p+1)/4) mod p
932
   */
933
934
  /* Compute (p+1)/4 into p1_4 */
935
0
  mpi_rshift (p1_4, p, 2);
936
0
  mpi_add_ui (p1_4, p1_4, 1);
937
938
0
  mpi_powm (y, t, p1_4, p);
939
940
0
  if (y_bit != mpi_test_bit (y, 0))
941
0
    mpi_sub (y, p, y);
942
943
0
  gcry_mpi_release (p1_4);
944
0
  gcry_mpi_release (t);
945
0
  gcry_mpi_release (x3);
946
0
  gcry_mpi_release (a);
947
0
  gcry_mpi_release (b);
948
949
0
  err = ec2os (x, y, p, &qvalue, &qvaluelen);
950
0
  gcry_mpi_release (x);
951
0
  gcry_mpi_release (y);
952
0
  gcry_mpi_release (p);
953
0
  if (err)
954
0
    return err;
955
956
0
  snprintf (lenstr, sizeof lenstr, "%u:", (unsigned int)qvaluelen);
957
  /* Note that for simplicity we do not subtract the old length of Q
958
   * for the new buffer.  */
959
0
  *r_newkeydata = xtrymalloc (qvaluelen + strlen(lenstr) + qvaluelen);
960
0
  if (!*r_newkeydata)
961
0
    return gpg_error_from_syserror ();
962
0
  dst = *r_newkeydata;
963
964
0
  n = q_ptr - keydata;
965
0
  memcpy (dst, keydata, n);         /* Copy first part of original data.  */
966
0
  dst += n;
967
968
0
  n = strlen (lenstr);
969
0
  memcpy (dst, lenstr, n);          /* Copy new prefix of Q's value.  */
970
0
  dst += n;
971
972
0
  memcpy (dst, qvalue, qvaluelen);  /* Copy new value of Q.    */
973
0
  dst += qvaluelen;
974
975
0
  log_assert (q_toklen < q_ptrlen);
976
0
  n = q_ptrlen - q_toklen;
977
0
  memcpy (dst, q_ptr + q_toklen, n);/* Copy rest of original data.  */
978
0
  dst += n;
979
980
0
  *r_newkeydatalen = dst - *r_newkeydata;
981
982
0
  xfree (qvalue);
983
984
0
  return 0;
985
0
}
986
987
988
/* Return the algo of a public KEY of SEXP. */
989
int
990
get_pk_algo_from_key (gcry_sexp_t key)
991
0
{
992
0
  gcry_sexp_t list;
993
0
  const char *s;
994
0
  size_t n;
995
0
  char algoname[10];
996
0
  int algo = 0;
997
998
0
  list = gcry_sexp_nth (key, 1);
999
0
  if (!list)
1000
0
    goto out;
1001
0
  s = gcry_sexp_nth_data (list, 0, &n);
1002
0
  if (!s)
1003
0
    goto out;
1004
0
  if (n >= sizeof (algoname))
1005
0
    goto out;
1006
0
  memcpy (algoname, s, n);
1007
0
  algoname[n] = 0;
1008
1009
0
  algo = gcry_pk_map_name (algoname);
1010
0
  if (algo == GCRY_PK_ECC)
1011
0
    {
1012
0
      gcry_sexp_t l1;
1013
0
      int i;
1014
1015
0
      l1 = gcry_sexp_find_token (list, "flags", 0);
1016
0
      for (i = l1 ? gcry_sexp_length (l1)-1 : 0; i > 0; i--)
1017
0
  {
1018
0
    s = gcry_sexp_nth_data (l1, i, &n);
1019
0
    if (!s)
1020
0
      continue; /* Not a data element. */
1021
1022
0
    if (n == 5 && !memcmp (s, "eddsa", 5))
1023
0
      {
1024
0
        algo = GCRY_PK_EDDSA;
1025
0
        break;
1026
0
      }
1027
0
  }
1028
0
      gcry_sexp_release (l1);
1029
1030
0
      l1 = gcry_sexp_find_token (list, "curve", 0);
1031
0
      s = gcry_sexp_nth_data (l1, 1, &n);
1032
0
      if (n == 5 && !memcmp (s, "Ed448", 5))
1033
0
        algo = GCRY_PK_EDDSA;
1034
0
      gcry_sexp_release (l1);
1035
0
    }
1036
1037
0
 out:
1038
0
  gcry_sexp_release (list);
1039
1040
0
  return algo;
1041
0
}
1042
1043
1044
/* This is a variant of get_pk_algo_from_key but takes an canonical
1045
 * encoded S-expression as input.  Returns a GCRYPT public key
1046
 * identiier or 0 on error.  */
1047
int
1048
get_pk_algo_from_canon_sexp (const unsigned char *keydata, size_t keydatalen)
1049
0
{
1050
0
  gcry_sexp_t sexp;
1051
0
  int algo;
1052
1053
0
  if (gcry_sexp_sscan (&sexp, NULL, keydata, keydatalen))
1054
0
    return 0;
1055
1056
0
  algo = get_pk_algo_from_key (sexp);
1057
0
  gcry_sexp_release (sexp);
1058
0
  return algo;
1059
0
}
1060
1061
1062
/* Given the public key S_PKEY, return a new buffer with a descriptive
1063
 * string for its algorithm.  This function may return NULL on memory
1064
 * error.  If R_ALGOID is not NULL the gcrypt algo id is stored there. */
1065
char *
1066
pubkey_algo_string (gcry_sexp_t s_pkey, enum gcry_pk_algos *r_algoid)
1067
0
{
1068
0
  const char *prefix;
1069
0
  gcry_sexp_t l1;
1070
0
  char *algoname;
1071
0
  int algo;
1072
0
  char *result;
1073
1074
0
  if (r_algoid)
1075
0
    *r_algoid = 0;
1076
1077
0
  l1 = gcry_sexp_find_token (s_pkey, "public-key", 0);
1078
0
  if (!l1)
1079
0
    l1 = gcry_sexp_find_token (s_pkey, "private-key", 0);
1080
0
  if (!l1)
1081
0
    return xtrystrdup ("E_no_key");
1082
0
  {
1083
0
    gcry_sexp_t l_tmp = gcry_sexp_cadr (l1);
1084
0
    gcry_sexp_release (l1);
1085
0
    l1 = l_tmp;
1086
0
  }
1087
0
  algoname = gcry_sexp_nth_string (l1, 0);
1088
0
  gcry_sexp_release (l1);
1089
0
  if (!algoname)
1090
0
    return xtrystrdup ("E_no_algo");
1091
1092
0
  algo = gcry_pk_map_name (algoname);
1093
0
  switch (algo)
1094
0
    {
1095
0
    case GCRY_PK_RSA: prefix = "rsa"; break;
1096
0
    case GCRY_PK_ELG: prefix = "elg"; break;
1097
0
    case GCRY_PK_DSA: prefix = "dsa"; break;
1098
0
    case GCRY_PK_ECC: prefix = "";  break;
1099
0
    default:          prefix = NULL; break;
1100
0
    }
1101
1102
0
  if (prefix && *prefix)
1103
0
    result = xtryasprintf ("%s%u", prefix, gcry_pk_get_nbits (s_pkey));
1104
0
  else if (prefix)
1105
0
    {
1106
0
      const char *curve = gcry_pk_get_curve (s_pkey, 0, NULL);
1107
0
      const char *name = openpgp_oid_or_name_to_curve (curve, 0);
1108
1109
0
      if (name)
1110
0
        result = xtrystrdup (name);
1111
0
      else if (curve)
1112
0
        result = xtryasprintf ("X_%s", curve);
1113
0
      else
1114
0
        result = xtrystrdup ("E_unknown");
1115
0
    }
1116
0
  else
1117
0
    result = xtryasprintf ("X_algo_%d", algo);
1118
1119
0
  if (r_algoid)
1120
0
    *r_algoid = algo;
1121
0
  xfree (algoname);
1122
0
  return result;
1123
0
}
1124
1125
1126
/* Map a pubkey algo id from gcrypt to a string.  This is the same as
1127
 * gcry_pk_algo_name but makes sure that the ECC algo identifiers are
1128
 * not all mapped to "ECC".  */
1129
const char *
1130
pubkey_algo_to_string (int algo)
1131
0
{
1132
0
  if (algo == GCRY_PK_ECDSA)
1133
0
    return "ECDSA";
1134
0
  else if (algo == GCRY_PK_ECDH)
1135
0
    return "ECDH";
1136
0
  else if (algo == GCRY_PK_EDDSA)
1137
0
    return "EdDSA";
1138
0
  else
1139
0
    return gcry_pk_algo_name (algo);
1140
0
}
1141
1142
1143
/* Map a hash algo id from gcrypt to a string.  This is the same as
1144
 * gcry_md_algo_name but the returned string is lower case, as
1145
 * expected by libksba and it avoids some overhead.  */
1146
const char *
1147
hash_algo_to_string (int algo)
1148
0
{
1149
0
  static const struct
1150
0
  {
1151
0
    const char *name;
1152
0
    int algo;
1153
0
  } hashnames[] =
1154
0
      {
1155
0
       { "sha256",    GCRY_MD_SHA256 },
1156
0
       { "sha512",    GCRY_MD_SHA512 },
1157
0
       { "sha1",      GCRY_MD_SHA1 },
1158
0
       { "sha384",    GCRY_MD_SHA384 },
1159
0
       { "sha224",    GCRY_MD_SHA224 },
1160
0
       { "sha3-224",  GCRY_MD_SHA3_224 },
1161
0
       { "sha3-256",  GCRY_MD_SHA3_256 },
1162
0
       { "sha3-384",  GCRY_MD_SHA3_384 },
1163
0
       { "sha3-512",  GCRY_MD_SHA3_512 },
1164
0
       { "ripemd160", GCRY_MD_RMD160 },
1165
0
       { "rmd160",    GCRY_MD_RMD160 },
1166
0
       { "md2",       GCRY_MD_MD2 },
1167
0
       { "md4",       GCRY_MD_MD4 },
1168
0
       { "tiger",     GCRY_MD_TIGER },
1169
0
       { "haval",     GCRY_MD_HAVAL },
1170
0
       { "sm3",       GCRY_MD_SM3 },
1171
0
       { "md5",       GCRY_MD_MD5 }
1172
0
      };
1173
0
  int i;
1174
1175
0
  for (i=0; i < DIM (hashnames); i++)
1176
0
    if (algo == hashnames[i].algo)
1177
0
      return hashnames[i].name;
1178
0
  return "?";
1179
0
}
1180
1181
1182
/* Map cipher modes to a string.  */
1183
const char *
1184
cipher_mode_to_string (int mode)
1185
0
{
1186
0
  switch (mode)
1187
0
    {
1188
0
    case GCRY_CIPHER_MODE_CFB: return "CFB";
1189
0
    case GCRY_CIPHER_MODE_CBC: return "CBC";
1190
0
    case GCRY_CIPHER_MODE_GCM: return "GCM";
1191
0
    case GCRY_CIPHER_MODE_OCB: return "OCB";
1192
0
    case 14:                   return "EAX";  /* Only in gcrypt 1.9 */
1193
0
    default: return "[?]";
1194
0
    }
1195
0
}
1196
1197
/* Return the canonical name of the ECC curve in KEY.  */
1198
const char *
1199
get_ecc_curve_from_key (gcry_sexp_t key)
1200
0
{
1201
0
  gcry_sexp_t list = NULL;
1202
0
  gcry_sexp_t l2 = NULL;
1203
0
  const char *curve_name = NULL;
1204
0
  char *name = NULL;
1205
1206
  /* Check that the first element is valid. */
1207
0
  list = gcry_sexp_find_token (key, "public-key", 0);
1208
0
  if (!list)
1209
0
    list = gcry_sexp_find_token (key, "private-key", 0);
1210
0
  if (!list)
1211
0
    list = gcry_sexp_find_token (key, "protected-private-key", 0);
1212
0
  if (!list)
1213
0
    list = gcry_sexp_find_token (key, "shadowed-private-key", 0);
1214
0
  if (!list)
1215
0
    goto leave;
1216
1217
0
  l2 = gcry_sexp_cadr (list);
1218
0
  gcry_sexp_release (list);
1219
0
  list = l2;
1220
0
  l2 = NULL;
1221
1222
0
  name = gcry_sexp_nth_string (list, 0);
1223
0
  if (!name)
1224
0
    goto leave;
1225
1226
0
  if (gcry_pk_map_name (name) != GCRY_PK_ECC)
1227
0
    goto leave;
1228
1229
0
  l2 = gcry_sexp_find_token (list, "curve", 0);
1230
0
  xfree (name);
1231
0
  name = gcry_sexp_nth_string (l2, 1);
1232
0
  curve_name = openpgp_oid_or_name_to_curve (name, 1);
1233
0
  gcry_sexp_release (l2);
1234
1235
0
 leave:
1236
0
  xfree (name);
1237
0
  gcry_sexp_release (list);
1238
0
  return curve_name;
1239
0
}