Coverage Report

Created: 2026-08-31 07:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gnupg/g10/skclist.c
Line
Count
Source
1
/* skclist.c - Build a list of secret keys
2
 * Copyright (C) 1998, 1999, 2000, 2001, 2006,
3
 *               2010 Free Software Foundation, Inc.
4
 *
5
 * This file is part of GnuPG.
6
 *
7
 * GnuPG is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * GnuPG is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, see <https://www.gnu.org/licenses/>.
19
 */
20
21
#include <config.h>
22
#include <stdio.h>
23
#include <stdlib.h>
24
#include <string.h>
25
#include <errno.h>
26
27
#include "gpg.h"
28
#include "options.h"
29
#include "packet.h"
30
#include "../common/status.h"
31
#include "keydb.h"
32
#include "../common/util.h"
33
#include "../common/i18n.h"
34
#include "keyserver-internal.h"
35
#include "call-agent.h"
36
37
38
/* Return true if Libgcrypt's RNG is in faked mode.  */
39
int
40
random_is_faked (void)
41
0
{
42
0
  return !!gcry_control (GCRYCTL_FAKED_RANDOM_P, 0);
43
0
}
44
45
46
void
47
release_sk_list (SK_LIST sk_list)
48
38.7k
{
49
38.7k
  SK_LIST sk_rover;
50
51
38.7k
  for (; sk_list; sk_list = sk_rover)
52
0
    {
53
0
      sk_rover = sk_list->next;
54
0
      free_public_key (sk_list->pk);
55
0
      xfree (sk_list);
56
0
    }
57
38.7k
}
58
59
60
/* Check that we are only using keys which don't have
61
 * the string "(insecure!)" or "not secure" or "do not use"
62
 * in one of the user ids.  */
63
static int
64
is_insecure (ctrl_t ctrl, PKT_public_key *pk)
65
0
{
66
0
  u32 keyid[2];
67
0
  KBNODE node = NULL, u;
68
0
  int insecure = 0;
69
70
0
  keyid_from_pk (pk, keyid);
71
0
  node = get_pubkeyblock (ctrl, keyid);
72
0
  for (u = node; u; u = u->next)
73
0
    {
74
0
      if (u->pkt->pkttype == PKT_USER_ID)
75
0
  {
76
0
    PKT_user_id *id = u->pkt->pkt.user_id;
77
0
    if (id->attrib_data)
78
0
      continue;   /* skip attribute packets */
79
0
    if (strstr (id->name, "(insecure!)")
80
0
        || strstr (id->name, "not secure")
81
0
        || strstr (id->name, "do not use")
82
0
        || strstr (id->name, "(INSECURE!)"))
83
0
      {
84
0
        insecure = 1;
85
0
        break;
86
0
      }
87
0
  }
88
0
    }
89
0
  release_kbnode (node);
90
91
0
  return insecure;
92
0
}
93
94
static int
95
key_present_in_sk_list (SK_LIST sk_list, PKT_public_key *pk)
96
0
{
97
0
  for (; sk_list; sk_list = sk_list->next)
98
0
    {
99
0
      if (!cmp_public_keys (sk_list->pk, pk))
100
0
  return 0;
101
0
    }
102
0
  return -1;
103
0
}
104
105
static int
106
is_duplicated_entry (strlist_t list, strlist_t item)
107
0
{
108
0
  for (; list && list != item; list = list->next)
109
0
    {
110
0
      if (!strcmp (list->d, item->d))
111
0
  return 1;
112
0
    }
113
0
  return 0;
114
0
}
115
116
117
gpg_error_t
118
build_sk_list (ctrl_t ctrl,
119
               strlist_t locusr, SK_LIST *ret_sk_list, unsigned int use)
