Coverage Report

Created: 2026-01-17 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gnupg/g10/pubkey-enc.c
Line
Count
Source
1
/* pubkey-enc.c - Process a public key encoded packet.
2
 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2006, 2009,
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
26
#include "gpg.h"
27
#include "../common/util.h"
28
#include "packet.h"
29
#include "keydb.h"
30
#include "trustdb.h"
31
#include "../common/status.h"
32
#include "options.h"
33
#include "main.h"
34
#include "../common/i18n.h"
35
#include "pkglue.h"
36
#include "call-agent.h"
37
#include "../common/host2net.h"
38
#include "../common/compliance.h"
39
40
41
static gpg_error_t get_it (ctrl_t ctrl, struct seskey_enc_list *k,
42
                           DEK *dek, PKT_public_key *sk, u32 *keyid);
43
44
45
/* Check that the given algo is mentioned in one of the valid user-ids. */
46
static int
47
is_algo_in_prefs (kbnode_t keyblock, preftype_t type, int algo)
48
0
{
49
0
  kbnode_t k;
50
51
0
  for (k = keyblock; k; k = k->next)
52
0
    {
53
0
      if (k->pkt->pkttype == PKT_USER_ID)
54
0
        {
55
0
          PKT_user_id *uid = k->pkt->pkt.user_id;
56
0
          prefitem_t *prefs = uid->prefs;
57
58
0
          if (uid->created && prefs && !uid->flags.revoked && !uid->flags.expired)
59
0
            {
60
0
              for (; prefs->type; prefs++)
61
0
                if (prefs->type == type && prefs->value == algo)
62
0
                  return 1;
63
0
            }
64
0
        }
65
0
    }
66
0
  return 0;
67
0
}
68
69
70
/*
71
 * Get the session key from a pubkey enc packet and return it in DEK,
72
 * which should have been allocated in secure memory by the caller.
73
 */
