Coverage Report

Created: 2023-06-08 06:40

/src/openssl111/crypto/dh/dh_key.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
3
 *
4
 * Licensed under the OpenSSL license (the "License").  You may not use
5
 * this file except in compliance with the License.  You can obtain a copy
6
 * in the file LICENSE in the source distribution or at
7
 * https://www.openssl.org/source/license.html
8
 */
9
10
#include <stdio.h>
11
#include "internal/cryptlib.h"
12
#include "dh_local.h"
13
#include "crypto/bn.h"
14
15
static int generate_key(DH *dh);
16
static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh);
17
static int dh_bn_mod_exp(const DH *dh, BIGNUM *r,
18
                         const BIGNUM *a, const BIGNUM *p,
19
                         const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
20
static int dh_init(DH *dh);
21
static int dh_finish(DH *dh);
22
23
int DH_generate_key(DH *dh)
24
0
{
25
0
    return dh->meth->generate_key(dh);
26
0
}
27
28
/*-
29
 * NB: This function is inherently not constant time due to the
30
 * RFC 5246 (8.1.2) padding style that strips leading zero bytes.
31
 */
32
int DH_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
33
0
{
34
0
    int ret = 0, i;
35
0
    volatile size_t npad = 0, mask = 1;
36
37
    /* compute the key; ret is constant unless compute_key is external */
38
0
    if ((ret = dh->meth->compute_key(key, pub_key, dh)) <= 0)
39
0
        return ret;
40
41
    /* count leading zero bytes, yet still touch all bytes */
42
0
    for (i = 0; i < ret; i++) {
43
0
        mask &= !key[i];
44
0
        npad += mask;
45
0
    }
46
47
    /* unpad key */
48
0
    ret -= npad;
49
    /* key-dependent memory access, potentially leaking npad / ret */
50
0
    memmove(key, key + npad, ret);
51
    /* key-dependent memory access, potentially leaking npad / ret */
52
0
    memset(key + ret, 0, npad);
53
54
0
    return ret;
55
0
}
56
57
int DH_compute_key_padded(unsigned char *key, const BIGNUM *pub_key, DH *dh)
58
0
{
59
0
    int rv, pad;
60
61
    /* rv is constant unless compute_key is external */
62
0
    rv = dh->meth->compute_key(key, pub_key, dh);
63
0
    if (rv <= 0)
64
0
        return rv;
65
0
    pad = BN_num_bytes(dh->p) - rv;
66
    /* pad is constant (zero) unless compute_key is external */
67
0
    if (pad > 0) {
68
0
        memmove(key + pad, key, rv);
69
0
        memset(key, 0, pad);
70
0
    }
71
0
    return rv + pad;
72
0
}
73
74
static DH_METHOD dh_ossl = {
75
    "OpenSSL DH Method",
76
    generate_key,
77
    compute_key,
78
    dh_bn_mod_exp,
79
    dh_init,
80
    dh_finish,
81
    DH_FLAG_FIPS_METHOD,
82
    NULL,
83
    NULL
84
};
85
86
static const DH_METHOD *default_DH_method = &dh_ossl;
87
88
const DH_METHOD *DH_OpenSSL(void)
89
0
{
90
0
    return &dh_ossl;
91
0
}
92
93
void DH_set_default_method(const DH_METHOD *meth)
94
0
{
95
0
    default_DH_method = meth;
96
0
}
97
98
const DH_METHOD *DH_get_default_method(void)
99
0
{
100
0
    return default_DH_method;
101
0
}
102
103
static int generate_key(DH *dh)
104
0
{
105
0
    int ok = 0;
106
0
    int generate_new_key = 0;
107
0
    unsigned l;
108
0
    BN_CTX *ctx = NULL;
109
0
    BN_MONT_CTX *mont = NULL;
110
0
    BIGNUM *pub_key = NULL, *priv_key = NULL;
111
112
0
    if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) {
113
0
        DHerr(DH_F_GENERATE_KEY, DH_R_MODULUS_TOO_LARGE);
114
0
        return 0;
115
0
    }
116
117
0
    ctx = BN_CTX_new();
118
0
    if (ctx == NULL)
119
0
        goto err;
120
121
0
    if (dh->priv_key == NULL) {
122
0
        priv_key = BN_secure_new();
123
0
        if (priv_key == NULL)
124
0
            goto err;
125
0
        generate_new_key = 1;
126
0
    } else
127
0
        priv_key = dh->priv_key;
128
129
0
    if (dh->pub_key == NULL) {
130
0
        pub_key = BN_new();
131
0
        if (pub_key == NULL)
132
0
            goto err;
133
0
    } else
134
0
        pub_key = dh->pub_key;
135
136
0
    if (dh->flags & DH_FLAG_CACHE_MONT_P) {
137
0
        mont = BN_MONT_CTX_set_locked(&dh->method_mont_p,
138
0
                                      dh->lock, dh->p, ctx);
139
0
        if (!mont)
140
0
            goto err;
141
0
    }
142
143
0
    if (generate_new_key) {
144
0
        if (dh->q) {
145
0
            do {
146
0
                if (!BN_priv_rand_range(priv_key, dh->q))
147
0
                    goto err;
148
0
            }
149
0
            while (BN_is_zero(priv_key) || BN_is_one(priv_key));
150
0
        } else {
151
            /* secret exponent length */
152
0
            l = dh->length ? dh->length : BN_num_bits(dh->p) - 1;
153
0
            if (!BN_priv_rand(priv_key, l, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY))
154
0
                goto err;
155
            /*
156
             * We handle just one known case where g is a quadratic non-residue:
157
             * for g = 2: p % 8 == 3
158
             */
159
0
            if (BN_is_word(dh->g, DH_GENERATOR_2) && !BN_is_bit_set(dh->p, 2)) {
160
                /* clear bit 0, since it won't be a secret anyway */
161
0
                if (!BN_clear_bit(priv_key, 0))
162
0
                    goto err;
163
0
            }
164
0
        }
165
0
    }
166
167
0
    {
168
0
        BIGNUM *prk = BN_new();
169
170
0
        if (prk == NULL)
171
0
            goto err;
172
0
        BN_with_flags(prk, priv_key, BN_FLG_CONSTTIME);
173
174
0
        if (!dh->meth->bn_mod_exp(dh, pub_key, dh->g, prk, dh->p, ctx, mont)) {
175
0
            BN_clear_free(prk);
176
0
            goto err;
177
0
        }
178
        /* We MUST free prk before any further use of priv_key */
179
0
        BN_clear_free(prk);
180
0
    }
181
182
0
    dh->pub_key = pub_key;
183
0
    dh->priv_key = priv_key;
184
0
    ok = 1;
185
0
 err:
186
0
    if (ok != 1)
187
0
        DHerr(DH_F_GENERATE_KEY, ERR_R_BN_LIB);
188
189
0
    if (pub_key != dh->pub_key)
190
0
        BN_free(pub_key);
191
0
    if (priv_key != dh->priv_key)
192
0
        BN_free(priv_key);
193
0
    BN_CTX_free(ctx);
194
0
    return ok;
195
0
}
196
197
static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
198
0
{
199
0
    BN_CTX *ctx = NULL;
200
0
    BN_MONT_CTX *mont = NULL;
201
0
    BIGNUM *tmp;
202
0
    int ret = -1;
203
0
    int check_result;
204
205
0
    if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) {
206
0
        DHerr(DH_F_COMPUTE_KEY, DH_R_MODULUS_TOO_LARGE);
207
0
        goto err;
208
0
    }
