Coverage Report

Created: 2026-01-09 06:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gnupg/g10/ecdh.c
Line
Count
Source
1
/* ecdh.c - ECDH public key operations used in public key glue code
2
 *  Copyright (C) 2010, 2011 Free Software Foundation, Inc.
3
 *
4
 * This file is part of GnuPG.
5
 *
6
 * GnuPG is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * GnuPG is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, see <https://www.gnu.org/licenses/>.
18
 */
19
20
#include <config.h>
21
#include <stdio.h>
22
#include <stdlib.h>
23
#include <string.h>
24
#include <errno.h>
25
26
#include "gpg.h"
27
#include "../common/util.h"
28
#include "pkglue.h"
29
#include "main.h"
30
#include "options.h"
31
32
/* A table with the default KEK parameters used by GnuPG.  */
33
static const struct
34
{
35
  unsigned int qbits;
36
  int openpgp_hash_id;   /* KEK digest algorithm. */
37
  int openpgp_cipher_id; /* KEK cipher algorithm. */
38
} kek_params_table[] =
39
  /* Note: Must be sorted by ascending values for QBITS.  */
40
  {
41
    { 256, DIGEST_ALGO_SHA256, CIPHER_ALGO_AES    },
42
    { 384, DIGEST_ALGO_SHA384, CIPHER_ALGO_AES256 },
43
44
    /* Note: 528 is 521 rounded to the 8 bit boundary */
45
    { 528, DIGEST_ALGO_SHA512, CIPHER_ALGO_AES256 }
46
  };
47
48
49
50
/* Return KEK parameters as an opaque MPI The caller must free the
51
   returned value.  Returns NULL and sets ERRNO on error.  */
52
gcry_mpi_t
53
pk_ecdh_default_params (unsigned int qbits)
54
0
{
55
0
  byte kek_params[4] = {
56
0
    3, /* Number of bytes to follow. */
57
0
    1  /* Version for KDF+AESWRAP.   */
58
0
  };
59
0
  int i;
60
61
  /* Search for matching KEK parameter.  Defaults to the strongest
62
     possible choices.  Performance is not an issue here, only
63
     interoperability.  */
64
0
  for (i=0; i < DIM (kek_params_table); i++)
65
0
    {
66
0
      if (kek_params_table[i].qbits >= qbits
67
0
          || i+1 == DIM (kek_params_table))
68
0
        {
69
0
          kek_params[2] = kek_params_table[i].openpgp_hash_id;
70
0
          kek_params[3] = kek_params_table[i].openpgp_cipher_id;
71
0
          break;
72
0
        }
73
0
    }
74
0
  log_assert (i < DIM (kek_params_table));
75
0
  if (DBG_CRYPTO)
76
0
    log_printhex (kek_params, sizeof(kek_params), "ECDH KEK params are");
77
78
0
  return gcry_mpi_set_opaque_copy (NULL, kek_params, 4 * 8);
79
0
}
80
81
82
/* Build KDF parameters */
83
/* RFC 6637 defines the KDF parameters and its encoding in Section
84
   8. EC DH Algorighm (ECDH).  Since it was written for v4 key, it
85
   said "20 octets representing a recipient encryption subkey or a
86
   master key fingerprint".  For v5 key, it is considered "adequate"
87
   (in terms of NIST SP 800 56A, see 5.8.2 FixedInfo) to use the first
88
   20 octets of its 32 octets fingerprint.  */
89
gpg_error_t
90
ecc_build_kdf_params (unsigned char **r_kdf_params, size_t *r_len,
91
                      const unsigned char **r_kdf_params_spec,
92
                      gcry_mpi_t *pkey, const byte fp[MAX_FINGERPRINT_LEN])
93
0
{
94
0
  const unsigned char *oid;
95
0
  const unsigned char *kdf_params_spec;
96
0
  unsigned int nbits;
97
0
  size_t oid_len;
98
0
  size_t len;
99
0
  unsigned char *kdf_params = NULL;
100
0
  int kdf_params_len = 0;
101
102
0
  if (!gcry_mpi_get_flag (pkey[0], GCRYMPI_FLAG_OPAQUE))
103
0
    return gpg_error (GPG_ERR_BAD_PUBKEY);
104
105
0
  oid = gcry_mpi_get_opaque (pkey[0], &nbits);
106
0
  oid_len = (nbits+7)/8;
107
108
  /* In the public key part, there is a specifier of KDF parameters
109
     (namely, hash algo for KDF and symmetric algo for wrapping key).
110
     Using this specifier (together with curve OID of the public key
111
     and the fingerprint), we build _the_ KDF parameters.  */
112
0
  if (!gcry_mpi_get_flag (pkey[2], GCRYMPI_FLAG_OPAQUE))
113
0
    return gpg_error (GPG_ERR_BAD_PUBKEY);
114
115
0
  kdf_params_spec = gcry_mpi_get_opaque (pkey[2], &nbits);
116
0
  len = (nbits+7)/8;
117
118
  /* Expect 4 bytes  03 01 hash_alg symm_alg.  */
119
0
  if (len != 4 || kdf_params_spec[0] != 3 || kdf_params_spec[1] != 1)
120
0
    return gpg_error (GPG_ERR_BAD_PUBKEY);
121
122
0
  kdf_params_len = oid_len + 1 + 4 + 20 + 20;
123
0
  kdf_params = xtrymalloc (kdf_params_len);
124
0
  if (!kdf_params)
125
0
    return gpg_error_from_syserror ();
126
127
0
  memcpy (kdf_params, oid, oid_len);
128
0
  kdf_params[oid_len] = PUBKEY_ALGO_ECDH;
129
0
  memcpy (kdf_params + oid_len + 1, kdf_params_spec, 4);
130
0
  memcpy (kdf_params + oid_len + 1 + 4, "Anonymous Sender    ", 20);
131
0
  memcpy (kdf_params + oid_len + 1 + 4 + 20, fp, 20);
132
133
0
  if (DBG_CRYPTO)
134
0
    log_printhex (kdf_params, kdf_params_len,
135
0
                  "ecdh KDF message params are:");
136
137
0
  *r_kdf_params = kdf_params;
138
0
  *r_len = kdf_params_len;
139
0
  if (r_kdf_params_spec)
140
0
    *r_kdf_params_spec = kdf_params_spec;
141
0
  return 0;
142
0
}