74
gpg_error_t
75
get_session_key (ctrl_t ctrl, struct seskey_enc_list *list, DEK *dek)
76
2
{
77
2
  PKT_public_key *sk = NULL;
78
2
  gpg_error_t err;
79
2
  void *enum_context = NULL;
80
2
  u32 keyid[2];
81
2
  int search_for_secret_keys = 1;
82
2
  struct seskey_enc_list *k;
83
84
2
  if (DBG_CLOCK)
85
2
    log_clock ("get_session_key enter");
86
87
2
  while (search_for_secret_keys)
88
2
    {
89
2
      sk = xmalloc_clear (sizeof *sk);
90
2
      err = enum_secret_keys (ctrl, &enum_context, sk);
91
2
      if (err)
92
2
        break;
93
94
      /* Check compliance.  */
95
0
      if (! gnupg_pk_is_allowed (opt.compliance, PK_USE_DECRYPTION,
96
0
                                 sk->pubkey_algo, 0,
97
0
                                 sk->pkey, nbits_from_pk (sk), NULL))
98
0
        {
99
0
          log_info (_("key %s is not suitable for decryption"
100
0
                      " in %s mode\n"),
101
0
                    keystr_from_pk (sk),
102
0
                    gnupg_compliance_option_string (opt.compliance));
103
0
          continue;
104
0
        }
105
106
      /* FIXME: The list needs to be sorted so that we try the keys in
107
       * an appropriate order.  For example:
108
       * - On-disk keys w/o protection
109
       * - On-disk keys with a cached passphrase
110
       * - On-card keys of an active card
111
       * - On-disk keys with protection
112
       * - On-card keys from cards which are not plugged it.  Here a
113
       *   cancel-all button should stop asking for other cards.
114
       * Without any anonymous keys the sorting can be skipped.
115
       */
116
0
      for (k = list; k; k = k->next)
117
0
        {
118
0
          if (k->u_sym)
119
0
            continue;
120
0
          if (!(k->u.pub.pubkey_algo == PUBKEY_ALGO_ELGAMAL_E
121
0
                || k->u.pub.pubkey_algo == PUBKEY_ALGO_ECDH
122
0
                || k->u.pub.pubkey_algo == PUBKEY_ALGO_KYBER
123
0
                || k->u.pub.pubkey_algo == PUBKEY_ALGO_RSA
124
0
                || k->u.pub.pubkey_algo == PUBKEY_ALGO_RSA_E
125
0
                || k->u.pub.pubkey_algo == PUBKEY_ALGO_ELGAMAL))
126
0
            continue;
127
128
0
          if (openpgp_pk_test_algo2 (k->u.pub.pubkey_algo, PUBKEY_USAGE_ENC))
129
0
            continue;
130
131
0
          if (sk->pubkey_algo != k->u.pub.pubkey_algo)
132
0
            continue;
133
134
0
          keyid_from_pk (sk, keyid);
135
136
0
          if (!k->u.pub.keyid[0] && !k->u.pub.keyid[1])
137
0
            {
138
0
              if (opt.skip_hidden_recipients)
139
0
                continue;
140
141
0
              if (!opt.quiet)
142
0
                log_info (_("anonymous recipient; trying secret key %s ...\n"),
143
0
                          keystr (keyid));
144
0
            }
145
0
          else if (opt.try_all_secrets
146
0
                   || (k->u.pub.keyid[0] == keyid[0]
147
0
                       && k->u.pub.keyid[1] == keyid[1]))
148
0
            {
149
0
              if (!opt.quiet && !(sk->pubkey_usage & PUBKEY_USAGE_XENC_MASK))
150
0
                log_info (_("used key is not marked for encryption use.\n"));
151
0
            }
152
0
          else
153
0
            continue;
154
155
0
          err = get_it (ctrl, k, dek, sk, keyid);
156
0
          k->result = err;
157
0
          if (!err)
158
0
            {
159
0
              if (!opt.quiet && !k->u.pub.keyid[0] && !k->u.pub.keyid[1])
160
0
                {
161
0
                  log_info (_("okay, we are the anonymous recipient.\n"));
162
0
                  if (!(sk->pubkey_usage & PUBKEY_USAGE_XENC_MASK))
163
0
                    log_info (_("used key is not marked for encryption use.\n")
164
0
                              );
165
0
                }
166
0
              search_for_secret_keys = 0;
167
0
              break;
168
0
            }
169
0
          else if (gpg_err_code (err) == GPG_ERR_FULLY_CANCELED)
170
0
            {
171
0
              search_for_secret_keys = 0;
172
0
              break; /* Don't try any more secret keys.  */
173
0
            }
174
0
        }
175
0
    }
176
2
  enum_secret_keys (ctrl, &enum_context, NULL);  /* free context */
177
178
2
  if (gpg_err_code (err) == GPG_ERR_EOF)
179
2
    {
180
2
      err = gpg_error (GPG_ERR_NO_SECKEY);
181
182
      /* Return the last specific error, if any.  */
183
4
      for (k = list; k; k = k->next)
184
2
        if (k->result != -1)
185
0
          err = k->result;
186
2
    }
187
188
2
  if (DBG_CLOCK)
189
2
    log_clock ("get_session_key leave");
190
2
  return err;
191
2
}
192
193
194
/* Build an SEXP to gpg-agent, for PKDECRYPT command.  */
195
static gpg_error_t
196
ecdh_sexp_build (gcry_sexp_t *r_s_data, struct seskey_enc_list *enc,
197
                 PKT_public_key *sk)