209
210
0
    ctx = BN_CTX_new();
211
0
    if (ctx == NULL)
212
0
        goto err;
213
0
    BN_CTX_start(ctx);
214
0
    tmp = BN_CTX_get(ctx);
215
0
    if (tmp == NULL)
216
0
        goto err;
217
218
0
    if (dh->priv_key == NULL) {
219
0
        DHerr(DH_F_COMPUTE_KEY, DH_R_NO_PRIVATE_VALUE);
220
0
        goto err;
221
0
    }
222
223
0
    if (dh->flags & DH_FLAG_CACHE_MONT_P) {
224
0
        mont = BN_MONT_CTX_set_locked(&dh->method_mont_p,
225
0
                                      dh->lock, dh->p, ctx);
226
0
        BN_set_flags(dh->priv_key, BN_FLG_CONSTTIME);
227
0
        if (!mont)
228
0
            goto err;
229
0
    }
230
231
0
    if (!DH_check_pub_key(dh, pub_key, &check_result) || check_result) {
232
0
        DHerr(DH_F_COMPUTE_KEY, DH_R_INVALID_PUBKEY);
233
0
        goto err;
234
0
    }
235
236
0
    if (!dh->
237
0
        meth->bn_mod_exp(dh, tmp, pub_key, dh->priv_key, dh->p, ctx, mont)) {
238
0
        DHerr(DH_F_COMPUTE_KEY, ERR_R_BN_LIB);
239
0
        goto err;
240
0
    }
241
242
0
    ret = BN_bn2binpad(tmp, key, BN_num_bytes(dh->p));
243
0
 err:
244
0
    BN_CTX_end(ctx);
245
0
    BN_CTX_free(ctx);
246
0
    return ret;
247
0
}
248
249
static int dh_bn_mod_exp(const DH *dh, BIGNUM *r,
250
                         const BIGNUM *a, const BIGNUM *p,
251
                         const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
252
0
{
253
0
    return BN_mod_exp_mont(r, a, p, m, ctx, m_ctx);
254
0
}
255
256
static int dh_init(DH *dh)
257
0
{
258
0
    dh->flags |= DH_FLAG_CACHE_MONT_P;
259
0
    return 1;
260
0
}
261
262
static int dh_finish(DH *dh)
263
0
{
264
0
    BN_MONT_CTX_free(dh->method_mont_p);
265
0
    return 1;
266
0
}