120
0
{
121
0
  gpg_error_t err;
122
0
  SK_LIST sk_list = NULL;
123
124
  /* XXX: Change this function to use get_pubkeys instead of
125
     getkey_byname to detect ambiguous key specifications and warn
126
     about duplicate keyblocks.  For ambiguous key specifications on
127
     the command line or provided interactively, prompt the user to
128
     select the best key.  If a key specification is ambiguous and we
129
     are in batch mode, die.  */
130
131
0
  if (!locusr) /* No user ids given - use the card key or the default key.  */
132
0
    {
133
0
      struct agent_card_info_s info;
134
0
      PKT_public_key *pk;
135
136
0
      memset (&info, 0, sizeof(info));
137
0
      pk = xmalloc_clear (sizeof *pk);
138
0
      pk->req_usage = use;
139
140
      /* Check if a card is available.  If any, use the key as a hint.  */
141
0
      err = agent_scd_serialno (NULL, NULL);
142
0
      if (!err)
143
0
        {
144
0
          err = agent_scd_getattr ("KEY-FPR", &info);
145
0
          if (err)
146
0
            log_error ("error retrieving key fingerprint from card: %s\n",
147
0
                       gpg_strerror (err));
148
0
        }
149
150
0
      err = get_seckey_default_or_card (ctrl, pk,
151
0
                                        info.fpr1len? info.fpr1 : NULL,
152
0
                                        info.fpr1len);
153
0
      if (err)
154
0
  {
155
0
    free_public_key (pk);
156
0
    pk = NULL;
157
0
    log_error ("no default secret key: %s\n", gpg_strerror (err));
158
0
    write_status_text (STATUS_INV_SGNR, get_inv_recpsgnr_code (err));
159
0
  }
160
0
      else if ((err = openpgp_pk_test_algo2 (pk->pubkey_algo, use)))
161
0
  {
162
0
    free_public_key (pk);
163
0
    pk = NULL;
164
0
    log_error ("invalid default secret key: %s\n", gpg_strerror (err));
165
0
    write_status_text (STATUS_INV_SGNR, get_inv_recpsgnr_code (err));
166
0
  }
167
0
      else
168
0
  {
169
0
    SK_LIST r;
170
171
0
    if (random_is_faked () && !is_insecure (ctrl, pk))
172
0
      {
173
0
        log_info (_("key is not flagged as insecure - "
174
0
        "can't use it with the faked RNG!\n"));
175
0
        free_public_key (pk);
176
0
        pk = NULL;
177
0
        write_status_text (STATUS_INV_SGNR,
178
0
         get_inv_recpsgnr_code (GPG_ERR_NOT_TRUSTED));
179
0
      }
180
0
    else
181
0
      {
182
0
        r = xmalloc (sizeof *r);
183
0
        r->pk = pk;
184
0
        pk = NULL;
185
0
        r->next = sk_list;
186
0
        r->mark = 0;
187
0
        sk_list = r;
188
0
      }
189
0
  }
190
0
    }
191
0
  else /* Check the given user ids.  */
192
0
    {
193
0
      strlist_t locusr_orig = locusr;
194
195
0
      for (; locusr; locusr = locusr->next)
196
0
  {
197
0
    PKT_public_key *pk;
198
199
0
    err = 0;
200
    /* Do an early check against duplicated entries.  However
201
     * this won't catch all duplicates because the user IDs may
202
     * be specified in different ways.  */
203
0
    if (is_duplicated_entry (locusr_orig, locusr))
204
0
      {
205
0
        log_info (_("skipped \"%s\": duplicated\n"), locusr->d);
206
0
        continue;
207
0
      }
208
0
    pk = xmalloc_clear (sizeof *pk);
209
0
    pk->req_usage = use;
210
0
          if ((err = getkey_byname (ctrl, NULL, pk, locusr->d, 1, NULL)))
211
0
      {
212
0
        free_public_key (pk);
213
0
        pk = NULL;
214
0
        log_error (_("skipped \"%s\": %s\n"),
215
0
       locusr->d, gpg_strerror (err));
216
0
        write_status_text_and_buffer
217
0
    (STATUS_INV_SGNR, get_inv_recpsgnr_code (err),
218
0
     locusr->d, strlen (locusr->d), -1);
219
0
      }
220
0
    else if (!key_present_in_sk_list (sk_list, pk))
221
0
      {
222
0
        free_public_key (pk);
223
0
        pk = NULL;
224
0
        log_info (_("skipped: secret key already present\n"));
225
0
      }
226
0
    else if ((err = openpgp_pk_test_algo2 (pk->pubkey_algo, use)))
227
0
      {
228
0
        free_public_key (pk);
229
0
        pk = NULL;
230
0
        log_error ("skipped \"%s\": %s\n", locusr->d, gpg_strerror (err));
231
0
        write_status_text_and_buffer
232
0
    (STATUS_INV_SGNR, get_inv_recpsgnr_code (err),
233
0
     locusr->d, strlen (locusr->d), -1);
234
0
      }
235
0
    else
236
0
      {
237
0
        SK_LIST r;
238
239
0
        if (pk->version == 4 && (use & PUBKEY_USAGE_SIG)
240
0
      && pk->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E)
241
0
    {
242
0
      log_info (_("skipped \"%s\": %s\n"), locusr->d,
243
0
          _("this is a PGP generated Elgamal key which"
244
0
            " is not secure for signatures!"));
245
0
      free_public_key (pk);
246
0
      pk = NULL;
247
0
      write_status_text_and_buffer
248
0
        (STATUS_INV_SGNR,
249
0
         get_inv_recpsgnr_code (GPG_ERR_WRONG_KEY_USAGE),
250
0
         locusr->d, strlen (locusr->d), -1);
251
0
    }
252
0
        else if (random_is_faked () && !is_insecure (ctrl, pk))
253
0
    {
254
0
      log_info (_("key is not flagged as insecure - "
255
0
            "can't use it with the faked RNG!\n"));
256
0
      free_public_key (pk);
257
0
      pk = NULL;
258
0
      write_status_text_and_buffer
259
0
        (STATUS_INV_SGNR,
260
0
         get_inv_recpsgnr_code (GPG_ERR_NOT_TRUSTED),
261
0
         locusr->d, strlen (locusr->d), -1);
262
0
    }
263
0
        else
264
0
    {
265
0
      r = xmalloc (sizeof *r);
266
0
      r->pk = pk;
267
0
      pk = NULL;
268
0
      r->next = sk_list;
269
0
      r->mark = 0;
270
0
      sk_list = r;
271
0
    }
272
0
      }
273
0
  }
274
0
    }
275
276
0
  if (!err && !sk_list)
277
0
    {
278
0
      log_error ("no valid signators\n");
279
0
      write_status_text (STATUS_NO_SGNR, "0");
280
0
      err = gpg_error (GPG_ERR_NO_USER_ID);
281
0
    }
282
283
0
  if (err)
284
0
    release_sk_list (sk_list);
285
0
  else
286
0
    *ret_sk_list = sk_list;
287
0
  return err;
288
0
}
289
290
291
/* Enumerate some secret keys (specifically, those specified with
292
 * --default-key and --try-secret-key).  Use the following procedure:
293
 *
294
 *  1) Initialize a void pointer to NULL
295
 *  2) Pass a reference to this pointer to this function (context)
296
 *     and provide space for the secret key (sk)
297
 *  3) Call this function as long as it does not return an error (or
298
 *     until you are done).  The error code GPG_ERR_EOF indicates the
299
 *     end of the listing.
300
 *  4) Call this function a last time with SK set to NULL,
301
 *     so that can free it's context.
302
 *
303
 * In pseudo-code:
304
 *
305
 *   void *ctx = NULL;
306
 *   PKT_public_key *sk = xmalloc_clear (sizeof (*sk));
307
 *
308
 *   while ((err = enum_secret_keys (&ctx, sk)))
309
 *     { // Process SK.
310
 *       if (done)
311
 *         break;
312
 *       sk = xmalloc_clear (sizeof (*sk));
313
 *     }
314
 *
315
 *   // Release any resources used by CTX.
316
 *   enum_secret_keys (&ctx, NULL);
317
 *
318
 *   if (gpg_err_code (err) != GPG_ERR_EOF)
319
 *     ; // An error occurred.
320
 */
