Coverage Report

Created: 2026-03-03 06:41

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