198
0
{
199
0
  gpg_error_t err;
200
0
  const unsigned char *kdf_params_spec;
201
0
  byte fp[MAX_FINGERPRINT_LEN];
202
0
  int keywrap_cipher_algo;
203
0
  int kdf_hash_algo;
204
0
  unsigned char *kdf_params = NULL;
205
0
  size_t kdf_params_len = 0;
206
207
0
  fingerprint_from_pk (sk, fp, NULL);
208
209
0
  err = ecc_build_kdf_params (&kdf_params, &kdf_params_len,
210
0
                              &kdf_params_spec, sk->pkey, fp);
211
0
  if (err)
212
0
    return err;
213
214
0
  keywrap_cipher_algo = kdf_params_spec[3];
215
0
  kdf_hash_algo = kdf_params_spec[2];
216
217
0
  if (!enc->u.pub.data[0] || !enc->u.pub.data[1])
218
0
    {
219
0
      xfree (kdf_params);
220
0
      return gpg_error (GPG_ERR_BAD_MPI);
221
0
    }
222
223
0
  err = gcry_sexp_build (r_s_data, NULL,
224
0
                         "(enc-val(ecc(c%d)(h%d)(e%m)(s%m)(kdf-params%b)))",
225
0
                         keywrap_cipher_algo, kdf_hash_algo,
226
0
                         enc->u.pub.data[0], enc->u.pub.data[1],
227
0
                         (int)kdf_params_len, kdf_params);
228
0
  xfree (kdf_params);
229
0
  return err;
230
0
}
231
232
233
static gpg_error_t
234
get_it (ctrl_t ctrl,
235
        struct seskey_enc_list *enc, DEK *dek, PKT_public_key *sk, u32 *keyid)
