Coverage Report

Created: 2026-02-26 06:52

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