321
gpg_error_t
322
enum_secret_keys (ctrl_t ctrl, void **context, PKT_public_key *sk)
323
77.5k
{
324
77.5k
  gpg_error_t err = 0;
325
77.5k
  const char *name;
326
77.5k
  int cardkey;
327
77.5k
  kbnode_t keyblock;
328
77.5k
  struct
329
77.5k
  {
330
77.5k
    int eof;
331
77.5k
    int state;
332
77.5k
    int cardkey_done;
333
77.5k
    strlist_t sl;
334
77.5k
    keypair_info_t card_keyinfo;
335
77.5k
    keypair_info_t card_keyinfo_list;
336
77.5k
    char fpr2[2 * MAX_FINGERPRINT_LEN + 2 ];
337
77.5k
    kbnode_t keyblock;
338
77.5k
    kbnode_t node;
339
77.5k
    getkey_ctx_t ctx;
340
77.5k
    SK_LIST results;
341
77.5k
  } *c = *context;
342
343
#if MAX_FINGERPRINT_LEN < KEYGRIP_LEN
344
# error buffer too short for this configuration
345
#endif
346
347
77.5k
  if (!c)
348
38.7k
    {
349
      /* Make a new context.  */
350
38.7k
      c = xtrycalloc (1, sizeof *c);
351
38.7k
      if (!c)
352
0
        {
353
0
          err = gpg_error_from_syserror ();
354
0
          free_public_key (sk);
355
0
          return err;
356
0
        }
357
38.7k
      *context = c;
358
38.7k
    }
359
360
77.5k
  if (!sk)
361
38.7k
    {
362
      /* Free the context.  */
363
38.7k
      free_keypair_info (c->card_keyinfo_list);
364
38.7k
      release_sk_list (c->results);
365
38.7k
      release_kbnode (c->keyblock);
366
38.7k
      getkey_end (ctrl, c->ctx);
367
38.7k
      xfree (c);
368
38.7k
      *context = NULL;
369
38.7k
      return 0;
370
38.7k
    }
371
372
38.7k
  if (c->eof)
373
0
    {
374
0
      free_public_key (sk);
375
0
      return gpg_error (GPG_ERR_EOF);
376
0
    }
377
378
38.7k
  for (;;)
379
38.7k
    {
380
      /* Loop until we have a keyblock.  */
381
38.7k
      while (!c->keyblock)
382
38.7k
        {
383
          /* Loop over the list of secret keys.  */
384
38.7k
          do
385
310k
            {
386
310k
              name = NULL;
387
310k
              cardkey = 0;
388
310k
              keyblock = NULL;
389
310k
              switch (c->state)
390
310k
                {
391
38.7k
                case 0: /* First try to use the --default-key.  */
392
38.7k
                  name = parse_def_secret_key (ctrl);
393
38.7k
                  c->state = 1;
394
38.7k
                  break;
395
396
38.7k
                case 1: /* Init list of keys to try.  */
397
38.7k
                  c->sl = opt.secret_keys_to_try;
398
38.7k
                  c->state++;
399
38.7k
                  break;
400
401
38.7k
                case 2: /* Get next item from list.  */
402
38.7k
                  if (c->sl)
403
0
                    {
404
0
                      name = c->sl->d;
405
0
                      c->sl = c->sl->next;
406
0
                    }
407
38.7k
                  else
408
38.7k
                    c->state++;
409
38.7k
                  break;
410
411
38.7k
                case 3: /* Init list of card keys to try.  */
412
38.7k
                  c->card_keyinfo_list = NULL;
413
38.7k
                  err = agent_scd_serialno (NULL, NULL);
414
38.7k
                  if (!err)
415
0
                    {
416
0
                      err = agent_scd_keyinfo (NULL, GCRY_PK_USAGE_ENCR,
417
0
                                               &c->card_keyinfo_list);
418
0
                    }
419
38.7k
                  c->card_keyinfo = c->card_keyinfo_list;
420
38.7k
                  c->state++;
421
38.7k
                  break;
422
423
38.7k
                case 4: /* Get next item from card keyinfo.  */
424
38.7k
                  if (c->card_keyinfo)
425
0
                    {
426
0
                      const char *s;
427
0
                      int i;
428
429
                      /* Get the key using the keygrip.  */
430
0
                      c->fpr2[0] = '&';
431
0
                      for (i=1, s = c->card_keyinfo->keygrip;
432
0
                           (*s && *s != ' '
433
0
                            && i < sizeof c->fpr2 - 2);
434
0
                           s++, i++)
435
0
                        c->fpr2[i] = *s;
436
0
                      c->fpr2[i] = 0;
437
0
                      name = c->fpr2;
438
0
                      cardkey = 1;
439
440
0
                      c->card_keyinfo = c->card_keyinfo->next;
441
0
                    }
442
38.7k
                  else
443
38.7k
                    c->state++;
444
38.7k
                  break;
445
446
38.7k
                case 5: /* Init search context to enum all secret keys.  */
447
38.7k
                  err = getkey_bynames (ctrl, &c->ctx, NULL, NULL,
448
38.7k
                                        GETKEY_WANT_SECRET,
449
38.7k
                                        &keyblock);
450
38.7k
                  if (err)
451
38.7k
                    {
452
38.7k
                      release_kbnode (keyblock);
453
38.7k
                      keyblock = NULL;
454
38.7k
                      getkey_end (ctrl, c->ctx);
455
38.7k
                      c->ctx = NULL;
456
38.7k
                    }
457
38.7k
                  c->state++;
458
38.7k
                  break;
459
460
38.7k
                case 6: /* Get next item from the context.  */
461
38.7k
                  if (c->ctx)
462
0
                    {
463
0
                      err = getkey_next (ctrl, c->ctx, NULL, &keyblock);
464
0
                      if (err)
465
0
                        {
466
0
                          release_kbnode (keyblock);
467
0
                          keyblock = NULL;
468
0
                          getkey_end (ctrl, c->ctx);
469
0
                          c->ctx = NULL;
470
0
                        }
471
0
                    }
472
38.7k
                  else
473
38.7k
                    c->state++;
474
38.7k
                  break;
475
476
38.7k
                default: /* No more names to check - stop.  */
477
38.7k
                  c->eof = 1;
478
38.7k
                  free_public_key (sk);
479
38.7k
                  return gpg_error (GPG_ERR_EOF);
480
310k
                }
481
310k
            }
482
271k
          while ((!name || !*name) && !keyblock);
483
484
0
          if (keyblock)
485
0
            c->node = c->keyblock = keyblock;
486
0
          else
487
0
            {
488
0
              err = getkey_byname (ctrl, NULL, NULL, name, 1, &c->keyblock);
489
0
              if (err)
490
0
                {
491
0
                  struct agent_card_info_s cinfo = { 0 };
492
493
                  /* getkey_byname might return a keyblock even in the
494
                     error case - I have not checked.  Thus better release
495
                     it.  */
496
0
                  release_kbnode (c->keyblock);
497
0
                  c->keyblock = NULL;
498
                  /* If this was a card key we might not yet have the
499
                   * public key for it.  Thus check whether the card
500
                   * can return the fingerprint of the encryption key
501
                   * and we can then find the public key via LDAP.  */
502
0
                  if (cardkey && !c->cardkey_done
503
0
                      && gpg_err_code (err) == GPG_ERR_NO_SECKEY
504
0
                      && !agent_scd_getattr ("KEY-FPR", &cinfo)
505
0
                      && cinfo.fpr2len)
506
0
                    {
507
                      /* Note that this code does not handle the case
508
                       * for two readers having both openpgp
509
                       * encryption keys. only one will be tried.  */
510
0
                      c->cardkey_done = 1;
511
0
                      if (opt.debug)
512
0
                        log_debug ("using LDAP to find public key"
513
0
                                   " for current card\n");
514
0
                      if (!keyserver_import_fpr
515
0
                          (ctrl, cinfo.fpr2, cinfo.fpr2len, opt.keyserver,
516
0
                           KEYSERVER_IMPORT_FLAG_LDAP))
517
0
                        {
518
0
                          char fpr_string[MAX_FINGERPRINT_LEN * 2 + 1];
519
520
0
                          bin2hex (cinfo.fpr2, cinfo.fpr2len, fpr_string);
521
0
                          err = getkey_byname (ctrl, NULL, NULL, fpr_string, 1,
522
0
                                               &c->keyblock);
523
0
                          if (err)
524
0
                            {
525
0
                              release_kbnode (c->keyblock);
526
0
                              c->keyblock = NULL;
527
0
                            }
528
0
                          else
529
0
                            c->node = c->keyblock;
530
0
                        }
531
0
                    }
532
0
                }
533
0
              else
534
0
                c->node = c->keyblock;
535
0
            }
536
0
        }
537
538
      /* Get the next key from the current keyblock.  */
539
0
      for (; c->node; c->node = c->node->next)
540
0
        {
541
0
          if (c->node->pkt->pkttype == PKT_PUBLIC_KEY
542
0
              || c->node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
543
0
            {
544
0
              SK_LIST r;
545
546
              /* Skip this candidate if it's already enumerated.  */
547
0
              for (r = c->results; r; r = r->next)
548
0
                if (!cmp_public_keys (r->pk, c->node->pkt->pkt.public_key))
549
0
                  break;
550
0
              if (r)
551
0
                continue;
552
553
0
              copy_public_key (sk, c->node->pkt->pkt.public_key);
554
0
              c->node = c->node->next;
555
556
0
              r = xtrycalloc (1, sizeof (*r));
557
0
              if (!r)
558
0
                {
559
0
                  err = gpg_error_from_syserror ();
560
0
                  free_public_key (sk);
561
0
                  return err;
562
0
                }
563
564
0
              r->pk = sk;
565
0
              r->next = c->results;
566
0
              c->results = r;
567
568
0
              return 0; /* Found.  */
569
0
            }
570
0
        }
571
572
      /* Dispose the keyblock and continue.  */
573
0
      release_kbnode (c->keyblock);
574
      c->keyblock = NULL;
575
0
    }
576
38.7k
}