Coverage Report

Created: 2026-07-30 06:13

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
46.9k
{
49
46.9k
  SK_LIST sk_rover;
50
51
46.9k
  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
46.9k
}
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
93.8k
{
324
93.8k
  gpg_error_t err = 0;
325
93.8k
  const char *name;
326
93.8k
  int cardkey;
327
93.8k
  kbnode_t keyblock;
328
93.8k
  struct
329
93.8k
  {
330
93.8k
    int eof;
331
93.8k
    int state;
332
93.8k
    int cardkey_done;
333
93.8k
    strlist_t sl;
334
93.8k
    keypair_info_t card_keyinfo;
335
93.8k
    keypair_info_t card_keyinfo_list;
336
93.8k
    char fpr2[2 * MAX_FINGERPRINT_LEN + 2 ];
337
93.8k
    kbnode_t keyblock;
338
93.8k
    kbnode_t node;
339
93.8k
    getkey_ctx_t ctx;
340
93.8k
    SK_LIST results;
341
93.8k
  } *c = *context;
342
343
#if MAX_FINGERPRINT_LEN < KEYGRIP_LEN
344
# error buffer too short for this configuration
345
#endif
346
347
93.8k
  if (!c)
348
46.9k
    {
349
      /* Make a new context.  */
350
46.9k
      c = xtrycalloc (1, sizeof *c);
351
46.9k
      if (!c)
352
0
        {
353
0
          err = gpg_error_from_syserror ();
354
0
          free_public_key (sk);
355
0
          return err;
356
0
        }
357
46.9k
      *context = c;
358
46.9k
    }
359
360
93.8k
  if (!sk)
361
46.9k
    {
362
      /* Free the context.  */
363
46.9k
      free_keypair_info (c->card_keyinfo_list);
364
46.9k
      release_sk_list (c->results);
365
46.9k
      release_kbnode (c->keyblock);
366
46.9k
      getkey_end (ctrl, c->ctx);
367
46.9k
      xfree (c);
368
46.9k
      *context = NULL;
369
46.9k
      return 0;
370
46.9k
    }
371
372
46.9k
  if (c->eof)
373
0
    {
374
0
      free_public_key (sk);
375
0
      return gpg_error (GPG_ERR_EOF);
376
0
    }
377
378
46.9k
  for (;;)
379
46.9k
    {
380
      /* Loop until we have a keyblock.  */
381
46.9k
      while (!c->keyblock)
382
46.9k
        {
383
          /* Loop over the list of secret keys.  */
384
46.9k
          do
385
375k
            {
386
375k
              name = NULL;
387
375k
              cardkey = 0;
388
375k
              keyblock = NULL;
389
375k
              switch (c->state)
390
375k
                {
391
46.9k
                case 0: /* First try to use the --default-key.  */
392
46.9k
                  name = parse_def_secret_key (ctrl);
393
46.9k
                  c->state = 1;
394
46.9k
                  break;
395
396
46.9k
                case 1: /* Init list of keys to try.  */
397
46.9k
                  c->sl = opt.secret_keys_to_try;
398
46.9k
                  c->state++;
399
46.9k
                  break;
400
401
46.9k
                case 2: /* Get next item from list.  */
402
46.9k
                  if (c->sl)
403
0
                    {
404
0
                      name = c->sl->d;
405
0
                      c->sl = c->sl->next;
406
0
                    }
407
46.9k
                  else
408
46.9k
                    c->state++;
409
46.9k
                  break;
410
411
46.9k
                case 3: /* Init list of card keys to try.  */
412
46.9k
                  c->card_keyinfo_list = NULL;
413
46.9k
                  err = agent_scd_serialno (NULL, NULL);
414
46.9k
                  if (!err)
415
0
                    {
416
0
                      err = agent_scd_keyinfo (NULL, GCRY_PK_USAGE_ENCR,
417
0
                                               &c->card_keyinfo_list);
418
0
                    }
419
46.9k
                  c->card_keyinfo = c->card_keyinfo_list;
420
46.9k
                  c->state++;
421
46.9k
                  break;
422
423
46.9k
                case 4: /* Get next item from card keyinfo.  */
424
46.9k
                  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
46.9k
                  else
443
46.9k
                    c->state++;
444
46.9k
                  break;
445
446
46.9k
                case 5: /* Init search context to enum all secret keys.  */
447
46.9k
                  err = getkey_bynames (ctrl, &c->ctx, NULL, NULL,
448
46.9k
                                        GETKEY_WANT_SECRET,
449
46.9k
                                        &keyblock);
450
46.9k
                  if (err)
451
46.9k
                    {
452
46.9k
                      release_kbnode (keyblock);
453
46.9k
                      keyblock = NULL;
454
46.9k
                      getkey_end (ctrl, c->ctx);
455
46.9k
                      c->ctx = NULL;
456
46.9k
                    }
457
46.9k
                  c->state++;
458
46.9k
                  break;
459
460
46.9k
                case 6: /* Get next item from the context.  */
461
46.9k
                  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
46.9k
                  else
473
46.9k
                    c->state++;
474
46.9k
                  break;
475
476
46.9k
                default: /* No more names to check - stop.  */
477
46.9k
                  c->eof = 1;
478
46.9k
                  free_public_key (sk);
479
46.9k
                  return gpg_error (GPG_ERR_EOF);
480
375k
                }
481
375k
            }
482
328k
          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
46.9k
}