236
0
{
237
0
  gpg_error_t err;
238
0
  byte *frame = NULL;
239
0
  unsigned int frameidx;
240
0
  size_t nframe;
241
0
  u16 csum, csum2;
242
0
  int padding;
243
0
  gcry_sexp_t s_data;
244
0
  char *desc;
245
0
  char *keygrip;
246
247
0
  if (DBG_CLOCK)
248
0
    log_clock ("decryption start");
249
250
0
  log_assert (!enc->u_sym);
251
252
  /* Get the keygrip.  */
253
0
  err = hexkeygrip_from_pk (sk, &keygrip);
254
0
  if (err)
255
0
    goto leave;
256
257
  /* Convert the data to an S-expression.  */
258
0
  if (sk->pubkey_algo == PUBKEY_ALGO_ELGAMAL
259
0
      || sk->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E)
260
0
    {
261
0
      if (!enc->u.pub.data[0] || !enc->u.pub.data[1])
262
0
        err = gpg_error (GPG_ERR_BAD_MPI);
263
0
      else
264
0
        err = gcry_sexp_build (&s_data, NULL, "(enc-val(elg(a%m)(b%m)))",
265
0
                               enc->u.pub.data[0], enc->u.pub.data[1]);
266
0
    }
267
0
  else if (sk->pubkey_algo == PUBKEY_ALGO_RSA
268
0
           || sk->pubkey_algo == PUBKEY_ALGO_RSA_E)
269
0
    {
270
0
      if (!enc->u.pub.data[0])
271
0
        err = gpg_error (GPG_ERR_BAD_MPI);
272
0
      else
273
0
        err = gcry_sexp_build (&s_data, NULL, "(enc-val(rsa(a%m)))",
274
0
                               enc->u.pub.data[0]);
275
0
    }
276
0
  else if (sk->pubkey_algo == PUBKEY_ALGO_ECDH)
277
0
    err = ecdh_sexp_build (&s_data, enc, sk);
278
0
  else if (sk->pubkey_algo == PUBKEY_ALGO_KYBER)
279
0
    {
280
0
      char fixedinfo[1+MAX_FINGERPRINT_LEN];
281
0
      int fixedlen;
282
283
0
      if ((opt.compat_flags & COMPAT_T7014_OLD))
284
0
        {
285
          /* Temporary use for tests with original test vectors.  */
286
0
          fixedinfo[0] = 0x69;
287
0
          fixedlen = 1;
288
0
        }
289
0
      else
290
0
        {
291
0
          fixedinfo[0] = enc->u.pub.seskey_algo;
292
0
          v5_fingerprint_from_pk (sk, fixedinfo+1, NULL);
293
0
          fixedlen = 33;
294
0
        }
295
296
0
      if (!enc->u.pub.data[0] || !enc->u.pub.data[1] || !enc->u.pub.data[2])
297
0
        err = gpg_error (GPG_ERR_BAD_MPI);
298
0
      else
299
0
        err = gcry_sexp_build (&s_data, NULL,
300
0
                           "(enc-val(pqc(e%m)(k%m)(s%m)(c%d)(fixed-info%b)))",
301
0
                               enc->u.pub.data[0],
302
0
                               enc->u.pub.data[1],
303
0
                               enc->u.pub.data[2],
304
0
                               enc->u.pub.seskey_algo, fixedlen, fixedinfo);
305
0
    }
306
0
  else
307
0
    err = gpg_error (GPG_ERR_BUG);
308
309
0
  if (err)
310
0
    goto leave;
311
312
  /* Decrypt. */
313
0
  desc = gpg_format_keydesc (ctrl, sk, FORMAT_KEYDESC_NORMAL, 1);
314
315
0
  err = agent_pkdecrypt (NULL, keygrip,
316
0
                         desc, sk->keyid, sk->main_keyid, sk->pubkey_algo,
317
0
                         s_data, &frame, &nframe, &padding);
318
0
  xfree (desc);
319
0
  gcry_sexp_release (s_data);
320
0
  if (err)
321
0
    goto leave;
322
323
  /* Now get the DEK (data encryption key) from the frame
324
   *
325
   * Old versions encode the DEK in this format (msb is left):
326
   *
327
   *     0  1  DEK(16 bytes)  CSUM(2 bytes)  0  RND(n bytes) 2
328
   *
329
   * Later versions encode the DEK like this:
330
   *
331
   *     0  2  RND(n bytes)  0  A  DEK(k bytes)  CSUM(2 bytes)
332
   *
333
   * (mpi_get_buffer already removed the leading zero).
334
   *
335
   * RND are non-zero randow bytes.
336
   * A   is the cipher algorithm
337
   * DEK is the encryption key (session key) with length k
338
   * CSUM
339
   */
340
0
  if (DBG_CRYPTO)
341
0
    log_printhex (frame, nframe, "DEK frame:");
342
0
  frameidx = 0;
343
344
0
  if (sk->pubkey_algo == PUBKEY_ALGO_KYBER)
345
0
    {
346
0
      if (nframe != 32 && opt.flags.require_pqc_encryption)
347
0
        {
348
0
          log_info (_("WARNING: session key is not quantum-resistant\n"));
349
0
        }
350
0
      dek->keylen = nframe;
351
0
      dek->algo = enc->u.pub.seskey_algo;
352
0
    }
353
0
  else if (sk->pubkey_algo == PUBKEY_ALGO_ECDH)
354
0
    {
355
      /* Now the frame are the bytes decrypted but padded session key.  */
356
0
      if (!nframe || nframe <= 8
357
0
          || frame[nframe-1] > nframe)
358
0
        {
359
0
          err = gpg_error (GPG_ERR_WRONG_SECKEY);
360
0
          goto leave;
361
0
        }
362
0
      nframe -= frame[nframe-1]; /* Remove padding.  */
363
0
      if (4 > nframe)
364
0
        {
365
0
          err = gpg_error (GPG_ERR_WRONG_SECKEY);
366
0
          goto leave;
367
0
        }
368
369
0
      dek->keylen = nframe - 3;
370
0
      dek->algo = frame[0];
371
0
      frameidx = 1;
372
0
    }
373
0
  else
374
0
    {
375
0
      if (padding)
376
0
        {
377
0
          if (7 > nframe)
378
0
            {
379
0
              err = gpg_error (GPG_ERR_WRONG_SECKEY);
380
0
              goto leave;
381
0
            }
382
383
          /* FIXME: Actually the leading zero is required but due to
384
           * the way we encode the output in libgcrypt as an MPI we
385
           * are not able to encode that leading zero.  However, when
386
           * using a Smartcard we are doing it the right way and
387
           * therefore we have to skip the zero.  This should be fixed
388
           * in gpg-agent of course. */
389
0
          frameidx = 0;
390
0
          if (!frame[frameidx])
391
0
            frameidx++;
392
393
0
          if (frame[frameidx] == 1 && frame[nframe - 1] == 2)
394
0
            {
395
0
              log_info (_("old encoding of the DEK is not supported\n"));
396
0
              err = gpg_error (GPG_ERR_CIPHER_ALGO);
397
0
              goto leave;
398
0
            }
399
0
          if (frame[frameidx] != 2) /* Something went wrong.  */
400
0
            {
401
0
              err = gpg_error (GPG_ERR_WRONG_SECKEY);
402
0
              goto leave;
403
0
            }
404
          /* Skip the random bytes.  */
405
0
          for (frameidx++; frameidx < nframe && frame[frameidx]; frameidx++)
406
0
            ;
407
0
          frameidx++; /* Skip the zero byte.  */
408
0
        }
409
410
0
      if (frameidx + 4 > nframe)
411
0
        {
412
0
          err = gpg_error (GPG_ERR_WRONG_SECKEY);
413
0
          goto leave;
414
0
        }
415
416
0
      dek->keylen = nframe - (frameidx + 1) - 2;
417
0
      dek->algo = frame[frameidx++];
418
0
    }
419
420
  /* Check whether we support the ago.  */
421
0
  err = openpgp_cipher_test_algo (dek->algo);
422
0
  if (err)
423
0
    {
424
0
      if (!opt.quiet && gpg_err_code (err) == GPG_ERR_CIPHER_ALGO)
425
0
        {
426
0
          log_info (_("cipher algorithm %d%s is unknown or disabled\n"),
427
0
                    dek->algo,
428
0
                    dek->algo == CIPHER_ALGO_IDEA ? " (IDEA)" : "");
429
0
        }
430
0
      dek->algo = 0;
431
0
      goto leave;
432
0
    }
433
0
  if (dek->keylen != openpgp_cipher_get_algo_keylen (dek->algo))
434
0
    {
435
0
      err = gpg_error (GPG_ERR_WRONG_SECKEY);
436
0
      goto leave;
437
0
    }
438
439
  /* Copy the key to DEK and compare the checksum if needed.  */
440
  /* We use the frameidx as flag for the need of a checksum.  */
441
0
  memcpy (dek->key, frame + frameidx, dek->keylen);
442
0
  if (frameidx)
443
0
    {
444
0
      csum = buf16_to_u16 (frame+nframe-2);
445
0
      for (csum2 = 0, frameidx = 0; frameidx < dek->keylen; frameidx++)
446
0
        csum2 += dek->key[frameidx];
447
0
      if (csum != csum2)
448
0
        {
449
0
          err = gpg_error (GPG_ERR_WRONG_SECKEY);
450
0
          goto leave;
451
0
        }
452
0
    }
453
454
0
  if (DBG_CLOCK)
455
0
    log_clock ("decryption ready");
456
0
  if (DBG_CRYPTO)
457
0
    log_printhex (dek->key, dek->keylen, "DEK is:");
458
459
  /* Check that the algo is in the preferences and whether it has
460
   * expired.  Also print a status line with the key's fingerprint.  */
461
0
  {
462
0
    PKT_public_key *pk = NULL;
463
0
    PKT_public_key *mainpk = NULL;
464
0
    kbnode_t pkb = get_pubkeyblock_ext (ctrl, keyid, GETKEY_ALLOW_ADSK);
465
466
0
    if (!pkb)
467
0
      {
468
0
        err = gpg_error (GPG_ERR_UNEXPECTED);
469
0
        log_info ("oops: public key not found for preference check\n");
470
0
      }
471
0
    else if (pkb->pkt->pkt.public_key->selfsigversion > 3
472
0
             && dek->algo != CIPHER_ALGO_3DES
473
0
             && !opt.quiet
474
0
             && !is_algo_in_prefs (pkb, PREFTYPE_SYM, dek->algo))
475
0
      log_info (_("WARNING: cipher algorithm %s not found in recipient"
476
0
                  " preferences\n"), openpgp_cipher_algo_name (dek->algo));
477
478
    /* if (!err && 25519 && openpgp_oidbuf_is_ed25519 (curve, len)) */
479
    /*   log_info ("Note: legacy OID was used for cv25519\n"); */
480
481
0
    if (!err)
482
0
      {
483
0
        kbnode_t k;
484
0
        int first = 1;
485
486
0
        for (k = pkb; k; k = k->next)
487
0
          {
488
0
            if (k->pkt->pkttype == PKT_PUBLIC_KEY
489
0
                || k->pkt->pkttype == PKT_PUBLIC_SUBKEY)
490
0
              {
491
0
                u32 aki[2];
492
493
0
                if (first)
494
0
                  {
495
0
                    first = 0;
496
0
                    mainpk = k->pkt->pkt.public_key;
497
0
                  }
498
499
0
                keyid_from_pk (k->pkt->pkt.public_key, aki);
500
0
                if (aki[0] == keyid[0] && aki[1] == keyid[1])
501
0
                  {
502
0
                    pk = k->pkt->pkt.public_key;
503
0
                    break;
504
0
                  }
505
0
              }
506
0
          }
507
0
        if (!pk)
508
0
          BUG ();
509
0
        if (pk->expiredate && pk->expiredate <= make_timestamp ())
510
0
          {
511
0
            log_info (_("Note: secret key %s expired at %s\n"),
512
0
                      keystr (keyid), asctimestamp (pk->expiredate));
513
0
          }
514
0
      }
515
516
0
    if (pk && !(pk->pubkey_usage & PUBKEY_USAGE_ENC)
517
0
        && (pk->pubkey_usage & PUBKEY_USAGE_RENC))
518
0
      {
519
0
        log_info (_("Note: ADSK key has been used for decryption"));
520
0
        log_printf ("\n");
521
0
      }
522
523
0
    if (pk && pk->flags.revoked)
524
0
      {
525
0
        log_info (_("Note: key has been revoked"));
526
0
        log_printf ("\n");
527
0
        show_revocation_reason (ctrl, pk, 1);
528
0
      }
529
530
0
    if (is_status_enabled () && pk && mainpk)
531
0
      {
532
0
        char pkhex[MAX_FINGERPRINT_LEN*2+1];
533
0
        char mainpkhex[MAX_FINGERPRINT_LEN*2+1];
534
535
0
        hexfingerprint (pk, pkhex, sizeof pkhex);
536
0
        hexfingerprint (mainpk, mainpkhex, sizeof mainpkhex);
537
538
        /* Note that we do not want to create a trustdb just for
539
         * getting the ownertrust: If there is no trustdb there can't
540
         * be an ultimately trusted key anyway and thus the ownertrust
541
         * value is irrelevant.  */
542
0
        write_status_printf (STATUS_DECRYPTION_KEY, "%s %s %c",
543
0
                             pkhex, mainpkhex,
544
0
                             get_ownertrust_info (ctrl, mainpk, 1));
545
546
0
      }
547
548
0
    release_kbnode (pkb);
549
0
    err = 0;
550
0
  }
551
552
0
 leave:
553
0
  xfree (frame);
554
0
  xfree (keygrip);
555
0
  return err;
556
0
}
557
558
559
/*
560
 * Get the session key from the given string.
561
 * String is supposed to be formatted as this:
562
 *  <algo-id>:<even-number-of-hex-digits>
563
 */
564
gpg_error_t
565
get_override_session_key (DEK *dek, const char *string)
566
0
{
567
0
  const char *s;
568
0
  int i;
569
570
0
  if (!string)
571
0
    return GPG_ERR_BAD_KEY;
572
0
  dek->algo = atoi (string);
573
0
  if (dek->algo < 1)
574
0
    return GPG_ERR_BAD_KEY;
575
0
  if (!(s = strchr (string, ':')))
576
0
    return GPG_ERR_BAD_KEY;
577
0
  s++;
578
0
  for (i = 0; i < DIM (dek->key) && *s; i++, s += 2)
579
0
    {
580
0
      int c = hextobyte (s);
581
0
      if (c == -1)
582
0
        return GPG_ERR_BAD_KEY;
583
0
      dek->key[i] = c;
584
0
    }
585
0
  if (*s)
586
0
    return GPG_ERR_BAD_KEY;
587
0
  dek->keylen = i;
588
0
  return 0;
589
0
}