Coverage Report

Created: 2026-02-14 07:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/third_party/heimdal/lib/hcrypto/dh-ltm.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2006 Kungliga Tekniska Högskolan
3
 * (Royal Institute of Technology, Stockholm, Sweden).
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 *
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
12
 *
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 *
17
 * 3. Neither the name of the Institute nor the names of its contributors
18
 *    may be used to endorse or promote products derived from this software
19
 *    without specific prior written permission.
20
 *
21
 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31
 * SUCH DAMAGE.
32
 */
33
34
#ifdef HAVE_CONFIG_H
35
#include <config.h>
36
#endif
37
#include <roken.h>
38
39
#include <dh.h>
40
41
#include "tommath.h"
42
43
static int
44
BN2mpz(mp_int *s, const BIGNUM *bn)
45
0
{
46
0
    size_t len;
47
0
    void *p;
48
49
0
    len = BN_num_bytes(bn);
50
0
    p = malloc(len);
51
0
    BN_bn2bin(bn, p);
52
0
    if (mp_from_ubin(s, p, len) != MP_OKAY) {
53
0
  free(p);
54
0
  return -1;
55
0
    }
56
0
    free(p);
57
0
    return 0;
58
0
}
59
60
61
static BIGNUM *
62
mpz2BN(mp_int *s)
63
0
{
64
0
    size_t size;
65
0
    BIGNUM *bn;
66
0
    void *p;
67
68
0
    size = mp_ubin_size(s);
69
0
    p = malloc(size);
70
0
    if (p == NULL)
71
0
  return NULL;
72
0
    if (mp_to_ubin(s, p, SIZE_MAX, NULL) != MP_OKAY) {
73
0
  free(p);
74
0
  return NULL;
75
0
    };
76
77
0
    bn = BN_bin2bn(p, size, NULL);
78
0
    free(p);
79
0
    return bn;
80
0
}
81
82
/*
83
 *
84
 */
85
86
0
#define DH_NUM_TRIES 10
87
88
static int
89
ltm_dh_generate_key(DH *dh)
90
0
{
91
0
    mp_int pub, priv_key, g, p;
92
0
    int have_private_key = (dh->priv_key != NULL);
93
0
    int codes, times = 0;
94
0
    int res;
95
96
0
    if (dh->p == NULL || dh->g == NULL)
97
0
  return 0;
98
99
0
    while (times++ < DH_NUM_TRIES) {
100
0
  if (!have_private_key) {
101
0
      size_t bits = BN_num_bits(dh->p);
102
103
0
      if (dh->priv_key)
104
0
    BN_free(dh->priv_key);
105
106
0
      dh->priv_key = BN_new();
107
0
      if (dh->priv_key == NULL)
108
0
    return 0;
109
0
      if (!BN_rand(dh->priv_key, bits - 1, 0, 0)) {
110
0
    BN_clear_free(dh->priv_key);
111
0
    dh->priv_key = NULL;
112
0
    return 0;
113
0
      }
114
0
  }
115
0
  if (dh->pub_key) {
116
0
      BN_free(dh->pub_key);
117
0
      dh->pub_key = NULL;
118
0
  }
119
120
0
  if (mp_init_multi(&pub, &priv_key, &g, &p, NULL) != MP_OKAY)
121
0
      continue;
122
123
0
  if (BN2mpz(&priv_key, dh->priv_key) != 0)
124
0
      continue;
125
126
0
  if (BN2mpz(&g, dh->g) != 0)
127
0
      continue;
128
129
0
  if (BN2mpz(&p, dh->p) != 0)
130
0
      continue;
131
132
0
  res = mp_exptmod(&g, &priv_key, &p, &pub);
133
134
0
  mp_clear_multi(&priv_key, &g, &p, NULL);
135
0
  if (res != 0)
136
0
      continue;
137
138
0
  dh->pub_key = mpz2BN(&pub);
139
0
  mp_clear(&pub);
140
0
  if (dh->pub_key == NULL)
141
0
      return 0;
142
143
0
  if (DH_check_pubkey(dh, dh->pub_key, &codes) && codes == 0)
144
0
      break;
145
0
  if (have_private_key)
146
0
      return 0;
147
0
    }
148
149
0
    if (times >= DH_NUM_TRIES) {
150
0
  if (!have_private_key && dh->priv_key) {
151
0
      BN_free(dh->priv_key);
152
0
      dh->priv_key = NULL;
153
0
  }
154
0
  if (dh->pub_key) {
155
0
      BN_free(dh->pub_key);
156
0
      dh->pub_key = NULL;
157
0
  }
158
0
  return 0;
159
0
    }
160
161
0
    return 1;
162
0
}
163
164
static int
165
ltm_dh_compute_key(unsigned char *shared, const BIGNUM * pub, DH *dh)
166
0
{
167
0
    mp_int s, priv_key, p, peer_pub;
168
0
    int ret;
169
170
0
    if (dh->pub_key == NULL || dh->g == NULL || dh->priv_key == NULL)
171
0
  return -1;
172
173
0
    if (mp_init_multi(&s, &priv_key, &p, &peer_pub, NULL) != MP_OKAY)
174
0
        return -1;
175
176
0
    if (BN2mpz(&p, dh->p) != 0) {
177
0
  ret = -1;
178
0
  goto out;
179
0
    }
180
181
0
    if (BN2mpz(&peer_pub, pub) != 0) {
182
0
  ret = 1;
183
0
  goto out;
184
0
    }
185
186
    /* check if peers pubkey is reasonable */
187
0
    if (mp_isneg(&peer_pub)
188
0
  || mp_cmp(&peer_pub, &p) >= 0
189
0
  || mp_cmp_d(&peer_pub, 1) <= 0)
190
0
    {
191
0
  ret = -1;
192
0
  goto out;
193
0
    }
194
195
0
    if (BN2mpz(&priv_key, dh->priv_key) != 0) {
196
0
  ret = -1;
197
0
  goto out;
198
0
    }
199
200
0
    ret = mp_exptmod(&peer_pub, &priv_key, &p, &s);
201
0
    if (ret != 0) {
202
0
  ret = -1;
203
0
  goto out;
204
0
    }
205
206
0
    ret = mp_ubin_size(&s);
207
0
    if (mp_to_ubin(&s, shared, SIZE_MAX, NULL) != MP_OKAY)
208
0
        ret = -1;
209
210
0
 out:
211
0
    mp_clear_multi(&s, &priv_key, &p, &peer_pub, NULL);
212
213
0
    return ret;
214
0
}
215
216
static int
217
ltm_dh_generate_params(DH *dh, int a, int b, BN_GENCB *callback)
218
0
{
219
    /* groups should already be known, we don't care about this */
220
0
    return 0;
221
0
}
222
223
static int
224
ltm_dh_init(DH *dh)
225
0
{
226
0
    return 1;
227
0
}
228
229
static int
230
ltm_dh_finish(DH *dh)
231
0
{
232
0
    return 1;
233
0
}
234
235
236
/*
237
 *
238
 */
239
240
const DH_METHOD _hc_dh_ltm_method = {
241
    "hcrypto ltm DH",
242
    ltm_dh_generate_key,
243
    ltm_dh_compute_key,
244
    NULL,
245
    ltm_dh_init,
246
    ltm_dh_finish,
247
    0,
248
    NULL,
249
    ltm_dh_generate_params
250
};
251
252
/**
253
 * DH implementation using libtommath.
254
 *
255
 * @return the DH_METHOD for the DH implementation using libtommath.
256
 *
257
 * @ingroup hcrypto_dh
258
 */
259
260
const DH_METHOD *
261
DH_ltm_method(void)
262
0
{
263
0
    return &_hc_dh_ltm_method;
264
0
}